Libnl-3 Includes Broken

libnl-3 includes broken?

OK, so the package is not broken, I am ;)

A short while ago, they introduced a mechanism to enable users to install different versions of this library.
Now you can configure it using "pkg-config" or just pass the precise directory to the compiler with "-I /usr/include/libnl3/".
And it works.

configure: error: libnl and libnl-genl are required but were not found

I "solved" my problem by installing powertop-2.0 instead.

libnl 3 (netlink library) undefined reference to nl* and genl*

Libraries you link in, the -lnl-genl-3 -lnl-3 arguments, must come after the code that uses it on the command line.

Which in your case can easiest be done with e.g. :

 gcc scan_access_points.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0) 

Adding route with libnl-3-route Invalid input data or parameter

The problem come from the bad use of function nl_addr_build.

Replace by nl_addr_parse() and that's working.

nl_addr_build : Parse a binary addr

nl_addr_parse : Parse a char* addr like "10.10.1.10"

How to send multipart messages using libnl and generic netlink?

How to use the multipart mechanism of generic netlink to broke this string in smaller parts to send and reassemble it on the Kernel side?

Netlink's Multipart feature "might" help you transmit an already fragmented string, but it won't help you with the actual string fragmentation operation. That's your job. Multipart is a means to transmit several small correlated objects through several packets, not one big object. In general, Netlink as a whole is designed with the assumption that any atomic piece of data you want to send will fit in a single packet. I would agree with the notion that 6Kbs worth of string is a bit of an oddball.

In actuality, Multipart is a rather ill-defined gimmic in my opinion. The problem is that the kernel doesn't actually handle it in any generic capacity; if you look at all the NLMSG_DONE usage instances, you will notice not only that it is very rarely read (most of them are writes), but also, it's not the Netlink code but rather some specific protocol doing it for some static (ie. private) operation. In other words, the semantics of NLMSG_DONE are given by you, not by the kernel. Linux will not save you any work if you choose to use it.

On the other hand, libnl-genl-3 does appear to perform some automatic juggling with the Multipart flags (NLMSG_DONE and NLM_F_MULTI), but that only applies when you're sending something from Kernelspace to Userspace, and on top of that, even the library itself admits that it doesn't really work.

Also, NLMSG_DONE is supposed to be placed in the "type" Netlink header field, not in the "flags" field. This is baffling to me, because Generic Netlink stores the family identifier in type, so it doesn't look like there's a way to simultaneously tell Netlink that the message belongs to you, AND that it's supposed to end some data stream. Unless I'm missing something important, Multipart and Generic Netlink are incompatible with each other.

I would therefore recommend implementing your own message control if necessary and forget about Multipart.

What's the maximum string size supported by generic netlink and libnl nla_put_string function?

It's not a constant. nlmsg_alloc() reserves
getpagesize() bytes per packet by default. You can tweak this default with nlmsg_set_default_size(), or more to the point you can override it with nlmsg_alloc_size().

Then you'd have to query the actual allocated size (because it's not guaranteed to be what you requested) and build from there. To get the available payload you'd have to subtract the Netlink header length, the Generic Header length and the Attribute Header lengths for any attributes you want to add. Also the user header length, if you have one. You would also have to align all these components because their sizeof is not necessarily their actual size (example).

All that said, the kernel will still reject packets which exceed the page size, so even if you specify a custom size you will still need to fragment your string.

So really, just forget all of the above. Just fragment the string to something like getpagesize() / 2 or whatever, and send it in separate chunks.

This is the general idea:

static void do_request(struct nl_sock *sk, int fam, char const *string)
{
struct nl_msg *msg;

msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, fam,
0, 0, DOC_EXMPL_C_ECHO, 1);
nla_put_string(msg, DOC_EXMPL_A_MSG, string);
nl_send_auto(sk, msg);
nlmsg_free(msg);
}

int main(int argc, char **argv)
{
struct nl_sock *sk;
int fam;

sk = nl_socket_alloc();
genl_connect(sk);
fam = genl_ctrl_resolve(sk, FAMILY_NAME);

do_request(sk, fam, "I'm sending a string.");
do_request(sk, fam, "Let's pretend I'm biiiiiig.");
do_request(sk, fam, "Look at me, I'm so big.");
do_request(sk, fam, "But I'm already fragmented, so it's ok.");

nl_close(sk);
nl_socket_free(sk);

return 0;
}

I left a full sandbox in my Dropbox. See the README. (Tested in kernel 5.4.0-37-generic.)

error: ‘nl_socket_alloc’ was not declared in this scope

Start with the first error and work your way down. Firstly, is the function nl_socket_alloc() declared in any of the header files that you #include? The way to find this out is the grep through those header files (they'll be somewhere on your system), looking for that symbol, and ensuring that the file you find it in is explicitly #include-ed.

Apply this strategy to the other missing symbols.

If you've included the file, the function nl_socket_alloc may be declared in the global namespace, in which case you may choose to refer to it as ::nl_socket_alloc (since you're defining a non-global namespace.

Hope these suggestions point you in the right direction.



Related Topics



Leave a reply



Submit