32 #include <netlink-private/netlink.h>
33 #include <netlink/netlink.h>
34 #include <netlink/utils.h>
35 #include <netlink/handlers.h>
36 #include <netlink/msg.h>
37 #include <netlink/attr.h>
41 static void __init init_default_cb(
void)
45 if ((nlcb = getenv(
"NLCB"))) {
46 if (!strcasecmp(nlcb,
"default"))
48 else if (!strcasecmp(nlcb,
"verbose"))
50 else if (!strcasecmp(nlcb,
"debug"))
53 fprintf(stderr,
"Unknown value for NLCB, valid values: "
54 "{default | verbose | debug}\n");
59 static uint32_t used_ports_map[32];
60 static NL_RW_LOCK(port_map_lock);
62 static uint32_t generate_local_port(
void)
65 uint32_t pid = getpid() & 0x3FFFFF;
67 nl_write_lock(&port_map_lock);
69 for (i = 0; i < 32; i++) {
70 if (used_ports_map[i] == 0xFFFFFFFF)
73 for (n = 0; n < 32; n++) {
74 if (1UL & (used_ports_map[i] >> n))
77 used_ports_map[i] |= (1UL << n);
83 nl_write_unlock(&port_map_lock);
85 return pid + (n << 22);
89 nl_write_unlock(&port_map_lock);
95 static void release_local_port(uint32_t port)
104 nl_write_lock(&port_map_lock);
105 used_ports_map[nr / 32] &= ~(1 << (nr % 32));
106 nl_write_unlock(&port_map_lock);
114 static struct nl_sock *__alloc_socket(
struct nl_cb *cb)
118 sk = calloc(1,
sizeof(*sk));
124 sk->s_local.nl_family = AF_NETLINK;
125 sk->s_peer.nl_family = AF_NETLINK;
126 sk->s_seq_expect = sk->s_seq_next = time(0);
127 sk->s_local.nl_pid = generate_local_port();
128 if (sk->s_local.nl_pid == UINT_MAX) {
149 return __alloc_socket(cb);
166 return __alloc_socket(nl_cb_get(cb));
181 if (!(sk->s_flags & NL_OWN_PORT))
182 release_local_port(sk->s_local.nl_pid);
195 static int noop_seq_check(
struct nl_msg *msg,
void *arg)
229 return sk->s_seq_next++;
246 sk->s_flags |= NL_NO_AUTO_ACK;
256 sk->s_flags &= ~NL_NO_AUTO_ACK;
266 uint32_t nl_socket_get_local_port(
const struct nl_sock *sk)
268 return sk->s_local.nl_pid;
282 port = generate_local_port();
287 if (!(sk->s_flags & NL_OWN_PORT))
288 release_local_port(sk->s_local.nl_pid);
290 sk->s_flags &= ~NL_OWN_PORT;
292 if (!(sk->s_flags & NL_OWN_PORT))
293 release_local_port(sk->s_local.nl_pid);
294 sk->s_flags |= NL_OWN_PORT;
297 sk->s_local.nl_pid = port;
329 return -NLE_BAD_SOCK;
339 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
340 &group,
sizeof(group));
343 return -nl_syserr2nlerr(errno);
346 group = va_arg(ap,
int);
354 int nl_socket_add_membership(
struct nl_sock *sk,
int group)
377 return -NLE_BAD_SOCK;
387 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
388 &group,
sizeof(group));
391 return -nl_syserr2nlerr(errno);
394 group = va_arg(ap,
int);
402 int nl_socket_drop_membership(
struct nl_sock *sk,
int group)
419 sk->s_local.nl_groups |= groups;
430 uint32_t nl_socket_get_peer_port(
const struct nl_sock *sk)
432 return sk->s_peer.nl_pid;
435 void nl_socket_set_peer_port(
struct nl_sock *sk, uint32_t port)
437 sk->s_peer.nl_pid = port;
440 uint32_t nl_socket_get_peer_groups(
const struct nl_sock *sk)
442 return sk->s_peer.nl_groups;
445 void nl_socket_set_peer_groups(
struct nl_sock *sk, uint32_t groups)
447 sk->s_peer.nl_groups = groups;
482 return -NLE_BAD_SOCK;
484 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
485 return -nl_syserr2nlerr(errno);
496 sk->s_flags |= NL_MSG_PEEK;
505 sk->s_flags &= ~NL_MSG_PEEK;
515 struct nl_cb *nl_socket_get_cb(
const struct nl_sock *sk)
517 return nl_cb_get(sk->s_cb);
520 void nl_socket_set_cb(
struct nl_sock *sk,
struct nl_cb *cb)
523 sk->s_cb = nl_cb_get(cb);
540 return nl_cb_set(sk->s_cb, type, kind, func, arg);
555 return nl_cb_err(sk->s_cb, kind, func, arg);
589 return -NLE_BAD_SOCK;
591 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
592 &txbuf,
sizeof(txbuf));
594 return -nl_syserr2nlerr(errno);
596 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
597 &rxbuf,
sizeof(rxbuf));
599 return -nl_syserr2nlerr(errno);
601 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
620 sk->s_bufsize = bufsize;
633 return sk->s_bufsize;
648 return -NLE_BAD_SOCK;
650 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
651 &state,
sizeof(state));
653 return -nl_syserr2nlerr(errno);
656 sk->s_flags |= NL_SOCK_PASSCRED;
658 sk->s_flags &= ~NL_SOCK_PASSCRED;
675 return -NLE_BAD_SOCK;
677 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
678 &state,
sizeof(state));
680 return -nl_syserr2nlerr(errno);