92 #include <netlink-local.h>
93 #include <netlink/netlink.h>
94 #include <netlink/utils.h>
95 #include <netlink/handlers.h>
96 #include <netlink/msg.h>
97 #include <netlink/attr.h>
101 static void __init init_default_cb(
void)
105 if ((nlcb = getenv(
"NLCB"))) {
106 if (!strcasecmp(nlcb,
"default"))
108 else if (!strcasecmp(nlcb,
"verbose"))
110 else if (!strcasecmp(nlcb,
"debug"))
113 fprintf(stderr,
"Unknown value for NLCB, valid values: "
114 "{default | verbose | debug}\n");
119 static uint32_t used_ports_map[32];
121 static uint32_t generate_local_port(
void)
124 uint32_t pid = getpid() & 0x3FFFFF;
126 for (i = 0; i < 32; i++) {
127 if (used_ports_map[i] == 0xFFFFFFFF)
130 for (n = 0; n < 32; n++) {
131 if (1UL & (used_ports_map[i] >> n))
134 used_ports_map[i] |= (1UL << n);
139 return pid + (n << 22);
148 static void release_local_port(uint32_t port)
152 if (port == UINT_MAX)
156 used_ports_map[nr / 32] &= ~(1 << nr % 32);
164 static struct nl_handle *__alloc_handle(
struct nl_cb *cb)
166 struct nl_handle *handle;
168 handle = calloc(1,
sizeof(*handle));
176 handle->h_local.nl_family = AF_NETLINK;
177 handle->h_peer.nl_family = AF_NETLINK;
178 handle->h_seq_expect = handle->h_seq_next = time(0);
179 handle->h_local.nl_pid = generate_local_port();
180 if (handle->h_local.nl_pid == UINT_MAX) {
182 nl_error(ENOBUFS,
"Out of local ports");
204 return __alloc_handle(cb);
221 return __alloc_handle(nl_cb_get(cb));
233 if (handle->h_fd >= 0)
236 if (!(handle->h_flags & NL_OWN_PORT))
237 release_local_port(handle->h_local.nl_pid);
239 nl_cb_put(handle->h_cb);
250 static int noop_seq_check(
struct nl_msg *msg,
void *arg)
284 return handle->h_seq_next++;
294 uint32_t nl_socket_get_local_port(
struct nl_handle *handle)
296 return handle->h_local.nl_pid;
310 port = generate_local_port();
311 handle->h_flags &= ~NL_OWN_PORT;
313 if (!(handle->h_flags & NL_OWN_PORT))
314 release_local_port(handle->h_local.nl_pid);
315 handle->h_flags |= NL_OWN_PORT;
318 handle->h_local.nl_pid = port;
347 if (handle->h_fd == -1)
348 return nl_error(EBADFD,
"Socket not connected");
350 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
351 &group,
sizeof(group));
353 return nl_error(errno,
"setsockopt(NETLINK_ADD_MEMBERSHIP) "
374 if (handle->h_fd == -1)
375 return nl_error(EBADFD,
"Socket not connected");
377 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
378 &group,
sizeof(group));
380 return nl_error(errno,
"setsockopt(NETLINK_DROP_MEMBERSHIP) "
397 handle->h_local.nl_groups |= groups;
408 uint32_t nl_socket_get_peer_port(
struct nl_handle *handle)
410 return handle->h_peer.nl_pid;
413 void nl_socket_set_peer_port(
struct nl_handle *handle, uint32_t port)
415 handle->h_peer.nl_pid = port;
425 int nl_socket_get_fd(
struct nl_handle *handle)
438 if (handle->h_fd == -1)
439 return nl_error(EBADFD,
"Socket not connected");
441 if (fcntl(handle->h_fd, F_SETFL, O_NONBLOCK) < 0)
442 return nl_error(errno,
"fcntl(F_SETFL, O_NONBLOCK) failed");
453 handle->h_flags |= NL_MSG_PEEK;
462 handle->h_flags &= ~NL_MSG_PEEK;
472 struct nl_cb *nl_socket_get_cb(
struct nl_handle *handle)
474 return nl_cb_get(handle->h_cb);
477 void nl_socket_set_cb(
struct nl_handle *handle,
struct nl_cb *cb)
479 nl_cb_put(handle->h_cb);
480 handle->h_cb = nl_cb_get(cb);
497 return nl_cb_set(handle->h_cb, type, kind, func, arg);
530 if (handle->h_fd == -1)
531 return nl_error(EBADFD,
"Socket not connected");
533 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_SNDBUF,
534 &txbuf,
sizeof(txbuf));
536 return nl_error(errno,
"setsockopt(SO_SNDBUF) failed");
538 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_RCVBUF,
539 &rxbuf,
sizeof(rxbuf));
541 return nl_error(errno,
"setsockopt(SO_RCVBUF) failed");
543 handle->h_flags |= NL_SOCK_BUFSIZE_SET;
559 if (handle->h_fd == -1)
560 return nl_error(EBADFD,
"Socket not connected");
562 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_PASSCRED,
563 &state,
sizeof(state));
565 return nl_error(errno,
"setsockopt(SO_PASSCRED) failed");
568 handle->h_flags |= NL_SOCK_PASSCRED;
570 handle->h_flags &= ~NL_SOCK_PASSCRED;
586 if (handle->h_fd == -1)
587 return nl_error(EBADFD,
"Socket not connected");
589 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_PKTINFO,
590 &state,
sizeof(state));
592 return nl_error(errno,
"setsockopt(NETLINK_PKTINFO) failed");
void nl_socket_disable_msg_peek(struct nl_handle *handle)
Disable use of MSG_PEEK when reading from socket.
void nl_disable_sequence_check(struct nl_handle *handle)
Disable sequence number checking.
void nl_handle_destroy(struct nl_handle *handle)
Destroy netlink handle.
Customized handler specified by the user.
void nl_join_groups(struct nl_handle *handle, int groups)
Join multicast groups (deprecated)
unsigned int nl_socket_use_seq(struct nl_handle *handle)
Use next sequence number.
int nl_set_passcred(struct nl_handle *handle, int state)
Enable/disable credential passing on netlink handle.
int nl_socket_recv_pktinfo(struct nl_handle *handle, int state)
Enable/disable receival of additional packet information.
int nl_socket_set_nonblocking(struct nl_handle *handle)
Set file descriptor of socket handle to non-blocking state.
nl_cb_kind
Callback kinds.
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
struct nl_handle * nl_handle_alloc(void)
Allocate new netlink socket handle.
int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
Set socket buffer size of netlink handle.
Debug handlers for debugging.
Called instead of internal sequence number checking.
struct nl_handle * nl_handle_alloc_cb(struct nl_cb *cb)
Allocate new socket handle with custom callbacks.
Proceed with wathever would come next.
nl_cb_type
Callback types.
int nl_socket_drop_membership(struct nl_handle *handle, int group)
Leave a group.
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
void nl_socket_set_local_port(struct nl_handle *handle, uint32_t port)
Set local port of socket.
int nl_socket_modify_cb(struct nl_handle *handle, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Modify the callback handler associated to the socket.
void nl_socket_enable_msg_peek(struct nl_handle *handle)
Enable use of MSG_PEEK when reading from socket.
int nl_socket_add_membership(struct nl_handle *handle, int group)
Join a group.
Verbose default handlers (error messages printed)