94 #include <netlink-local.h>
95 #include <netlink/netlink.h>
96 #include <netlink/utils.h>
97 #include <netlink/handlers.h>
98 #include <netlink/msg.h>
99 #include <netlink/attr.h>
103 static void __init init_default_cb(
void)
107 if ((nlcb = getenv(
"NLCB"))) {
108 if (!strcasecmp(nlcb,
"default"))
110 else if (!strcasecmp(nlcb,
"verbose"))
112 else if (!strcasecmp(nlcb,
"debug"))
115 fprintf(stderr,
"Unknown value for NLCB, valid values: "
116 "{default | verbose | debug}\n");
121 static uint32_t used_ports_map[32];
122 static NL_RW_LOCK(port_map_lock);
124 static uint32_t generate_local_port(
void)
127 uint32_t pid = getpid() & 0x3FFFFF;
129 nl_write_lock(&port_map_lock);
131 for (i = 0; i < 32; i++) {
132 if (used_ports_map[i] == 0xFFFFFFFF)
135 for (n = 0; n < 32; n++) {
136 if (1UL & (used_ports_map[i] >> n))
139 used_ports_map[i] |= (1UL << n);
145 nl_write_unlock(&port_map_lock);
147 return pid + (n << 22);
151 nl_write_unlock(&port_map_lock);
157 static void release_local_port(uint32_t port)
161 if (port == UINT_MAX)
166 nl_write_lock(&port_map_lock);
167 used_ports_map[nr / 32] &= ~(1 << (nr % 32));
168 nl_write_unlock(&port_map_lock);
176 static struct nl_handle *__alloc_handle(
struct nl_cb *cb)
178 struct nl_handle *handle;
180 handle = calloc(1,
sizeof(*handle));
187 handle->h_cb = nl_cb_get(cb);
188 handle->h_local.nl_family = AF_NETLINK;
189 handle->h_peer.nl_family = AF_NETLINK;
190 handle->h_seq_expect = handle->h_seq_next = time(0);
191 handle->h_local.nl_pid = generate_local_port();
192 if (handle->h_local.nl_pid == UINT_MAX) {
194 nl_error(ENOBUFS,
"Out of local ports");
209 struct nl_handle *sk;
218 sk = __alloc_handle(cb);
239 return __alloc_handle(cb);
251 if (handle->h_fd >= 0)
254 if (!(handle->h_flags & NL_OWN_PORT))
255 release_local_port(handle->h_local.nl_pid);
257 nl_cb_put(handle->h_cb);
268 static int noop_seq_check(
struct nl_msg *msg,
void *arg)
302 return handle->h_seq_next++;
312 uint32_t nl_socket_get_local_port(
struct nl_handle *handle)
314 return handle->h_local.nl_pid;
328 port = generate_local_port();
329 handle->h_flags &= ~NL_OWN_PORT;
331 if (!(handle->h_flags & NL_OWN_PORT))
332 release_local_port(handle->h_local.nl_pid);
333 handle->h_flags |= NL_OWN_PORT;
336 handle->h_local.nl_pid = port;
365 if (handle->h_fd == -1)
366 return nl_error(EBADFD,
"Socket not connected");
368 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
369 &group,
sizeof(group));
371 return nl_error(errno,
"setsockopt(NETLINK_ADD_MEMBERSHIP) "
392 if (handle->h_fd == -1)
393 return nl_error(EBADFD,
"Socket not connected");
395 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
396 &group,
sizeof(group));
398 return nl_error(errno,
"setsockopt(NETLINK_DROP_MEMBERSHIP) "
415 handle->h_local.nl_groups |= groups;
426 uint32_t nl_socket_get_peer_port(
struct nl_handle *handle)
428 return handle->h_peer.nl_pid;
431 void nl_socket_set_peer_port(
struct nl_handle *handle, uint32_t port)
433 handle->h_peer.nl_pid = port;
443 int nl_socket_get_fd(
struct nl_handle *handle)
456 if (handle->h_fd == -1)
457 return nl_error(EBADFD,
"Socket not connected");
459 if (fcntl(handle->h_fd, F_SETFL, O_NONBLOCK) < 0)
460 return nl_error(errno,
"fcntl(F_SETFL, O_NONBLOCK) failed");
471 handle->h_flags |= NL_MSG_PEEK;
480 handle->h_flags &= ~NL_MSG_PEEK;
490 struct nl_cb *nl_socket_get_cb(
struct nl_handle *handle)
492 return nl_cb_get(handle->h_cb);
495 void nl_socket_set_cb(
struct nl_handle *handle,
struct nl_cb *cb)
500 nl_cb_put(handle->h_cb);
501 handle->h_cb = nl_cb_get(cb);
518 return nl_cb_set(handle->h_cb, type, kind, func, arg);
551 if (handle->h_fd == -1)
552 return nl_error(EBADFD,
"Socket not connected");
554 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_SNDBUF,
555 &txbuf,
sizeof(txbuf));
557 return nl_error(errno,
"setsockopt(SO_SNDBUF) failed");
559 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_RCVBUF,
560 &rxbuf,
sizeof(rxbuf));
562 return nl_error(errno,
"setsockopt(SO_RCVBUF) failed");
564 handle->h_flags |= NL_SOCK_BUFSIZE_SET;
580 if (handle->h_fd == -1)
581 return nl_error(EBADFD,
"Socket not connected");
583 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_PASSCRED,
584 &state,
sizeof(state));
586 return nl_error(errno,
"setsockopt(SO_PASSCRED) failed");
589 handle->h_flags |= NL_SOCK_PASSCRED;
591 handle->h_flags &= ~NL_SOCK_PASSCRED;
607 if (handle->h_fd == -1)
608 return nl_error(EBADFD,
"Socket not connected");
610 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_PKTINFO,
611 &state,
sizeof(state));
613 return nl_error(errno,
"setsockopt(NETLINK_PKTINFO) failed");