// Returns AF_MAX (with errno set) if error, AF_UNSPEC if no more addrs (socket closed) struct IPAddr nextAddr(struct AddrFilter const filter, struct MonitorState * const state){ // NLMSG_OK checks length first, so safe to call with state->nlh == NULL iff // state->nlmsg_len < (int) sizeof(struct nlmsghdr) if (NLMSG_OK(state->nlh, state->nlmsg_len) && (state->nlh->nlmsg_type != NLMSG_DONE)){ struct nlmsghdr * nlh = state->nlh; state->nlh = NLMSG_NEXT(state->nlh, state->nlmsg_len); switch(nlh->nlmsg_type){ case NLMSG_ERROR: errno = -((struct nlmsgerr *) NLMSG_DATA(nlh))->error; struct IPAddr addr = {.af = AF_MAX}; return addr; case RTM_NEWADDR: { struct ifaddrmsg * ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); if (!filterIfAddrMsg(*ifa, filter)) return nextAddr(filter, state); { struct rtattr * rth; size_t rtmsg_len; for (rth = IFA_RTA(ifa), rtmsg_len = IFA_PAYLOAD(nlh); RTA_OK(rth, rtmsg_len); RTA_NEXT(rth, rtmsg_len)){ if (rth->rta_type != IFA_ADDRESS) continue; // family checked in filterIfAddrMsg, so always valid. struct IPAddr addr = {.af = ifa->ifa_family}; switch (ifa->ifa_family) { case AF_INET: addr.ipv4 = *((struct in_addr *) RTA_DATA(rth)); break; case AF_INET6: addr.ipv6 = *((struct in6_addr *) RTA_DATA(rth)); break; } if (addrIsPrivate(addr) && !filter.allow_private) return nextAddr(filter, state); else return addr; } } // Recieved RTM_NEWADDR without any address. errno = EBADMSG; struct IPAddr addr = {.af = AF_MAX}; return addr; } default: return nextAddr(filter, state); } } else { state->nlmsg_len = nextMessage(filter, state->socket, &state->buf, &state->buf_len); if (state->nlmsg_len == 0) { // Socket closed by kernel struct IPAddr addr = {.af = AF_UNSPEC}; return addr; } else if (state->nlmsg_len < 0) { // Socket error struct IPAddr addr = {.af = AF_MAX}; return addr; } else {
int avahi_netlink_work(AvahiNetlink *nl, int block) { ssize_t bytes; struct msghdr smsg; struct cmsghdr *cmsg; struct ucred *cred; struct iovec iov; struct nlmsghdr *p; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; assert(nl); iov.iov_base = nl->buffer; iov.iov_len = nl->buffer_length; smsg.msg_name = NULL; smsg.msg_namelen = 0; smsg.msg_iov = &iov; smsg.msg_iovlen = 1; smsg.msg_control = cred_msg; smsg.msg_controllen = sizeof(cred_msg); smsg.msg_flags = (block ? 0 : MSG_DONTWAIT); if ((bytes = recvmsg(nl->fd, &smsg, 0)) < 0) { if (errno == EAGAIN || errno == EINTR) return 0; avahi_log_error(__FILE__": recvmsg() failed: %s", strerror(errno)); return -1; } cmsg = CMSG_FIRSTHDR(&smsg); if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { avahi_log_warn("No sender credentials received, ignoring data."); return -1; } cred = (struct ucred*) CMSG_DATA(cmsg); if (cred->pid != 0) return -1; p = (struct nlmsghdr *) nl->buffer; assert(nl->callback); for (; bytes > 0; p = NLMSG_NEXT(p, bytes)) { if (!NLMSG_OK(p, (size_t) bytes)) { avahi_log_warn(__FILE__": packet truncated"); return -1; } nl->callback(nl, p, nl->userdata); } return 0; }
int netlink_mon_handler(orc_options_t * options, orc_driver_t * drv, int netlink_sock) { char buf[BUFLEN]; int msg_len; struct nlmsghdr * nl_msg; msg_len = recv(netlink_sock, buf, BUFLEN, 0); nl_msg = (struct nlmsghdr *) buf; for (; NLMSG_OK(nl_msg, msg_len); nl_msg=NLMSG_NEXT(nl_msg, msg_len)) { switch(nl_msg->nlmsg_type) { case RTM_NEWLINK: orc_debug("RTNETLINK: add interface\n"); /** TODO **/ break; case RTM_DELLINK: orc_debug("RTNETLINK: del interface\n"); /** TODO **/ break; case RTM_NEWADDR: orc_trace("RTNETLINK: add IPv4 address\n"); handle_v4_addr(OP_ADD, options, nl_msg); break; case RTM_DELADDR: orc_trace("RTNETLINK: del IPv4 address\n"); handle_v4_addr(OP_DEL, options, nl_msg); break; case RTM_NEWROUTE: orc_trace("RTNETLINK: add IPv4 route\n"); handle_v4_route(OP_ADD, options, nl_msg); break; case RTM_DELROUTE: orc_trace("RTNETLINK: del IPv4 route\n"); handle_v4_route(OP_DEL, options, nl_msg); break; case RTM_NEWNEIGH: orc_trace("RTNETLINK: add IPv4 neighbor\n"); handle_v4_neighbor(OP_ADD, options, nl_msg); break; case RTM_DELNEIGH: orc_trace("RTNETLINK: del IPv4 neighbor\n"); handle_v4_neighbor(OP_DEL, options, nl_msg); break; case NLMSG_DONE: orc_log("RTNETLINK: ignoring an NLM_DONE msg\n"); break; default: orc_log("RTNETLINK: unknown msg of type %d -- ignoring\n", nl_msg->nlmsg_type); }; } return 0; }
// gw and iface[IF_NAMESIZE] MUST be allocated int get_default_gw(struct in_addr *gw, char *iface) { struct rtmsg req; unsigned int nl_len; char buf[8192]; struct nlmsghdr *nlhdr; if (!gw || !iface) { return -1; } // Send RTM_GETROUTE request memset(&req, 0, sizeof(req)); int sock = send_nl_req(RTM_GETROUTE, 0, &req, sizeof(req)); // Read responses nl_len = read_nl_sock(sock, buf, sizeof(buf)); if (nl_len <= 0) { return -1; } // Parse responses nlhdr = (struct nlmsghdr *)buf; while (NLMSG_OK(nlhdr, nl_len)) { struct rtattr *rt_attr; struct rtmsg *rt_msg; int rt_len; int has_gw = 0; rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr); if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) { return -1; } rt_attr = (struct rtattr *) RTM_RTA(rt_msg); rt_len = RTM_PAYLOAD(nlhdr); while (RTA_OK(rt_attr, rt_len)) { switch (rt_attr->rta_type) { case RTA_OIF: if_indextoname(*(int *) RTA_DATA(rt_attr), iface); break; case RTA_GATEWAY: gw->s_addr = *(unsigned int *) RTA_DATA(rt_attr); has_gw = 1; break; } rt_attr = RTA_NEXT(rt_attr, rt_len); } if (has_gw) { return 0; } nlhdr = NLMSG_NEXT(nlhdr, nl_len); } return -1; }
static int read_iface_prefix(const char *ip_str, int is_ipv6) { uint8_t family = is_ipv6 ? AF_INET6 : AF_INET; char buf[16384]; unsigned int len; struct { struct nlmsghdr nlhdr; struct ifaddrmsg addrmsg; } msg; struct nlmsghdr *retmsg; int sock = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); memset(&msg, 0, sizeof(msg)); msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; msg.nlhdr.nlmsg_type = RTM_GETADDR; msg.addrmsg.ifa_family = family; SAFE_SEND(1, sock, &msg, msg.nlhdr.nlmsg_len, 0); len = recv(sock, buf, sizeof(buf), 0); retmsg = (struct nlmsghdr *)buf; while NLMSG_OK(retmsg, len) { char ifname[IFNAMSIZ]; struct ifaddrmsg *retaddr; struct rtattr *retrta; char pradd[128]; int attlen; retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg); retrta = (struct rtattr *)IFA_RTA(retaddr); attlen = IFA_PAYLOAD(retmsg); while RTA_OK(retrta, attlen) { if (retrta->rta_type == IFA_ADDRESS) { inet_ntop(family, RTA_DATA(retrta), pradd, sizeof(pradd)); if_indextoname(retaddr->ifa_index, ifname); if (!strcmp(pradd, ip_str)) { prefix = retaddr->ifa_prefixlen; iface = strdup(ifname); return 0; } } retrta = RTA_NEXT(retrta, attlen); } retmsg = NLMSG_NEXT(retmsg, len); } return -1; }
int get_gateway (char *gateway) { struct nlmsghdr *nlMsg; //struct rtmsg *rtMsg; struct route_info *rtInfo; char msgBuf[BUFSIZE]; int sock, len, msgSeq = 0; //?? Socket if ((sock = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { cfg_error("Socket Creation: \n"); return -1; } /* Initialize the buffer */ memset (msgBuf, 0, BUFSIZE); /* point the header and the msg structure pointers into the buffer */ nlMsg = (struct nlmsghdr *)msgBuf; //rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); /* Fill in the nlmsg header */ nlMsg->nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); // Length of message. nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. nlMsg->nlmsg_seq = msgSeq++;/*lint !e632*/ // Sequence of the message packet. nlMsg->nlmsg_pid = getpid ();/*lint !e632*/ // PID of process sending the request. /* Send the request */ if (send (sock, nlMsg, (size_t)(nlMsg->nlmsg_len), 0) < 0) { cfg_error("Write To Socket Failed...\n"); return -1; } /* Read the response */ if ((len = readNlSock (sock, msgBuf, msgSeq, getpid ())) < 0) { cfg_error("Read From Socket Failed...\n"); return -1; } /* Parse and print the response */ rtInfo = (struct route_info *)malloc (sizeof (struct route_info)); if (NULL != rtInfo) { for (; NLMSG_OK (nlMsg, len); nlMsg = NLMSG_NEXT (nlMsg, len)) { /*lint !e574 */ /*lint !e574 */ memset (rtInfo, 0, sizeof (struct route_info)); parseRoutes (nlMsg, rtInfo, gateway); } free (rtInfo); } close (sock); return 0; }
int process_and_print() { std::vector<Entry> ev; unsigned int nlmsg_len_c = nlmsg_len; count = count_messages(); int i = 0; rtentry_array = (rttable_entry *)malloc(count * sizeof(rttable_entry)); // preparujemy wiadomości nlmsg_ptr = (struct nlmsghdr *) read_buffer; for(; NLMSG_OK(nlmsg_ptr, nlmsg_len_c); nlmsg_ptr = NLMSG_NEXT(nlmsg_ptr, nlmsg_len_c)) { Entry e; rtmsg_ptr = (struct rtmsg *) NLMSG_DATA(nlmsg_ptr); prepare_rttable_entry( rtmsg_ptr, &(rtentry_array[i]) ); e.inner = rtentry_array[i]; if (e.inner.dest) { char buf[128]; inet_ntop(e.inner.family, e.inner.dest, buf, 128); e.addr = boost::asio::ip::address::from_string(buf); } ev.push_back(e); i++; } // sortujemy sort(ev.begin(), ev.end(), Entry_oper); // dodajemy wcięcia for(unsigned int i=0; i<ev.size(); i++) { int max_indent = 0; for(unsigned int j=0; j<i; j++) { if ((ev[j].subsumes(ev[i]))) // && (ev[j] != ev[i])) { #define max(a,b) a > b ? a : b max_indent = max(max_indent, ev[j].indent+1); #undef max } } ev[i].indent = max_indent; } // wypisujemy for(unsigned int i=0; i<ev.size(); i++) { ev[i].print(); } return 0; }
static int nl_getmsg(int sd, int request, int seq, struct nlmsghdr **nlhp, int *done) { struct nlmsghdr *nh; size_t bufsize = 65536, lastbufsize = 0; void *buff = NULL; int result = 0, read_size; int msg_flags; pid_t pid = getpid(); for (;;){ void *newbuff = realloc(buff, bufsize); if (newbuff == NULL || bufsize < lastbufsize) { result = -1; break; } buff = newbuff; result = read_size = nl_recvmsg(sd, request, seq, buff, bufsize, &msg_flags); if (read_size < 0 || (msg_flags & MSG_TRUNC)){ lastbufsize = bufsize; bufsize *= 2; continue; } if (read_size == 0) break; nh = (struct nlmsghdr *)buff; for (nh = (struct nlmsghdr *)buff; NLMSG_OK(nh, read_size); nh = (struct nlmsghdr *)NLMSG_NEXT(nh, read_size)){ if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq) continue; if (nh->nlmsg_type == NLMSG_DONE){ (*done)++; break; /* ok */ } if (nh->nlmsg_type == NLMSG_ERROR){ struct nlmsgerr *nlerr = (struct nlmsgerr *)NLMSG_DATA(nh); result = -1; if (nh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) __set_errno(EIO); else __set_errno(-nlerr->error); break; } } break; } if (result < 0) if (buff){ int saved_errno = errno; free(buff); __set_errno(saved_errno); } *nlhp = (struct nlmsghdr *)buff; return result; }
/** * nfnl_iterator_next - get the next message hold by the iterator * @h: nfnetlink handler * @it: nfnetlink iterator that contains the current message processed * * This function update the current message to be processed pointer. * It returns NFNL_CB_CONTINUE if there is still more messages to be * processed, otherwise NFNL_CB_STOP is returned. */ int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it) { assert(h); assert(it); it->nlh = NLMSG_NEXT(it->nlh, it->len); if (!it->nlh) return 0; return 1; }
int read_reply() { //string to hold content of the route // table (i.e. one entry) char dsts[24], gws[24], ifs[16], ms[24]; // outer loop: loops thru all the NETLINK // headers that also include the route entry // header nlp = (struct nlmsghdr *) buf; for(; NLMSG_OK(nlp, nll); nlp = NLMSG_NEXT(nlp, nll)) { // get route entry header rtp = (struct rtmsg *) NLMSG_DATA(nlp); // we are only concerned about the // main route table if(rtp->rtm_table != RT_TABLE_MAIN) continue; // init all the strings bzero(dsts, sizeof(dsts)); bzero(gws, sizeof(gws)); bzero(ifs, sizeof(ifs)); bzero(ms, sizeof(ms)); // inner loop: loop thru all the attributes of // one route entry rtap = (struct rtattr *) RTM_RTA(rtp); rtl = RTM_PAYLOAD(nlp); for( ; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap,rtl)) { switch(rtap->rta_type) { // destination IPv4 address case RTA_DST: inet_ntop(AF_INET, RTA_DATA(rtap), dsts, 24); break; // next hop IPv4 address case RTA_GATEWAY: inet_ntop(AF_INET, RTA_DATA(rtap), gws, 24); break; // unique ID associated with the network // interface case RTA_OIF: sprintf(ifs, "%d", *((int *) RTA_DATA(rtap))); default: break; } } sprintf(ms, "%d", rtp->rtm_dst_len); test_msg("dst %s/%s gw %s if %s\n", dsts, ms, gws, ifs); } return 0; }
int main(int argc, const char *argv[]) { struct nlmsghdr *nl_msg; struct route_info *rt_info; char msg[BUFSIZE]; int sd, len, msg_seq = 0; /* Create Socket */ if ((sd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { perror("Socket Creation: "); } memset(msg, 0, BUFSIZE); /* point the header and the msg structure pointers into the buffer */ nl_msg = (struct nlmsghdr *) msg; /* Fill in the nlmsg header*/ nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message nl_msg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump nl_msg->nlmsg_seq = msg_seq++; // Sequence of the message packet. nl_msg->nlmsg_pid = getpid(); // PID of process sending the request. /* Send the request */ if (send(sd, nl_msg, nl_msg->nlmsg_len, 0) < 0) { printf("Write To Socket Failed...\n"); return -1; } /* Read the response */ if ((len = socket_netlink_read(sd, msg, msg_seq, getpid())) < 0) { printf("Read From Socket Failed...\n"); return -1; } /* Parse and print the response */ rt_info = (struct route_info *) malloc(sizeof(struct route_info)); fprintf(stdout, "Destination\tGateway\tInterface\tSource\n"); for ( ; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len)) { memset(rt_info, 0, sizeof(struct route_info)); route_parse(nl_msg, rt_info); } free(rt_info); close(sd); print_gateway(); return 0; }
static void CAHandleNetlink() { #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) { continue; } int newIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } uint32_t listLength = u_arraylist_length(iflist); for (uint32_t i = 0; i < listLength; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((int)ifitem->index != newIndex) { continue; } CAProcessNewInterface(ifitem); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif // __linux__ }
static void ril_mtu_watch_handle_nlmsg(struct ril_mtu_watch *self, const struct nlmsghdr *hdr, int len) { while (len > 0 && NLMSG_OK(hdr, len)) { if (hdr->nlmsg_type == RTM_NEWLINK) { ril_mtu_watch_handle_ifinfomsg(self, NLMSG_DATA(hdr), IFLA_PAYLOAD(hdr)); } hdr = NLMSG_NEXT(hdr, len); } }
static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx) { struct netlink_data *netlink = eloop_ctx; char buf[8192]; int left; struct sockaddr_nl from; socklen_t fromlen; struct nlmsghdr *h; int max_events = 10; try_again: fromlen = sizeof(from); left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen); if (left < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s", strerror(errno)); return; } h = (struct nlmsghdr *) buf; while (NLMSG_OK(h, left)) { switch (h->nlmsg_type) { case RTM_NEWLINK: netlink_receive_link(netlink, netlink->cfg->newlink_cb, h); break; case RTM_DELLINK: netlink_receive_link(netlink, netlink->cfg->dellink_cb, h); break; } h = NLMSG_NEXT(h, left); } if (left > 0) { wpa_printf(MSG_DEBUG, "netlink: %d extra bytes in the end of " "netlink message", left); } if (--max_events > 0) { /* * Try to receive all events in one eloop call in order to * limit race condition on cases where AssocInfo event, Assoc * event, and EAPOL frames are received more or less at the * same time. We want to process the event messages first * before starting EAPOL processing. */ goto try_again; } }
void process_netlink_msg(int netlink_fd){ int len = 0; char buffer[4096]; struct iovec iov; struct sockaddr_nl dst_addr; struct msghdr msgh; struct nlmsghdr *nlh = NULL; nlh = (struct nlmsghdr *)buffer; memset(&iov, 0, sizeof(iov)); iov.iov_base = (void *)nlh; iov.iov_len = sizeof(nlh); memset(&msgh, 0, sizeof(msgh)); msgh.msg_name = (void *)&(dst_addr); msgh.msg_namelen = sizeof(dst_addr); msgh.msg_iov = &iov; msgh.msg_iovlen = 1; while ((len = recv (netlink_fd,nlh,4096,MSG_DONTWAIT)) > 0){ for (;(NLMSG_OK (nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE); nlh = NLMSG_NEXT(nlh, len)){ switch(nlh->nlmsg_type){ case RTM_NEWADDR: lispd_log_msg(LISP_LOG_DEBUG_2, "=>process_netlink_msg: Received new address message"); process_nl_add_address (nlh); break; case RTM_DELADDR: lispd_log_msg(LISP_LOG_DEBUG_2, "=>process_netlink_msg: Received del address message"); process_nl_del_address (nlh); break; case RTM_NEWLINK: lispd_log_msg(LISP_LOG_DEBUG_2, "=>process_netlink_msg: Received link message"); process_nl_new_link (nlh); break; case RTM_NEWROUTE: lispd_log_msg(LISP_LOG_DEBUG_2, "=>process_netlink_msg: Received new route message"); process_nl_new_route (nlh); break; case RTM_DELROUTE: //lispd_log_msg(LISP_LOG_DEBUG_2, "=>process_netlink_msg: Received remove route message"); //process_nl_del_route (nlh); break; default: break; } } nlh = (struct nlmsghdr *)buffer; memset(nlh,0,4096); } lispd_log_msg(LISP_LOG_DEBUG_2, "Finish pocessing netlink message"); return; }
void getPortInode(QueryData &results, int type) { int nl_sock = 0; int numbytes = 0; int rtalen = 0; struct nlmsghdr *nlh; uint8_t recv_buf[SOCKET_BUFFER_SIZE]; struct inet_diag_msg *diag_msg; // set up the socket if ((nl_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG)) == -1) { close(nl_sock); return; } // send the inet_diag message if (send_diag_msg(nl_sock, type) < 0) { close(nl_sock); return; } // recieve netlink messages numbytes = recv(nl_sock, recv_buf, sizeof(recv_buf), 0); nlh = (struct nlmsghdr *)recv_buf; while (NLMSG_OK(nlh, numbytes)) { // close the socket once NLMSG_DONE header recieved if (nlh->nlmsg_type == NLMSG_DONE) { close(nl_sock); return; } if (nlh->nlmsg_type == NLMSG_ERROR) { close(nl_sock); return; } // parse and process netlink message diag_msg = (struct inet_diag_msg *)NLMSG_DATA(nlh); rtalen = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*diag_msg)); try { results.push_back(parse_diag_msg(diag_msg, rtalen)); } catch (std::exception &e) { LOG(ERROR) << e.what(); } nlh = NLMSG_NEXT(nlh, numbytes); } close(nl_sock); return; }
QueryData genRoutes(QueryContext& context) { QueryData results; int socket_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (socket_fd < 0) { VLOG(1) << "Cannot open NETLINK socket"; return {}; } // Create netlink message header auto netlink_buffer = (void*)malloc(MAX_NETLINK_SIZE); if (netlink_buffer == nullptr) { close(socket_fd); return {}; } memset(netlink_buffer, 0, MAX_NETLINK_SIZE); auto netlink_msg = (struct nlmsghdr*)netlink_buffer; netlink_msg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); netlink_msg->nlmsg_type = RTM_GETROUTE; // routes from kernel routing table netlink_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST | NLM_F_ATOMIC; netlink_msg->nlmsg_seq = 0; netlink_msg->nlmsg_pid = getpid(); // Send the netlink request to the kernel if (send(socket_fd, netlink_msg, netlink_msg->nlmsg_len, 0) < 0) { TLOG << "Cannot write NETLINK request header to socket"; close(socket_fd); free(netlink_buffer); return {}; } // Wrap the read socket to support multi-netlink messages size_t size = 0; if (!readNetlink(socket_fd, 1, (char*)netlink_msg, &size).ok()) { TLOG << "Cannot read NETLINK response from socket"; close(socket_fd); free(netlink_buffer); return {}; } // Treat the netlink response as route information while (NLMSG_OK(netlink_msg, size)) { genNetlinkRoutes(netlink_msg, results); netlink_msg = NLMSG_NEXT(netlink_msg, size); } close(socket_fd); free(netlink_buffer); return results; }
int main() { struct sockaddr_nl addr; int sock, len; char buffer[4096]; struct nlmsghdr *nlh; if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { perror("couldn't open NETLINK_ROUTE socket"); return 1; } fprintf(stderr,"socket: f%d\n",sock); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_IPV4_IFADDR; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("couldn't bind"); return 1; } fprintf(stderr,"bound\n"); nlh = (struct nlmsghdr *)buffer; while ((len = recv(sock, nlh, 4096, 0)) > 0) { fprintf(stderr,"recv returned %db (%d %s)\n",len,errno,strerror(errno)); while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR) { struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(nlh); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_LOCAL) { uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth))); char name[IFNAMSIZ]; if_indextoname(ifa->ifa_index, name); printf("%s is now %d.%d.%d.%d\n", name, (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff); } rth = RTA_NEXT(rth, rtl); } } nlh = NLMSG_NEXT(nlh, len); } }
static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) { ssize_t bytes_read; // Read through all the responses, handing interesting ones to __handle_netlink_response. while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) { nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf); for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) { if (hdr->nlmsg_type == NLMSG_DONE) return true; if (hdr->nlmsg_type == NLMSG_ERROR) return false; __handle_netlink_response(out, hdr); } } // We only get here if recv fails before we see a NLMSG_DONE. return false; }
static int kni_rtnl_check(void *arg) { struct netif_port *dev = arg; int fd = dev->kni.kni_rtnl_fd; int n, i; char buf[4096]; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; bool update = false; int max_trials = 1000; /* try to handle more events once, because we're not really * event-driven, the polling speed may not fast enough. * there may not so may events in real world ? but when * performan strength test, it's really found kni_rtnl_timer * is too slow, so that more and more events queued. */ for (i = 0; i < max_trials; i++) { n = recv(fd, nlh, sizeof(buf), 0); if (n < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) break; /* no more events */ RTE_LOG(WARNING, Kni, "fail to check kni event!\n"); return DTIMER_OK; } else if (n == 0) break; /* closed */ while (NLMSG_OK(nlh, n) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR) { update = true; break; /* not need handle all messages, recv again. */ } nlh = NLMSG_NEXT(nlh, n); } } if (!kni_dev_exist(dev)) return DTIMER_OK; /* note we should not update kni mac list for every event ! */ if (update) { RTE_LOG(DEBUG, Kni, "%d events received!\n", i); if (kni_update_maddr(dev) == EDPVS_OK) RTE_LOG(DEBUG, Kni, "update maddr of %s OK!\n", dev->name); else RTE_LOG(ERR, Kni, "update maddr of %s Failed!\n", dev->name); } return DTIMER_OK; }
/* * our custom recvmsg, checks for the port number and hides it from ss */ asmlinkage ssize_t manipulated_recvmsg(int fd, struct user_msghdr __user * msg, unsigned int flags) { /* lock and increase the call counter */ INCREASE_CALL_COUNTER(recvmsg_call_counter, &recvmsg_lock, recvmsg_lock_flags); ssize_t retv; char *stream; struct nlmsghdr *nlh; struct inet_diag_msg *idm; unsigned int port; int i; int count; int offset; int found = 1; /* compute the length of original call */ retv = original_recvmsg(fd, msg, flags); nlh = (struct nlmsghdr *)(msg->msg_iov->iov_base); /* to hold the bytes remaining */ count = retv; while (NLMSG_OK(nlh, count)) { if (found == 0) nlh = NLMSG_NEXT(nlh, count); stream = (char *)nlh; idm = NLMSG_DATA(nlh); port = ntohs(idm->id.idiag_sport); /* check if we need to hide this socket */ if (is_tcp_socket_hidden(port)) { found = 1; offset = NLMSG_ALIGN(nlh->nlmsg_len); for (i = 0; i < count; ++i) stream[i] = stream[i + offset]; retv -= offset; } else found = 0; } /* lock and increase the call counter */ DECREASE_CALL_COUNTER(recvmsg_call_counter, &recvmsg_lock, recvmsg_lock_flags); return retv; }
/* * Handle a single netlink message. Block until we get a route status * change message. Returns 0 if there was a route status change, 1 if there was * a timeout, and -1 if there was a read error. */ int API routeup_once (struct routeup *rtc, unsigned int timeout) { char buf[4096]; ssize_t sz; struct timeval remaining; struct timeval *rp = timeout ? &remaining : NULL; fd_set fds; remaining.tv_sec = timeout; remaining.tv_usec = 0; FD_ZERO (&fds); FD_SET (rtc->netlinkfd, &fds); while (select (rtc->netlinkfd + 1, &fds, NULL, NULL, rp) >= 0) { FD_ZERO (&fds); FD_SET (rtc->netlinkfd, &fds); if (timeout && !remaining.tv_sec && !remaining.tv_usec) return 1; if ((sz = read (rtc->netlinkfd, buf, sizeof (buf))) < 0) return -1; struct nlmsghdr *nh; for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, sz); nh = NLMSG_NEXT (nh, sz)) { /* * Unpack the netlink message into a bunch of... well... * netlink messages. The terminology is overloaded. Walk * through the message until we find a header of type * NLMSG_DONE. */ if (nh->nlmsg_type == NLMSG_DONE) break; if (nh->nlmsg_type != RTM_NEWROUTE) continue; /* * Clear out the socket so we don't keep old messages * queued up and eventually overflow the receive buffer. */ while (read (rtc->netlinkfd, buf, sizeof(buf)) > 0) /* loop through receive queue */; if (errno != EAGAIN) return -1; return 0; } } return -1; }
void netlink_multicast(struct daemon *daemon) { ssize_t len; struct nlmsghdr *h; if ((len = netlink_recv(daemon)) != -1) { for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) if (h->nlmsg_type == NLMSG_ERROR) nl_err(h); else nl_routechange(daemon, h); } }
std::unique_ptr<std::vector<char>> Netlink::rcv(unsigned int nlmsgSeq) { std::unique_ptr<std::vector<char>> buf(new std::vector<char>()); msghdr msg = utils::make_clean<msghdr>(); sockaddr_nl nladdr = utils::make_clean<sockaddr_nl>(); iovec iov = utils::make_clean<iovec>(); msg.msg_name = &nladdr; msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; nladdr.nl_family = AF_NETLINK; nlmsghdr* answer; nlmsghdr* lastOk = NULL; size_t offset = 0; do { buf->resize(offset + NLMSG_RCV_GOOD_SIZE); answer = reinterpret_cast<nlmsghdr*>(buf->data() + offset); iov.iov_base = answer; iov.iov_len = buf->size() - offset; unsigned int ret = vsm_recvmsg(mFd, &msg, 0); for (unsigned int len = ret; NLMSG_OK(answer, len); answer = NLMSG_NEXT(answer, len)) { lastOk = answer; if (answer->nlmsg_type == NLMSG_ERROR) { // It is NACK/ACK message nlmsgerr *err = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(answer)); if (answer->nlmsg_seq != nlmsgSeq) { throw VasumException("Receive failed: answer message was mismatched"); } if (err->error) { throw VasumException("Receive failed: " + getSystemErrorMessage(-err->error)); } } else if (answer->nlmsg_type == NLMSG_OVERRUN) { throw VasumException("Receive failed: data lost"); } } if (lastOk == NULL) { const std::string msg = "Can't receive data from the system"; LOGE(msg); throw VasumException(msg); } offset += NLMSG_ALIGN(ret); } while (lastOk->nlmsg_type != NLMSG_DONE && lastOk->nlmsg_flags & NLM_F_MULTI); buf->resize(offset); return buf; }
/*** read_event ***/ int read_event (int sockint) { int status, rc = EXIT_FAILURE; char buf[4096]; struct iovec iov = { buf, sizeof buf }; struct sockaddr_nl snl; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; struct nlmsghdr *h; if ((status = recvmsg (sockint, &msg, 0)) < 0) { /* Socket non-blocking so bail out once we have read everything */ if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) { rc = EXIT_SUCCESS; goto out; } /* Anything else is an error */ fprintf (stderr, "read_netlink: Error recvmsg: %d\n", status); goto out; } if (status == 0) fprintf (stderr, "read_netlink: EOF\n"); /* We need to handle more than one message per 'recvmsg' */ for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); h = NLMSG_NEXT (h, status)) { /* Finish reading */ if (h->nlmsg_type == NLMSG_DONE) { rc = EXIT_SUCCESS; goto out; } /* Message is some kind of error */ if (h->nlmsg_type == NLMSG_ERROR) { fprintf (stderr, "read_netlink: Message is an error - decode TBD\n"); goto out; } /* Call message handler */ if (msg_handler(&snl, h) != EXIT_SUCCESS) { fprintf (stderr, "read_event: Message hander returned error.\n"); goto out; } } rc = EXIT_SUCCESS; out: return rc; }
/* * Function : icm_parse_netlink_msg * Description : parse the received netlink msg to know * the interface state changes. * Input params : pointer pointing to the ICM_DEV_INFO_T structure * Return : SUCCESS or FAILURE * */ int icm_parse_rtnetlink_msg(ICM_DEV_INFO_T* pdev) { int len; char buf[RTNETLINKBUFSIZ] = {0}; struct iovec iov = {buf, sizeof(buf)}; struct sockaddr_nl sa; struct nlmsghdr *nh; struct msghdr msg = {(void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0}; struct ifinfomsg *ifinfo; char ifname[IFNAMSIZ] = {0}; ICM_NLSOCK_T *prtnlinfo = ICM_GET_ADDR_OF_RTNLSOCK_INFO(pdev); int sd = prtnlinfo->sock_fd; len = recvmsg(sd, &msg, 0); /* Parsing the Netlink message */ for(nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if(nh->nlmsg_type == NLMSG_DONE) { break; } if(nh->nlmsg_type == NLMSG_ERROR) { return -1; } ifinfo = NLMSG_DATA(nh); if_indextoname(ifinfo->ifi_index, ifname); if((ifinfo->ifi_flags & IFF_RUNNING) && (ifinfo->ifi_flags & IFF_UP)) { ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET, "VAP %s ifindex %d is Created. Status: UP Running\n", ifname, ifinfo->ifi_index); ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET,"Updating Device information\n"); } else if((ifinfo->ifi_flags & IFF_UP) || (ifinfo->ifi_flags & IFF_RUNNING)) { ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET, "VAP %s ifindex %d is Created. Status: Down Not Running\n", ifname, ifinfo->ifi_index); ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET,"Updating Device information\n"); } else { ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET, "VAP %s ifindex %d is Destroyed.\n", ifname, ifinfo->ifi_index); ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_MAJOR, ICM_MODULE_ID_SOCKET,"Updating Device information\n"); } icm_configure_radio_iface(pdev); } return SUCCESS; }
static void netsnmp_access_arp_read_netlink(int fd, void *data) { netsnmp_arp_access *access = (netsnmp_arp_access *) data; netsnmp_arp_entry *entry; char buf[16384]; struct nlmsghdr *h; int r, len; do { r = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); if (r < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) return; snmp_log(LOG_WARNING, "netlink buffer overrun\n"); access->synchronized = 0; if (access->cache_expired != NULL) *access->cache_expired = 1; return; } } while (0); len = r; for (h = (struct nlmsghdr *) buf; NLMSG_OK(h, len); h = NLMSG_NEXT(h, len)) { if (h->nlmsg_type == NLMSG_DONE) { access->synchronized = 1; continue; } entry = netsnmp_access_arp_entry_create(); if (NULL == entry) break; DEBUGMSGTL(("access:netlink:arp", "arp netlink notification\n")); entry->generation = access->generation; r = fillup_entry_info (entry, h); if (r > 0) { access->update_hook(access, entry); } else { if (r < 0) { NETSNMP_LOGONCE((LOG_ERR, "filling entry info failed\n")); DEBUGMSGTL(("access:netlink:arp", "filling entry info failed\n")); } netsnmp_access_arp_entry_free(entry); } } }
/* ****************************************************************************** * dcs_local_ip_monitor_process *//** * * \brief - Called by the polling thread that gets an indication that the local * IP address has changed. The function sets the Local IP Address in * the dcs_local_ip variable * * \param[in] socket - The socket on which the information arrived * \param[in] context - NULL * * \retval DOVE_STATUS_OK * ****************************************************************************** */ static int dcs_local_ip_monitor_process(int socket, void *context) { struct nlmsghdr *nlh; char buf[4096]; int len; dove_status status = DOVE_STATUS_OK; while ((len = recv(dps_monitor_socket, buf, sizeof(buf), 0)) > 0) { nlh = (struct nlmsghdr *)buf; while ((NLMSG_OK(nlh, (uint32_t)len)) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR || nlh->nlmsg_type == RTM_DELADDR) { struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(nlh); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_LOCAL) { char ifname[IFNAMSIZ]; if_indextoname(ifa->ifa_index, ifname); if (!strcmp(ifname, SVA_INTERFACE_NAME) && (nlh->nlmsg_type == RTM_NEWADDR)) { status = set_local_ip(); if (status != DOVE_STATUS_OK) { log_warn(PythonDataHandlerLogLevel, "Cannot get IP Address of SVA"); break; } // Register the Local DPS Node with the Cluster dcs_set_service_role(dcs_role_assigned); } } rth = RTA_NEXT(rth, rtl); } } nlh = NLMSG_NEXT(nlh, len); } } return DOVE_STATUS_OK; }
static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) { char buf[8192]; int left; struct sockaddr_nl from; socklen_t fromlen; struct nlmsghdr *h; struct hostapd_data *hapd = eloop_ctx; fromlen = sizeof(from); left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen); if (left < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s", __func__, strerror(errno)); return; } h = (struct nlmsghdr *) buf; while (NLMSG_OK(h, left)) { int len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink " "message: len=%d left=%d plen=%d", len, left, plen); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: vlan_read_ifnames(h, plen, 0, hapd); break; case RTM_DELLINK: vlan_read_ifnames(h, plen, 1, hapd); break; } h = NLMSG_NEXT(h, left); } if (left > 0) { wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of " "netlink message", __func__, left); } }
static void factory_receive_skb(struct sk_buff *skb) { struct nlmsghdr *nlh; int len; int err; nlh = (struct nlmsghdr*)skb->data; len = skb->len; while (NLMSG_OK(nlh, len)) { err = process_received_msg(skb, nlh); /* if err or if this message says it wants a response */ if (err || (nlh->nlmsg_flags & NLM_F_ACK)) netlink_ack(skb, nlh, err); nlh = NLMSG_NEXT(nlh, len); } }