void CW80211ManagementFrameEvent(struct nl_handle **handleMgmt, cw_sock_handler handler, void * cb, struct WTPBSSInfo * BSSInfo) { //Set file descriptor of socket to non-blocking state nl_socket_set_nonblocking(*handleMgmt); int nlSocketFDmgmt = nl_socket_get_fd(*handleMgmt); CWBool exitThread=CW_FALSE; while(1) { //On delete BSS CWThreadMutexLock(&(BSSInfo->bssMutex)); exitThread = BSSInfo->destroyBSS; CWThreadMutexUnlock(&(BSSInfo->bssMutex)); if(exitThread == CW_TRUE) CWExitThread(); int result; fd_set readset; do { FD_ZERO(&readset); FD_SET(nlSocketFDmgmt, &readset); result = select(nlSocketFDmgmt + 1, &readset, NULL, NULL, NULL); } while (result == -1 && errno == EINTR); if (result > 0) { if (FD_ISSET(nlSocketFDmgmt, &readset)) { handler(cb, (*handleMgmt)); } } else if (result < 0) { CWLog("Error on select(): %s", strerror(errno)); } } }
/** * Allocate new cache manager * @arg sk Netlink socket or NULL to auto allocate * @arg protocol Netlink protocol this manager is used for * @arg flags Flags (\c NL_AUTO_PROVIDE) * @arg result Result pointer * * Allocates a new cache manager for the specified netlink protocol. * * 1. If sk is not specified (\c NULL) a netlink socket matching the * specified protocol will be automatically allocated. * * 2. The socket will be put in non-blocking mode and sequence checking * will be disabled regardless of whether the socket was provided by * the caller or automatically allocated. * * 3. The socket will be connected. * * If the flag \c NL_AUTO_PROVIDE is specified, any cache added to the * manager will automatically be made available to other users using * nl_cache_mngt_provide(). * * @note If the socket is provided by the caller, it is NOT recommended * to use the socket for anything else besides receiving netlink * notifications. * * @return 0 on success or a negative error code. */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr **result) { struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; /* Catch abuse of flags */ if (flags & NL_ALLOCATED_SOCK) BUG(); mngr = calloc(1, sizeof(*mngr)); if (!mngr) return -NLE_NOMEM; if (!sk) { if (!(sk = nl_socket_alloc())) goto errout; flags |= NL_ALLOCATED_SOCK; } mngr->cm_sock = sk; mngr->cm_nassocs = NASSOC_INIT; mngr->cm_protocol = protocol; mngr->cm_flags = flags; mngr->cm_assocs = calloc(mngr->cm_nassocs, sizeof(struct nl_cache_assoc)); if (!mngr->cm_assocs) goto errout; /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_sock); if ((err = nl_connect(mngr->cm_sock, protocol)) < 0) goto errout; if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0) goto errout; /* Create and allocate socket for sync cache fills */ mngr->cm_sync_sock = nl_socket_alloc(); if (!mngr->cm_sync_sock) { err = -NLE_NOMEM; goto errout; } if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0) goto errout_free_sync_sock; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); *result = mngr; return 0; errout_free_sync_sock: nl_socket_free(mngr->cm_sync_sock); errout: nl_cache_mngr_free(mngr); return err; }
/** * Allocate new cache manager * @arg sk Netlink socket. * @arg protocol Netlink Protocol this manager is used for * @arg flags Flags * @arg result Result pointer * * @return 0 on success or a negative error code. */ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, struct nl_cache_mngr **result) { struct nl_cache_mngr *mngr; int err = -NLE_NOMEM; if (sk == NULL) BUG(); mngr = calloc(1, sizeof(*mngr)); if (!mngr) goto errout; mngr->cm_handle = sk; mngr->cm_nassocs = 32; mngr->cm_protocol = protocol; mngr->cm_flags = flags; mngr->cm_assocs = calloc(mngr->cm_nassocs, sizeof(struct nl_cache_assoc)); if (!mngr->cm_assocs) goto errout; nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_handle); if ((err = nl_connect(mngr->cm_handle, protocol) < 0)) goto errout; if ((err = nl_socket_set_nonblocking(mngr->cm_handle) < 0)) goto errout; NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", mngr, protocol, mngr->cm_nassocs); *result = mngr; return 0; errout: nl_cache_mngr_free(mngr); return err; }
GWaterNlSource * g_water_nl_source_new_for_sock(GMainContext *context, struct nl_sock *sock) { g_return_val_if_fail(sock != NULL, NULL); GSource *source; GWaterNlSource *self; source = g_source_new(&_g_water_nl_source_funcs, sizeof(GWaterNlSource)); self = (GWaterNlSource *)source; self->sock = sock; nl_socket_set_nonblocking(self->sock); self->fd = g_source_add_unix_fd(source, nl_socket_get_fd(self->sock), G_IO_IN | G_IO_ERR | G_IO_HUP); g_source_attach(source, context); return self; }
/* Set netlink socket channel as non-blocking */ static int netlink_set_nonblock(nl_handle_t *nl, int *flags) { #ifdef _HAVE_LIBNL3_ int ret; if ((ret = nl_socket_set_nonblocking(nl->sk)) < 0 ) { log_message(LOG_INFO, "Netlink: Cannot set nonblocking : (%s)", strerror(ret)); return -1; } #else *flags |= O_NONBLOCK; if (fcntl(nl->fd, F_SETFL, *flags) < 0) { log_message(LOG_INFO, "Netlink: Cannot F_SETFL socket : (%s)", strerror(errno)); return -1; } #endif return 0; }
static ni_socket_t * __ni_rtevent_sock_open(void) { unsigned int recv_buff_len = __ni_rtevent_config_recv_buff_len(); unsigned int mesg_buff_len = __ni_rtevent_config_mesg_buff_len(); ni_rtevent_handle_t *handle; ni_socket_t *sock; int fd, ret; if (!(handle = __ni_rtevent_handle_new())) { ni_error("Unable to allocate rtnetlink event handle: %m"); return NULL; } if (!(handle->nlsock = nl_socket_alloc())) { ni_error("Cannot allocate rtnetlink event socket: %m"); __ni_rtevent_handle_free(handle); return NULL; } /* * Modify the callback for processing valid messages... * We may pass some kind of data (event filter?) too... */ nl_socket_modify_cb(handle->nlsock, NL_CB_VALID, NL_CB_CUSTOM, __ni_rtevent_process_cb, NULL); /* Required to receive async event notifications */ nl_socket_disable_seq_check(handle->nlsock); if ((ret = nl_connect(handle->nlsock, NETLINK_ROUTE)) < 0) { ni_error("Cannot open rtnetlink: %s", nl_geterror(ret)); __ni_rtevent_handle_free(handle); return NULL; } /* Enable non-blocking processing */ nl_socket_set_nonblocking(handle->nlsock); fd = nl_socket_get_fd(handle->nlsock); if (!(sock = ni_socket_wrap(fd, SOCK_DGRAM))) { ni_error("Cannot wrap rtnetlink event socket: %m"); __ni_rtevent_handle_free(handle); return NULL; } if (recv_buff_len) { if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, (char *)&recv_buff_len, sizeof(recv_buff_len)) && setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buff_len, sizeof(recv_buff_len))) { ni_warn("Unable to set netlink event receive buffer to %u bytes: %m", recv_buff_len); } else { ni_info("Using netlink event receive buffer of %u bytes", recv_buff_len); } } if (mesg_buff_len) { if (nl_socket_set_msg_buf_size(handle->nlsock, mesg_buff_len)) { ni_warn("Unable to set netlink event message buffer to %u bytes", mesg_buff_len); } else { ni_info("Using netlink event message buffer of %u bytes", mesg_buff_len); } } sock->user_data = handle; sock->receive = __ni_rtevent_receive; sock->close = __ni_rtevent_close; sock->handle_error = __ni_rtevent_sock_error_handler; sock->release_user_data = __ni_rtevent_sock_release_data; return sock; }
/** * virNetlinkEventServiceStart: * * start a monitor to receive netlink messages for libvirtd. * This registers a netlink socket with the event interface. * * Returns -1 if the monitor cannot be registered, 0 upon success */ int virNetlinkEventServiceStart(void) { virNetlinkEventSrvPrivatePtr srv; int fd; int ret = -1; if (server) return 0; VIR_INFO("starting netlink event service"); if (VIR_ALLOC(srv) < 0) { virReportOOMError(); return -1; } if (virMutexInit(&srv->lock) < 0) { VIR_FREE(srv); return -1; } virNetlinkEventServerLock(srv); /* Allocate a new socket and get fd */ srv->netlinknh = virNetlinkAlloc(); if (!srv->netlinknh) { virReportSystemError(errno, "%s", _("cannot allocate nlhandle for virNetlinkEvent server")); goto error_locked; } if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) { virReportSystemError(errno, "%s", _("cannot connect to netlink socket")); goto error_server; } fd = nl_socket_get_fd(srv->netlinknh); if (fd < 0) { virReportSystemError(errno, "%s", _("cannot get netlink socket fd")); goto error_server; } if (nl_socket_set_nonblocking(srv->netlinknh)) { virReportSystemError(errno, "%s", _("cannot set netlink socket nonblocking")); goto error_server; } if ((srv->eventwatch = virEventAddHandle(fd, VIR_EVENT_HANDLE_READABLE, virNetlinkEventCallback, srv, NULL)) < 0) { netlinkError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to add netlink event handle watch")); goto error_server; } srv->netlinkfd = fd; VIR_DEBUG("netlink event listener on fd: %i running", fd); ret = 0; server = srv; error_server: if (ret < 0) { nl_close(srv->netlinknh); virNetlinkFree(srv->netlinknh); } error_locked: virNetlinkEventServerUnlock(srv); if (ret < 0) { virMutexDestroy(&srv->lock); VIR_FREE(srv); } return ret; }
/** * virNetlinkEventServiceStart: * * start a monitor to receive netlink messages for libvirtd. * This registers a netlink socket with the event interface. * * @protocol: netlink protocol * @groups: broadcast groups to join in * Returns -1 if the monitor cannot be registered, 0 upon success */ int virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups) { virNetlinkEventSrvPrivatePtr srv; int fd; int ret = -1; if (protocol >= MAX_LINKS) { virReportSystemError(EINVAL, _("invalid protocol argument: %d"), protocol); return -EINVAL; } if (server[protocol]) return 0; VIR_INFO("starting netlink event service with protocol %d", protocol); if (VIR_ALLOC(srv) < 0) return -1; if (virMutexInit(&srv->lock) < 0) { VIR_FREE(srv); return -1; } virNetlinkEventServerLock(srv); /* Allocate a new socket and get fd */ if (!(srv->netlinknh = virNetlinkCreateSocket(protocol))) goto error_locked; fd = nl_socket_get_fd(srv->netlinknh); if (fd < 0) { virReportSystemError(errno, "%s", _("cannot get netlink socket fd")); goto error_server; } if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) { virReportSystemError(errno, "%s", _("cannot add netlink membership")); goto error_server; } if (nl_socket_set_nonblocking(srv->netlinknh)) { virReportSystemError(errno, "%s", _("cannot set netlink socket nonblocking")); goto error_server; } if ((srv->eventwatch = virEventAddHandle(fd, VIR_EVENT_HANDLE_READABLE, virNetlinkEventCallback, srv, NULL)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to add netlink event handle watch")); goto error_server; } srv->netlinkfd = fd; VIR_DEBUG("netlink event listener on fd: %i running", fd); ret = 0; server[protocol] = srv; error_server: if (ret < 0) { nl_close(srv->netlinknh); virNetlinkFree(srv->netlinknh); } error_locked: virNetlinkEventServerUnlock(srv); if (ret < 0) { virMutexDestroy(&srv->lock); VIR_FREE(srv); } return ret; }
void ind_ovs_port_added(uint32_t port_no, const char *ifname, of_mac_addr_t mac_addr) { indigo_error_t err; if (ind_ovs_ports[port_no]) { return; } struct ind_ovs_port *port = calloc(1, sizeof(*port)); if (port == NULL) { LOG_ERROR("failed to allocate port"); return; } strncpy(port->ifname, ifname, sizeof(port->ifname)); port->dp_port_no = port_no; port->mac_addr = mac_addr; aim_ratelimiter_init(&port->upcall_log_limiter, 1000*1000, 5, NULL); aim_ratelimiter_init(&port->pktin_limiter, PORT_PKTIN_INTERVAL, PORT_PKTIN_BURST_SIZE, NULL); pthread_mutex_init(&port->quiesce_lock, NULL); pthread_cond_init(&port->quiesce_cvar, NULL); port->notify_socket = ind_ovs_create_nlsock(); if (port->notify_socket == NULL) { goto cleanup_port; } if (nl_socket_set_nonblocking(port->notify_socket) < 0) { LOG_ERROR("failed to set netlink socket nonblocking"); goto cleanup_port; } struct nl_msg *msg = ind_ovs_create_nlmsg(ovs_vport_family, OVS_VPORT_CMD_SET); nla_put_u32(msg, OVS_VPORT_ATTR_PORT_NO, port_no); nla_put_u32(msg, OVS_VPORT_ATTR_UPCALL_PID, nl_socket_get_local_port(port->notify_socket)); err = ind_ovs_transact(msg); if (err < 0) { LOG_ERROR("datapath failed to configure port %s", ifname); goto cleanup_port; } if (!ind_ovs_get_interface_flags(ifname, &port->ifflags)) { /* Bring interface up if not already */ if (!(port->ifflags & IFF_UP)) { port->ifflags |= IFF_UP; (void) ind_ovs_set_interface_flags(ifname, port->ifflags); } } else { /* Not a netdev, fake the interface flags */ port->ifflags = IFF_UP; } /* Ensure port is fully populated before publishing it. */ __sync_synchronize(); ind_ovs_ports[port_no] = port; if ((err = port_status_notify(port_no, OF_PORT_CHANGE_REASON_ADD)) < 0) { LOG_WARN("failed to notify controller of port addition"); /* Can't cleanup the port because it's already visible to other * threads. */ } ind_ovs_upcall_register(port); LOG_INFO("Added port %s", port->ifname); ind_ovs_kflow_invalidate_all(); return; cleanup_port: assert(ind_ovs_ports[port_no] == NULL); if (port->notify_socket) { nl_socket_free(port->notify_socket); } free(port); }
/* Create a socket to netlink interface_t */ static int netlink_socket(nl_handle_t *nl, int flags, int group, ...) { int ret; va_list gp; memset(nl, 0, sizeof (*nl)); #ifdef _HAVE_LIBNL3_ /* We need to keep libnl3 in step with our netlink socket creation. */ nl->sk = nl_socket_alloc(); if ( nl->sk == NULL ) { log_message(LOG_INFO, "Netlink: Cannot allocate netlink socket" ); return -1; } ret = nl_connect(nl->sk, NETLINK_ROUTE); if (ret != 0) { log_message(LOG_INFO, "Netlink: Cannot open netlink socket : (%d)", ret); return -1; } /* Unfortunately we can't call nl_socket_add_memberships() with variadic arguments * from a variadic argument list passed to us */ va_start(gp, group); while (group != 0) { if (group < 0) { va_end(gp); return -1; } if ((ret = nl_socket_add_membership(nl->sk, group))) { log_message(LOG_INFO, "Netlink: Cannot add socket membership 0x%x : (%d)", group, ret); return -1; } group = va_arg(gp,int); } va_end(gp); if (flags & SOCK_NONBLOCK) { if ((ret = nl_socket_set_nonblocking(nl->sk))) { log_message(LOG_INFO, "Netlink: Cannot set netlink socket non-blocking : (%d)", ret); return -1; } } if ((ret = nl_socket_set_buffer_size(nl->sk, IF_DEFAULT_BUFSIZE, 0))) { log_message(LOG_INFO, "Netlink: Cannot set netlink buffer size : (%d)", ret); return -1; } nl->nl_pid = nl_socket_get_local_port(nl->sk); nl->fd = nl_socket_get_fd(nl->sk); /* Set CLOEXEC */ fcntl(nl->fd, F_SETFD, fcntl(nl->fd, F_GETFD) | FD_CLOEXEC); #else socklen_t addr_len; struct sockaddr_nl snl; #if !HAVE_DECL_SOCK_NONBLOCK int sock_flags = flags; flags &= ~SOCK_NONBLOCK; #endif nl->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC | flags, NETLINK_ROUTE); if (nl->fd < 0) { log_message(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)", strerror(errno)); return -1; } #if !HAVE_DECL_SOCK_NONBLOCK if ((sock_flags & SOCK_NONBLOCK) && set_sock_flags(nl->fd, F_SETFL, O_NONBLOCK)) return -1; #endif memset(&snl, 0, sizeof (snl)); snl.nl_family = AF_NETLINK; ret = bind(nl->fd, (struct sockaddr *) &snl, sizeof (snl)); if (ret < 0) { log_message(LOG_INFO, "Netlink: Cannot bind netlink socket : (%s)", strerror(errno)); close(nl->fd); return -1; } /* Join the requested groups */ va_start(gp, group); while (group != 0) { if (group < 0) { va_end(gp); return -1; } ret = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); if (ret < 0) { log_message(LOG_INFO, "Netlink: Cannot add membership on netlink socket : (%s)", strerror(errno)); va_end(gp); return -1; } group = va_arg(gp,int); } va_end(gp); addr_len = sizeof (snl); ret = getsockname(nl->fd, (struct sockaddr *) &snl, &addr_len); if (ret < 0 || addr_len != sizeof (snl)) { log_message(LOG_INFO, "Netlink: Cannot getsockname : (%s)", strerror(errno)); close(nl->fd); return -1; } if (snl.nl_family != AF_NETLINK) { log_message(LOG_INFO, "Netlink: Wrong address family %d", snl.nl_family); close(nl->fd); return -1; } /* Save the port id for checking message source later */ nl->nl_pid = snl.nl_pid; /* Set default rcvbuf size */ if_setsockopt_rcvbuf(&nl->fd, IF_DEFAULT_BUFSIZE); #endif nl->seq = (uint32_t)time(NULL); if (nl->fd < 0) return -1; return ret; }
int netlink_wrapper::open_channel() { auto_unlocker lock(m_cache_lock); nl_logdbg("opening netlink channel"); /* // build to subscriptions groups mask for indicating what type of events the kernel will send on channel unsigned subscriptions = ~RTMGRP_TC; if (netlink_route_group_mask & nlgrpLINK) { subscriptions |= (1 << (RTNLGRP_LINK - 1)); } if (netlink_route_group_mask & nlgrpADDRESS) { if (!m_preferred_family || m_preferred_family == AF_INET) subscriptions |= (1 << (RTNLGRP_IPV4_IFADDR - 1)); if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV6_IFADDR - 1)); } if (netlink_route_group_mask & nlgrpROUTE) { if (!m_preferred_family || m_preferred_family == AF_INET) subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1)); if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1)); } if (netlink_route_group_mask & nlgrpPREFIX) { if (!m_preferred_family || m_preferred_family == AF_INET6) subscriptions |= (1 << (RTNLGRP_IPV6_PREFIX - 1)); } if (netlink_route_group_mask & nlgrpNEIGH) { subscriptions |= (1 << (RTNLGRP_NEIGH - 1)); } */ // Allocate a new netlink handle m_handle = nl_handle_alloc(); BULLSEYE_EXCLUDE_BLOCK_START if (m_handle == NULL) { nl_logerr("failed to allocate netlink handle, nl_errno=%d", nl_get_errno()); return -1; } BULLSEYE_EXCLUDE_BLOCK_END // set internal structure to pass the handle with callbacks from netlink g_nl_rcv_arg.handle = m_handle; // if multiple handles being allocated then a unique netlink PID need to be provided // If port is 0, a unique port identifier will be generated automatically as a unique PID nl_socket_set_local_port(m_handle, 0); //Disables checking of sequence numbers on the netlink handle. //This is required to allow messages to be processed which were not requested by a preceding request message, e.g. netlink events. nl_disable_sequence_check(m_handle); //joining group //nl_join_groups(m_handle, 0); // Allocate a new cache manager for RTNETLINK // NL_AUTO_PROVIDE = automatically provide the caches added to the manager. m_mngr = nl_cache_mngr_alloc(m_handle, NETLINK_ROUTE, NL_AUTO_PROVIDE); BULLSEYE_EXCLUDE_BLOCK_START if (!m_mngr) { nl_logerr("Fail to allocate cac he manager"); return -1; } BULLSEYE_EXCLUDE_BLOCK_END nl_logdbg("netlink socket is open"); m_cache_neigh = nl_cache_mngr_add(m_mngr, "route/neigh", neigh_cache_callback); m_cache_link = nl_cache_mngr_add(m_mngr, "route/link", link_cache_callback); m_cache_route = nl_cache_mngr_add(m_mngr, "route/route", route_cache_callback); // set custom callback for every message to update message nl_socket_modify_cb(m_handle, NL_CB_MSG_IN, NL_CB_CUSTOM, nl_msg_rcv_cb ,NULL); // set the socket non-blocking BULLSEYE_EXCLUDE_BLOCK_START if (nl_socket_set_nonblocking(m_handle)) { nl_logerr("Failed to set the socket non-blocking"); return -1; } BULLSEYE_EXCLUDE_BLOCK_END return 0; }