/* * Print out all Wireless Events part of the RTNetlink message * Most often, there will be only one event per message, but * just make sure we read everything... */ static inline int print_event_stream(int ifindex, char * data, int len) { struct iw_event iwe; struct stream_descr stream; int i = 0; int ret; char buffer[64]; struct timeval recv_time; struct timezone tz; struct wireless_iface * wireless_data; /* Get data from cache */ wireless_data = iw_get_interface_data(ifindex); if(wireless_data == NULL) return(-1); /* Print received time in readable form */ gettimeofday(&recv_time, &tz); iw_print_timeval(buffer, sizeof(buffer), &recv_time, &tz); iw_init_event_stream(&stream, data, len); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, wireless_data->range.we_version_compiled); if(ret != 0) { if(i++ == 0) printf("%s %-8.16s ", buffer, wireless_data->ifname); else printf(" "); if(ret > 0) print_event_token(&iwe, &wireless_data->range, wireless_data->has_range); else printf("(Invalid event)\n"); /* Push data out *now*, in case we are redirected to a pipe */ fflush(stdout); } } while(ret > 0); return(0); }
static inline void llf_handle_netlink_events(struct rtnl_handle *rth) { while (1) { struct sockaddr_nl sanl; socklen_t sanllen; struct nlmsghdr *h; struct ifinfomsg *ifi; int amt; char buf[8192]; amt = recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &sanl, &sanllen); if (amt < 0) { if (errno != EINTR && errno != EAGAIN) { fprintf(stderr, "%s: error reading netlink: %s.\n", __PRETTY_FUNCTION__, strerror(errno)); } return; } if (amt == 0) { fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__); return; } h = (struct nlmsghdr *) buf; while (amt >= (int) sizeof(*h)) { int len = h->nlmsg_len; int l = len - sizeof(*h); if (l < 0 || len > amt) { fprintf(stderr, "%s: malformed netlink message: len=%d\n", __PRETTY_FUNCTION__, len); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: // LinkCatcher(h); if (h->nlmsg_type != RTM_NEWLINK) return; ifi = NLMSG_DATA(h); /* Check for attributes */ if (h->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) { int attrlen = h->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg)); struct rtattr *attr = (void *) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)); while (RTA_OK(attr, attrlen)) { /* Check if the Wireless kind */ if (attr->rta_type == IFLA_WIRELESS) { struct iw_event iwe; struct stream_descr stream; int ret; #if WE_VERSION >= 17 struct wireless_iface *wireless_data; /* Get data from cache */ wireless_data = iw_get_interface_data(ifi->ifi_index); if (wireless_data == NULL) return; #endif /* Go to display it */ iw_init_event_stream(&stream, (void *) attr + RTA_ALIGN(sizeof (struct rtattr)), attr->rta_len - RTA_ALIGN(sizeof (struct rtattr))); do { /* Extract an event and print it */ #if WE_VERSION >= 17 ret = iw_extract_event_stream(&stream, &iwe, wireless_data-> range. we_version_compiled); #else ret = iw_extract_event_stream(&stream, &iwe); #endif if (ret != 0) { if (ret > 0) llf_print_event(&iwe, NULL, 0); else DEBUG(LOG_WARNING, 0, "Invalid iw event"); } } while (ret > 0); } attr = RTA_NEXT(attr, attrlen); } } break; default: #if 0 fprintf(stderr, "%s: got nlmsg of type %#x.\n", __PRETTY_FUNCTION__, h->nlmsg_type); #endif break; } len = NLMSG_ALIGN(len); amt -= len; h = (struct nlmsghdr *) ((char *) h + len); } if (amt > 0) fprintf(stderr, "%s: remnant of size %d on netlink\n", __PRETTY_FUNCTION__, amt); } }