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);