32 #include <netlink-private/netlink.h>
33 #include <netlink-private/socket.h>
34 #include <netlink/netlink.h>
35 #include <netlink/utils.h>
36 #include <netlink/handlers.h>
37 #include <netlink/msg.h>
38 #include <netlink/attr.h>
42 static void __init init_default_cb(
void)
46 if ((nlcb = getenv(
"NLCB"))) {
47 if (!strcasecmp(nlcb,
"default"))
49 else if (!strcasecmp(nlcb,
"verbose"))
51 else if (!strcasecmp(nlcb,
"debug"))
54 fprintf(stderr,
"Unknown value for NLCB, valid values: "
55 "{default | verbose | debug}\n");
60 static uint32_t used_ports_map[32];
61 static NL_RW_LOCK(port_map_lock);
63 static uint32_t generate_local_port(
void)
66 static uint16_t idx_state = 0;
67 uint32_t pid = getpid() & 0x3FFFFF;
69 nl_write_lock(&port_map_lock);
72 uint32_t t = time(NULL);
76 idx_state = t ^ (t >> 16) ^ 0x3047;
78 idx_state = idx_state + 20011;
82 for (j = 0; j < 32; j++) {
91 i = (((i-1) + 7) % 31) + 1;
93 if (used_ports_map[i] == 0xFFFFFFFF)
96 for (m = 0; m < 32; m++) {
98 if (1UL & (used_ports_map[i] >> n))
101 used_ports_map[i] |= (1UL << n);
107 nl_write_unlock(&port_map_lock);
109 return pid + (((uint32_t)n) << 22);
113 nl_write_unlock(&port_map_lock);
116 NL_DBG(1,
"Warning: Ran out of unique local port namespace\n");
120 static void release_local_port(uint32_t port)
125 if (port == UINT32_MAX)
131 mask = 1UL << (nr % 32);
134 nl_write_lock(&port_map_lock);
135 BUG_ON((used_ports_map[nr] & mask) != mask);
136 used_ports_map[nr] &= ~mask;
137 nl_write_unlock(&port_map_lock);
141 void _nl_socket_used_ports_release_all(
const uint32_t *used_ports)
145 for (i = 0; i < 32; i++) {
146 if (used_ports[i] != 0) {
147 nl_write_lock(&port_map_lock);
148 for (; i < 32; i++) {
149 BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
150 used_ports_map[i] &= ~(used_ports[i]);
152 nl_write_unlock(&port_map_lock);
158 void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
164 mask = 1UL << (nr % 32);
172 used_ports[nr] |= mask;
181 static struct nl_sock *__alloc_socket(
struct nl_cb *cb)
185 sk = calloc(1,
sizeof(*sk));
190 sk->s_cb = nl_cb_get(cb);
191 sk->s_local.nl_family = AF_NETLINK;
192 sk->s_peer.nl_family = AF_NETLINK;
193 sk->s_seq_expect = sk->s_seq_next = time(0);
196 sk->s_flags = NL_OWN_PORT;
216 sk = __alloc_socket(cb);
237 return __alloc_socket(cb);
252 if (!(sk->s_flags & NL_OWN_PORT))
253 release_local_port(sk->s_local.nl_pid);
266 static int noop_seq_check(
struct nl_msg *msg,
void *arg)
300 return sk->s_seq_next++;
317 sk->s_flags |= NL_NO_AUTO_ACK;
327 sk->s_flags &= ~NL_NO_AUTO_ACK;
333 int _nl_socket_is_local_port_unspecified(
struct nl_sock *sk)
335 return (sk->s_local.nl_pid == 0);
338 uint32_t _nl_socket_generate_local_port_no_release(
struct nl_sock *sk)
345 port = generate_local_port();
346 sk->s_flags &= ~NL_OWN_PORT;
347 sk->s_local.nl_pid = port;
357 uint32_t nl_socket_get_local_port(
const struct nl_sock *sk)
359 if (sk->s_local.nl_pid == 0) {
369 return _nl_socket_generate_local_port_no_release((
struct nl_sock *) sk);
371 return sk->s_local.nl_pid;
388 if (!(sk->s_flags & NL_OWN_PORT))
389 release_local_port(sk->s_local.nl_pid);
390 sk->s_flags |= NL_OWN_PORT;
391 sk->s_local.nl_pid = port;
423 return -NLE_BAD_SOCK;
433 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
434 &group,
sizeof(group));
437 return -nl_syserr2nlerr(errno);
440 group = va_arg(ap,
int);
448 int nl_socket_add_membership(
struct nl_sock *sk,
int group)
471 return -NLE_BAD_SOCK;
481 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
482 &group,
sizeof(group));
485 return -nl_syserr2nlerr(errno);
488 group = va_arg(ap,
int);
496 int nl_socket_drop_membership(
struct nl_sock *sk,
int group)
513 sk->s_local.nl_groups |= groups;
524 uint32_t nl_socket_get_peer_port(
const struct nl_sock *sk)
526 return sk->s_peer.nl_pid;
529 void nl_socket_set_peer_port(
struct nl_sock *sk, uint32_t port)
531 sk->s_peer.nl_pid = port;
534 uint32_t nl_socket_get_peer_groups(
const struct nl_sock *sk)
536 return sk->s_peer.nl_groups;
539 void nl_socket_set_peer_groups(
struct nl_sock *sk, uint32_t groups)
541 sk->s_peer.nl_groups = groups;
576 return -NLE_BAD_SOCK;
578 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
579 return -nl_syserr2nlerr(errno);
590 sk->s_flags |= NL_MSG_PEEK;
599 sk->s_flags &= ~NL_MSG_PEEK;
609 struct nl_cb *nl_socket_get_cb(
const struct nl_sock *sk)
611 return nl_cb_get(sk->s_cb);
614 void nl_socket_set_cb(
struct nl_sock *sk,
struct nl_cb *cb)
620 sk->s_cb = nl_cb_get(cb);
637 return nl_cb_set(sk->s_cb, type, kind, func, arg);
652 return nl_cb_err(sk->s_cb, kind, func, arg);
686 return -NLE_BAD_SOCK;
688 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
689 &txbuf,
sizeof(txbuf));
691 return -nl_syserr2nlerr(errno);
693 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
694 &rxbuf,
sizeof(rxbuf));
696 return -nl_syserr2nlerr(errno);
698 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
717 sk->s_bufsize = bufsize;
730 return sk->s_bufsize;
745 return -NLE_BAD_SOCK;
747 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
748 &state,
sizeof(state));
750 return -nl_syserr2nlerr(errno);
753 sk->s_flags |= NL_SOCK_PASSCRED;
755 sk->s_flags &= ~NL_SOCK_PASSCRED;
772 return -NLE_BAD_SOCK;
774 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
775 &state,
sizeof(state));
777 return -nl_syserr2nlerr(errno);
int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
nl_recvmsgs() callback for error message processing customization
void nl_socket_enable_auto_ack(struct nl_sock *sk)
Enable automatic request for ACK (default)
int nl_socket_set_passcred(struct nl_sock *sk, int state)
Enable/disable credential passing on netlink socket.
int nl_socket_drop_memberships(struct nl_sock *sk, int group,...)
Leave groups.
Customized handler specified by the user.
int nl_socket_get_fd(const struct nl_sock *sk)
Return the file descriptor of the backing socket.
void nl_socket_disable_auto_ack(struct nl_sock *sk)
Disable automatic request for ACK.
void nl_socket_enable_msg_peek(struct nl_sock *sk)
Enable use of MSG_PEEK when reading from socket.
void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
Set local port of socket.
int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void *arg)
Modify the error callback handler associated with the socket.
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.
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Modify the callback handler associated with the socket.
struct nl_sock * nl_socket_alloc_cb(struct nl_cb *cb)
Allocate new socket with custom callbacks.
void nl_socket_disable_seq_check(struct nl_sock *sk)
Disable sequence number checking.
int nl_socket_set_nonblocking(const struct nl_sock *sk)
Set file descriptor of socket to non-blocking state.
void nl_socket_free(struct nl_sock *sk)
Free a netlink socket.
unsigned int nl_socket_use_seq(struct nl_sock *sk)
Use next sequence number.
Debug handlers for debugging.
void nl_socket_disable_msg_peek(struct nl_sock *sk)
Disable use of MSG_PEEK when reading from socket.
Called instead of internal sequence number checking.
Proceed with wathever would come next.
int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
Set default message buffer size of netlink socket.
nl_cb_type
Callback types.
struct nl_cb * nl_cb_alloc(enum nl_cb_kind kind)
Allocate a new callback handle.
int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
Set socket buffer size of netlink socket.
void nl_join_groups(struct nl_sock *sk, int groups)
Join multicast groups (deprecated)
int nl_socket_add_memberships(struct nl_sock *sk, int group,...)
Join groups.
int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
Enable/disable receival of additional packet information.
size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
Get default message buffer size of netlink socket.
int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void *arg)
Set up an error callback.
Verbose default handlers (error messages printed)