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");
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.
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.
int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg)
nl_recvmsgs() callback for message processing customization
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)