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);
92 NL_DBG(1,
"Warning: Ran out of unique local port namespace\n");
96 static void release_local_port(uint32_t port)
100 if (port == UINT_MAX)
105 nl_write_lock(&port_map_lock);
106 used_ports_map[nr / 32] &= ~(1 << (nr % 32));
107 nl_write_unlock(&port_map_lock);
115 static struct nl_sock *__alloc_socket(
struct nl_cb *cb)
119 sk = calloc(1,
sizeof(*sk));
124 sk->s_cb = nl_cb_get(cb);
125 sk->s_local.nl_family = AF_NETLINK;
126 sk->s_peer.nl_family = AF_NETLINK;
127 sk->s_seq_expect = sk->s_seq_next = time(0);
128 sk->s_local.nl_pid = generate_local_port();
129 if (sk->s_local.nl_pid == UINT_MAX) {
152 sk = __alloc_socket(cb);
173 return __alloc_socket(cb);
188 if (!(sk->s_flags & NL_OWN_PORT))
189 release_local_port(sk->s_local.nl_pid);
202 static int noop_seq_check(
struct nl_msg *msg,
void *arg)
236 return sk->s_seq_next++;
253 sk->s_flags |= NL_NO_AUTO_ACK;
263 sk->s_flags &= ~NL_NO_AUTO_ACK;
273 uint32_t nl_socket_get_local_port(
const struct nl_sock *sk)
275 return sk->s_local.nl_pid;
289 port = generate_local_port();
294 if (!(sk->s_flags & NL_OWN_PORT))
295 release_local_port(sk->s_local.nl_pid);
297 sk->s_flags &= ~NL_OWN_PORT;
299 if (!(sk->s_flags & NL_OWN_PORT))
300 release_local_port(sk->s_local.nl_pid);
301 sk->s_flags |= NL_OWN_PORT;
304 sk->s_local.nl_pid = port;
336 return -NLE_BAD_SOCK;
346 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
347 &group,
sizeof(group));
350 return -nl_syserr2nlerr(errno);
353 group = va_arg(ap,
int);
361 int nl_socket_add_membership(
struct nl_sock *sk,
int group)
384 return -NLE_BAD_SOCK;
394 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
395 &group,
sizeof(group));
398 return -nl_syserr2nlerr(errno);
401 group = va_arg(ap,
int);
409 int nl_socket_drop_membership(
struct nl_sock *sk,
int group)
426 sk->s_local.nl_groups |= groups;
437 uint32_t nl_socket_get_peer_port(
const struct nl_sock *sk)
439 return sk->s_peer.nl_pid;
442 void nl_socket_set_peer_port(
struct nl_sock *sk, uint32_t port)
444 sk->s_peer.nl_pid = port;
447 uint32_t nl_socket_get_peer_groups(
const struct nl_sock *sk)
449 return sk->s_peer.nl_groups;
452 void nl_socket_set_peer_groups(
struct nl_sock *sk, uint32_t groups)
454 sk->s_peer.nl_groups = groups;
489 return -NLE_BAD_SOCK;
491 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
492 return -nl_syserr2nlerr(errno);
503 sk->s_flags |= NL_MSG_PEEK;
512 sk->s_flags &= ~NL_MSG_PEEK;
522 struct nl_cb *nl_socket_get_cb(
const struct nl_sock *sk)
524 return nl_cb_get(sk->s_cb);
527 void nl_socket_set_cb(
struct nl_sock *sk,
struct nl_cb *cb)
533 sk->s_cb = nl_cb_get(cb);
550 return nl_cb_set(sk->s_cb, type, kind, func, arg);
565 return nl_cb_err(sk->s_cb, kind, func, arg);
599 return -NLE_BAD_SOCK;
601 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
602 &txbuf,
sizeof(txbuf));
604 return -nl_syserr2nlerr(errno);
606 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
607 &rxbuf,
sizeof(rxbuf));
609 return -nl_syserr2nlerr(errno);
611 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
630 sk->s_bufsize = bufsize;
643 return sk->s_bufsize;
658 return -NLE_BAD_SOCK;
660 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
661 &state,
sizeof(state));
663 return -nl_syserr2nlerr(errno);
666 sk->s_flags |= NL_SOCK_PASSCRED;
668 sk->s_flags &= ~NL_SOCK_PASSCRED;
685 return -NLE_BAD_SOCK;
687 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
688 &state,
sizeof(state));
690 return -nl_syserr2nlerr(errno);