int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; int deprecated = 0; struct rtattr * rta_tb[IFA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) return 0; len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (filter.flushb && n->nlmsg_type != RTM_NEWADDR) return 0; parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); if (!rta_tb[IFA_LOCAL]) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; if (filter.ifindex && filter.ifindex != ifa->ifa_index) return 0; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) return 0; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) return 0; if (filter.label) { SPRINT_BUF(b1); const char *label; if (rta_tb[IFA_LABEL]) label = RTA_DATA(rta_tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) return 0; } if (filter.pfx.family) { if (rta_tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) return 0; } } if (filter.family && filter.family != ifa->ifa_family) return 0; if (filter.flushb) { struct nlmsghdr *fn; if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { if (flush_update()) return -1; } fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELADDR; fn->nlmsg_flags = NLM_F_REQUEST; fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) return 0; } if (n->nlmsg_type == RTM_DELADDR) fprintf(fp, "Deleted "); if (filter.oneline || filter.flushb) fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); if (ifa->ifa_family == AF_INET) fprintf(fp, " inet "); else if (ifa->ifa_family == AF_INET6) fprintf(fp, " inet6 "); else if (ifa->ifa_family == AF_DECnet) fprintf(fp, " dnet "); else if (ifa->ifa_family == AF_IPX) fprintf(fp, " ipx "); else fprintf(fp, " family %d ", ifa->ifa_family); if (rta_tb[IFA_LOCAL]) { fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); if (rta_tb[IFA_ADDRESS] == NULL || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) { fprintf(fp, "/%d ", ifa->ifa_prefixlen); } else { fprintf(fp, " peer %s/%d ", rt_addr_n2a(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_ADDRESS]), abuf, sizeof(abuf)), ifa->ifa_prefixlen); } } if (rta_tb[IFA_BROADCAST]) { fprintf(fp, "brd %s ", rt_addr_n2a(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_BROADCAST]), RTA_DATA(rta_tb[IFA_BROADCAST]), abuf, sizeof(abuf))); } if (rta_tb[IFA_ANYCAST]) { fprintf(fp, "any %s ", rt_addr_n2a(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_ANYCAST]), RTA_DATA(rta_tb[IFA_ANYCAST]), abuf, sizeof(abuf))); } fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); if (ifa->ifa_flags&IFA_F_SECONDARY) { ifa->ifa_flags &= ~IFA_F_SECONDARY; if (ifa->ifa_family == AF_INET6) fprintf(fp, "temporary "); else fprintf(fp, "secondary "); } if (ifa->ifa_flags&IFA_F_TENTATIVE) { ifa->ifa_flags &= ~IFA_F_TENTATIVE; fprintf(fp, "tentative "); } if (ifa->ifa_flags&IFA_F_DEPRECATED) { ifa->ifa_flags &= ~IFA_F_DEPRECATED; deprecated = 1; fprintf(fp, "deprecated "); } if (ifa->ifa_flags&IFA_F_HOMEADDRESS) { ifa->ifa_flags &= ~IFA_F_HOMEADDRESS; fprintf(fp, "home "); } if (ifa->ifa_flags&IFA_F_NODAD) { ifa->ifa_flags &= ~IFA_F_NODAD; fprintf(fp, "nodad "); } if (!(ifa->ifa_flags&IFA_F_PERMANENT)) { fprintf(fp, "dynamic "); } else ifa->ifa_flags &= ~IFA_F_PERMANENT; if (ifa->ifa_flags&IFA_F_DADFAILED) { ifa->ifa_flags &= ~IFA_F_DADFAILED; fprintf(fp, "dadfailed "); } if (ifa->ifa_flags) fprintf(fp, "flags %02x ", ifa->ifa_flags); if (rta_tb[IFA_LABEL]) fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL])); if (rta_tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); char buf[128]; fprintf(fp, "%s", _SL_); if (ci->ifa_valid == INFINITY_LIFE_TIME) sprintf(buf, "valid_lft forever"); else sprintf(buf, "valid_lft %usec", ci->ifa_valid); if (ci->ifa_prefered == INFINITY_LIFE_TIME) sprintf(buf+strlen(buf), " preferred_lft forever"); else { if (deprecated) sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered); else sprintf(buf+strlen(buf), " preferred_lft %usec", ci->ifa_prefered); } fprintf(fp, " %s", buf); } fprintf(fp, "\n"); fflush(fp); return 0; }
static void rtnl_print_ifinfo(struct nlmsghdr *hdr) { struct ifinfomsg *ifi = NLMSG_DATA(hdr); struct rtattr *attr = IFLA_RTA(ifi); uint32_t attrs_len = IFLA_PAYLOAD(hdr); char flags[256]; char if_addr[64] = {}; char *af_link = "unknown"; if (ifi->ifi_family == AF_UNSPEC) af_link = "unspec"; else if (ifi->ifi_family == AF_BRIDGE) af_link = "bridge"; tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family, colorize_start(bold), af_link, colorize_end()); tprintf(", Type %d (%s%s%s)", ifi->ifi_type, colorize_start(bold), device_type2str(ifi->ifi_type), colorize_end()); tprintf(", Index %d", ifi->ifi_index); tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags, colorize_start(bold), rtnl_link_flags2str(ifi->ifi_flags, flags, sizeof(flags)), colorize_end()); tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change, colorize_start(bold), rtnl_link_flags2str(ifi->ifi_change, flags, sizeof(flags)), colorize_end()); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case IFLA_ADDRESS: attr_fmt(attr, "Address %s", device_addr2str(RTA_DATA(attr), RTA_LEN(attr), ifi->ifi_type, if_addr, sizeof(if_addr))); break; case IFLA_BROADCAST: attr_fmt(attr, "Broadcast %s", device_addr2str(RTA_DATA(attr), RTA_LEN(attr), ifi->ifi_type, if_addr, sizeof(if_addr))); break; case IFLA_IFNAME: attr_fmt(attr, "Name %s%s%s", colorize_start(bold), RTA_STR(attr), colorize_end()); break; case IFLA_MTU: attr_fmt(attr, "MTU %d", RTA_INT(attr)); break; case IFLA_LINK: attr_fmt(attr, "Link %d", RTA_INT(attr)); break; case IFLA_QDISC: attr_fmt(attr, "QDisc %s", RTA_STR(attr)); break; case IFLA_OPERSTATE: { uint8_t st = RTA_UINT8(attr); char states[256]; attr_fmt(attr, "Operation state 0x%x (%s%s%s)", st, colorize_start(bold), rtnl_link_operstate2str(st, states, sizeof(states)), colorize_end()); } break; case IFLA_LINKMODE: { uint8_t mode = RTA_UINT8(attr); char str[32]; attr_fmt(attr, "Mode 0x%x (%s%s%s)", mode, colorize_start(bold), rtnl_link_mode2str(mode, str, sizeof(str)), colorize_end()); } break; case IFLA_GROUP: attr_fmt(attr, "Group %d", RTA_INT(attr)); break; case IFLA_TXQLEN: attr_fmt(attr, "Tx queue len %d", RTA_INT(attr)); break; case IFLA_NET_NS_PID: attr_fmt(attr, "Network namespace pid %d", RTA_INT(attr)); break; case IFLA_NET_NS_FD: attr_fmt(attr, "Network namespace fd %d", RTA_INT(attr)); break; } } }
static void rtnl_print_route(struct nlmsghdr *hdr) { struct rtmsg *rtm = NLMSG_DATA(hdr); uint32_t attrs_len = RTM_PAYLOAD(hdr); struct rtattr *attr = RTM_RTA(rtm); struct rta_cacheinfo *ci; int hz = get_user_hz(); char addr_str[256]; char flags[256]; tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family, colorize_start(bold), addr_family2str(rtm->rtm_family), colorize_end()); tprintf(", Dst Len %d", rtm->rtm_dst_len); tprintf(", Src Len %d", rtm->rtm_src_len); tprintf(", ToS %d", rtm->rtm_tos); tprintf(", Table %d (%s%s%s)", rtm->rtm_table, colorize_start(bold), route_table2str(rtm->rtm_table), colorize_end()); tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol, colorize_start(bold), route_proto2str(rtm->rtm_protocol), colorize_end()); tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope, colorize_start(bold), scope2str(rtm->rtm_scope), colorize_end()); tprintf(", Type %d (%s%s%s)", rtm->rtm_type, colorize_start(bold), route_type2str(rtm->rtm_type), colorize_end()); tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags, colorize_start(bold), flags2str(route_flags, rtm->rtm_flags, flags, sizeof(flags)), colorize_end()); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case RTA_DST: attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_SRC: attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_IIF: attr_fmt(attr, "Iif %d", RTA_INT(attr)); break; case RTA_OIF: attr_fmt(attr, "Oif %d", RTA_INT(attr)); break; case RTA_GATEWAY: attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_PRIORITY: attr_fmt(attr, "Priority %u", RTA_UINT32(attr)); break; case RTA_PREFSRC: attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_MARK: attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr)); break; case RTA_FLOW: attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr)); break; case RTA_TABLE: attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr), colorize_start(bold), route_table2str(RTA_UINT32(attr)), colorize_end()); break; case RTA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); tprintf("expires(%ds)", ci->rta_expires / hz); tprintf(", error(%d)", ci->rta_error); tprintf(", users(%d)", ci->rta_clntref); tprintf(", used(%d)", ci->rta_used); tprintf(", last use(%ds)", ci->rta_lastuse / hz); tprintf(", id(%d)", ci->rta_id); tprintf(", ts(%d)", ci->rta_ts); tprintf(", ts age(%ds))", ci->rta_tsage); tprintf(", Len %lu\n", RTA_LEN(attr)); break; } } }
int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct rtattr * tb[XFRMA_MAX+1]; struct rtattr * rta; struct xfrm_usersa_info *xsinfo = NULL; struct xfrm_user_expire *xexp = NULL; struct xfrm_usersa_id *xsid = NULL; int len = n->nlmsg_len; if (n->nlmsg_type != XFRM_MSG_NEWSA && n->nlmsg_type != XFRM_MSG_DELSA && n->nlmsg_type != XFRM_MSG_UPDSA && n->nlmsg_type != XFRM_MSG_EXPIRE) { fprintf(stderr, "Not a state: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } if (n->nlmsg_type == XFRM_MSG_DELSA) { /* Dont blame me for this .. Herbert made me do it */ xsid = NLMSG_DATA(n); len -= NLMSG_SPACE(sizeof(*xsid)); } else if (n->nlmsg_type == XFRM_MSG_EXPIRE) { xexp = NLMSG_DATA(n); xsinfo = &xexp->state; len -= NLMSG_SPACE(sizeof(*xexp)); } else { xexp = NULL; xsinfo = NLMSG_DATA(n); len -= NLMSG_SPACE(sizeof(*xsinfo)); } if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (xsinfo && !xfrm_state_filter_match(xsinfo)) return 0; if (n->nlmsg_type == XFRM_MSG_DELSA) fprintf(fp, "Deleted "); else if (n->nlmsg_type == XFRM_MSG_UPDSA) fprintf(fp, "Updated "); else if (n->nlmsg_type == XFRM_MSG_EXPIRE) fprintf(fp, "Expired "); if (n->nlmsg_type == XFRM_MSG_DELSA) rta = XFRMSID_RTA(xsid); else if (n->nlmsg_type == XFRM_MSG_EXPIRE) rta = XFRMEXP_RTA(xexp); else rta = XFRMS_RTA(xsinfo); parse_rtattr(tb, XFRMA_MAX, rta, len); if (n->nlmsg_type == XFRM_MSG_DELSA) { //xfrm_policy_id_print(); if (!tb[XFRMA_SA]) { fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n"); return -1; } if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) { fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n"); return -1; } xsinfo = RTA_DATA(tb[XFRMA_SA]); } xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL); if (n->nlmsg_type == XFRM_MSG_EXPIRE) { fprintf(fp, "\t"); fprintf(fp, "hard %u", xexp->hard); fprintf(fp, "%s", _SL_); } if (oneline) fprintf(fp, "\n"); fflush(fp); return 0; }
/** * Scan netlink message in the buffer for IPv6 default route changes. */ static int rtmon_check_defaults(const void *buf, size_t len) { struct nlmsghdr *nh; int dfltdiff = 0; for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { struct rtmsg *rtm; struct rtattr *rta; int attrlen; int delta = 0; const void *gwbuf; size_t gwlen; int oif; DPRINTF2(("nlmsg type %d flags 0x%x\n", nh->nlmsg_seq, nh->nlmsg_type, nh->nlmsg_flags)); if (nh->nlmsg_type == NLMSG_DONE) { break; } if (nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *ne = (struct nlmsgerr *)NLMSG_DATA(nh); DPRINTF2(("> error %d\n", ne->error)); LWIP_UNUSED_ARG(ne); break; } if (nh->nlmsg_type < RTM_BASE || RTM_MAX <= nh->nlmsg_type) { /* shouldn't happen */ DPRINTF2(("> not an RTM message!\n")); continue; } rtm = (struct rtmsg *)NLMSG_DATA(nh); attrlen = RTM_PAYLOAD(nh); if (nh->nlmsg_type == RTM_NEWROUTE) { delta = +1; } else if (nh->nlmsg_type == RTM_DELROUTE) { delta = -1; } else { /* shouldn't happen */ continue; } /* * Is this an IPv6 default route in the main table? (Local * table always has ::/0 reject route, hence the last check). */ if (rtm->rtm_family == AF_INET6 /* should always be true */ && rtm->rtm_dst_len == 0 && rtm->rtm_table == RT_TABLE_MAIN) { dfltdiff += delta; } else { /* some other route change */ continue; } gwbuf = NULL; gwlen = 0; oif = -1; for (rta = RTM_RTA(rtm); RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) { if (rta->rta_type == RTA_GATEWAY) { gwbuf = RTA_DATA(rta); gwlen = RTA_PAYLOAD(rta); } else if (rta->rta_type == RTA_OIF) { /* assert RTA_PAYLOAD(rta) == 4 */ memcpy(&oif, RTA_DATA(rta), sizeof(oif)); } } /* XXX: TODO: note that { oif, gw } was added/removed */ LWIP_UNUSED_ARG(gwbuf); LWIP_UNUSED_ARG(gwlen); LWIP_UNUSED_ARG(oif); } return dfltdiff; }
int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtattr * tb[XFRMA_MAX+1]; struct rtattr * rta; struct xfrm_userpolicy_info *xpinfo = NULL; struct xfrm_user_polexpire *xpexp = NULL; struct xfrm_userpolicy_id *xpid = NULL; __u8 ptype = XFRM_POLICY_TYPE_MAIN; FILE *fp = (FILE*)arg; int len = n->nlmsg_len; if (n->nlmsg_type != XFRM_MSG_NEWPOLICY && n->nlmsg_type != XFRM_MSG_DELPOLICY && n->nlmsg_type != XFRM_MSG_UPDPOLICY && n->nlmsg_type != XFRM_MSG_POLEXPIRE) { fprintf(stderr, "Not a policy: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } if (n->nlmsg_type == XFRM_MSG_DELPOLICY) { xpid = NLMSG_DATA(n); len -= NLMSG_SPACE(sizeof(*xpid)); } else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) { xpexp = NLMSG_DATA(n); xpinfo = &xpexp->pol; len -= NLMSG_SPACE(sizeof(*xpexp)); } else { xpexp = NULL; xpinfo = NLMSG_DATA(n); len -= NLMSG_SPACE(sizeof(*xpinfo)); } if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (n->nlmsg_type == XFRM_MSG_DELPOLICY) rta = XFRMPID_RTA(xpid); else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) rta = XFRMPEXP_RTA(xpexp); else rta = XFRMP_RTA(xpinfo); parse_rtattr(tb, XFRMA_MAX, rta, len); if (tb[XFRMA_POLICY_TYPE]) { struct xfrm_userpolicy_type *upt; if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) { fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n"); return -1; } upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]); ptype = upt->type; } if (xpinfo && !xfrm_policy_filter_match(xpinfo, ptype)) return 0; if (n->nlmsg_type == XFRM_MSG_DELPOLICY) fprintf(fp, "Deleted "); else if (n->nlmsg_type == XFRM_MSG_UPDPOLICY) fprintf(fp, "Updated "); else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) fprintf(fp, "Expired "); if (n->nlmsg_type == XFRM_MSG_DELPOLICY) { //xfrm_policy_id_print(); if (!tb[XFRMA_POLICY]) { fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n"); return -1; } if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) { fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n"); return -1; } xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]); } xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL); if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) { fprintf(fp, "\t"); fprintf(fp, "hard %u", xpexp->hard); fprintf(fp, "%s", _SL_); } if (oneline) fprintf(fp, "\n"); fflush(fp); return 0; }
static int print_spdinfo( struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; __u32 *f = NLMSG_DATA(n); struct rtattr * tb[XFRMA_SPD_MAX+1]; struct rtattr * rta; int len = n->nlmsg_len; len -= NLMSG_LENGTH(sizeof(__u32)); if (len < 0) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } rta = XFRMSAPD_RTA(f); parse_rtattr(tb, XFRMA_SPD_MAX, rta, len); fprintf(fp,"\t SPD"); if (tb[XFRMA_SPD_INFO]) { struct xfrmu_spdinfo *si; if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } si = RTA_DATA(tb[XFRMA_SPD_INFO]); fprintf(fp," IN %d", si->incnt); fprintf(fp," OUT %d", si->outcnt); fprintf(fp," FWD %d", si->fwdcnt); if (show_stats) { fprintf(fp," (Sock:"); fprintf(fp," IN %d", si->inscnt); fprintf(fp," OUT %d", si->outscnt); fprintf(fp," FWD %d", si->fwdscnt); fprintf(fp,")"); } fprintf(fp, "%s", _SL_); } if (show_stats > 1) { struct xfrmu_spdhinfo *sh; if (tb[XFRMA_SPD_HINFO]) { if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } sh = RTA_DATA(tb[XFRMA_SPD_HINFO]); fprintf(fp,"\t SPD buckets:"); fprintf(fp," count %d", sh->spdhcnt); fprintf(fp," Max %d", sh->spdhmcnt); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_SPD_IPV4_HTHRESH]) { struct xfrmu_spdhthresh *th; if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]); fprintf(fp,"\t SPD IPv4 thresholds:"); fprintf(fp," local %d", th->lbits); fprintf(fp," remote %d", th->rbits); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_SPD_IPV6_HTHRESH]) { struct xfrmu_spdhthresh *th; if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]); fprintf(fp,"\t SPD IPv6 thresholds:"); fprintf(fp," local %d", th->lbits); fprintf(fp," remote %d", th->rbits); fprintf(fp, "%s", _SL_); } } if (oneline) fprintf(fp, "\n"); return 0; }
struct ip4_routing_table * parse_nlmsg(struct nlmsghdr* msg) { char dst_temp[IP4_ALEN]; char gw_temp[IP4_ALEN]; unsigned int priority; unsigned int interface; struct ip4_routing_table *table_pointer = NULL; switch (msg->nlmsg_type) { case NLMSG_ERROR: { struct nlmsgerr* errorMsg = (struct nlmsgerr*) NLMSG_DATA(msg); PRINT_DEBUG("\nrecvd NLMSG_ERROR error seq:%d code:%d...", msg->nlmsg_seq, errorMsg->error); break; } case RTM_NEWROUTE: { struct rtmsg* rtm = (struct rtmsg*) NLMSG_DATA(msg); struct rtattr* rta = RTM_RTA(rtm); int rtaLen = msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); if (rtm->rtm_type == RTN_UNICAST) // don't consider local, broadcast and unreachable routes { table_pointer = (struct ip4_routing_table*) malloc( sizeof(struct ip4_routing_table)); memset(table_pointer, 0, sizeof(struct ip4_routing_table)); // zero the routing table entry data for (; RTA_OK(rta, rtaLen); rta = RTA_NEXT(rta, rtaLen)) { switch (rta->rta_type) { case RTA_DST: //destination table_pointer->mask = rtm->rtm_dst_len; memcpy(dst_temp, RTA_DATA(rta), IP4_ALEN); PRINT_DEBUG("received RTA_DST"); PRINT_DEBUG("dst_str = %u.%u.%u.%u", dst_temp[0]&0xFF, dst_temp[1]&0xFF, dst_temp[2]&0xFF, dst_temp[3]&0xFF); table_pointer->dst = IP4_ADR_P2N(dst_temp[0]&0xFF, dst_temp[1]&0xFF, dst_temp[2]&0xFF, dst_temp[3]&0xFF); break; case RTA_GATEWAY: //next hop table_pointer->mask = rtm->rtm_dst_len; memcpy(gw_temp, RTA_DATA(rta), IP4_ALEN); PRINT_DEBUG("received RTA_GATEWAY"); PRINT_DEBUG("gw_str = %u.%u.%u.%u",gw_temp[0]&0xFF, gw_temp[1]&0xFF, gw_temp[2]&0xFF, gw_temp[3]&0xFF); table_pointer->gw = IP4_ADR_P2N(gw_temp[0]&0xFF, gw_temp[1]&0xFF, gw_temp[2]&0xFF, gw_temp[3]&0xFF); break; case RTA_OIF: //interface memcpy(&table_pointer->interface, RTA_DATA(rta), sizeof(interface)); PRINT_DEBUG("interface:%u",table_pointer->interface); break; case RTA_PRIORITY: //metric memcpy(&table_pointer->metric, RTA_DATA(rta), sizeof(priority)); PRINT_DEBUG("metric:%u",table_pointer->metric); break; } //switch(rta->) }// for() } // if RTN_UNICAST return (table_pointer); } } //switch (msg->nlmsg_type) return (NULL); }
static void bionic_ifaddrs_recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq) { char buf[8192]; struct sockaddr_nl nladdr; struct iovec iov = { buf, sizeof(buf) }; struct ifaddrmsg *m; struct rtattr *rta_tb[IFA_MAX + 1]; struct ifaddrs *I; while (1) { int status; struct nlmsghdr *h; struct msghdr msg = { (void*) &nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; status = recvmsg(fd, &msg, 0); if (status <= 0 || nladdr.nl_pid) continue; h = (struct nlmsghdr*) buf; while (NLMSG_OK(h, status)) { if (h->nlmsg_seq != seq) goto skip_it; switch (h->nlmsg_type) { case NLMSG_DONE: return; case NLMSG_ERROR: return; case RTM_NEWADDR: break; default: goto skip_it; } m = NLMSG_DATA(h); #if HAVE_IPV6 if (m->ifa_family != AF_INET && m->ifa_family != AF_INET6) #else /* HAVE_IPV6 */ if (m->ifa_family != AF_INET) #endif /* !HAVE_IPV6 */ goto skip_it; if (m->ifa_flags & IFA_F_TENTATIVE) goto skip_it; memset(rta_tb, 0, sizeof(rta_tb)); bionic_ifaddrs_parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg))); if (rta_tb[IFA_LOCAL] == NULL) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (rta_tb[IFA_LOCAL] == NULL) goto skip_it; if (!(I = calloc(1, sizeof(struct ifaddrs)))) return; I->ifa_name = calloc(IFNAMSIZ, sizeof(char)); I->ifa_flags = m->ifa_index; I->ifa_addr = calloc(1, sizeof(struct sockaddr_storage)); I->ifa_addr->sa_family = m->ifa_family; I->ifa_dstaddr = calloc(1, sizeof(struct sockaddr_storage)); I->ifa_netmask = calloc(1, sizeof(struct sockaddr_storage)); switch (m->ifa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in*) I->ifa_addr; memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), sizeof(struct in_addr)); break; } case AF_INET6: { struct sockaddr_in6 *sin = (struct sockaddr_in6*) I->ifa_addr; memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), sizeof(struct in6_addr)); if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) sin->sin6_scope_id = I->ifa_flags; break; } default: break; } I->ifa_next = *ifa; *ifa = I; skip_it: h = NLMSG_NEXT(h, status); } if (msg.msg_flags & MSG_TRUNC) continue; } }
/* Netlink interface link lookup filter */ static int netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface_t *ifp; int i, len; char *name; ifi = NLMSG_DATA(h); if (h->nlmsg_type != RTM_NEWLINK) return 0; len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg)); if (len < 0) return -1; /* Interface name lookup */ memset(tb, 0, sizeof (tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *) RTA_DATA(tb[IFLA_IFNAME]); /* Return if loopback */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* Skip it if already exist */ ifp = if_get_by_ifname(name); if (ifp) { if (!ifp->vmac) { vmac_reflect_flags(ifi); ifp->flags = ifi->ifi_flags; } return 0; } /* Fill the interface structure */ ifp = (interface_t *) MALLOC(sizeof(interface_t)); memcpy(ifp->ifname, name, strlen(name)); ifp->ifindex = ifi->ifi_index; ifp->mtu = *(int *) RTA_DATA(tb[IFLA_MTU]); ifp->hw_type = ifi->ifi_type; if (!ifp->vmac) { vmac_reflect_flags(ifi); ifp->flags = ifi->ifi_flags; ifp->base_ifindex = ifi->ifi_index; } if (tb[IFLA_ADDRESS]) { int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); if (hw_addr_len > IF_HWADDR_MAX) log_message(LOG_ERR, "MAC address for %s is too large: %d", name, hw_addr_len); else { ifp->hw_addr_len = hw_addr_len; memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len); for (i = 0; i < hw_addr_len; i++) if (ifp->hw_addr[i] != 0) break; if (i == hw_addr_len) ifp->hw_addr_len = 0; else ifp->hw_addr_len = hw_addr_len; } } /* Queue this new interface_t */ if_add_queue(ifp); return 0; }
/** * virNetDevVPortProfileGetStatus: * * tb: top level netlink response attributes + values * vf: The virtual function used in the request * instanceId: instanceId of the interface (vm uuid in case of 802.1Qbh) * is8021Qbg: whether this function is call for 8021Qbg * status: pointer to a uint16 where the status will be written into * * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in * case of success, < 0 otherwise with error having been reported */ static int virNetDevVPortProfileGetStatus(struct nlattr **tb, int32_t vf, const unsigned char *instanceId, bool nltarget_kernel, bool is8021Qbg, uint16_t *status) { int rc = -1; struct nlattr *tb_port[IFLA_PORT_MAX + 1] = { NULL, }; if (vf == PORT_SELF_VF && nltarget_kernel) { if (tb[IFLA_PORT_SELF]) { if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF], ifla_port_policy)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("error parsing IFLA_PORT_SELF part")); goto cleanup; } } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IFLA_PORT_SELF is missing")); goto cleanup; } } else { if (tb[IFLA_VF_PORTS]) { int rem; bool found = false; struct nlattr *tb_vf_ports = { NULL, }; nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) { if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("error while iterating over " "IFLA_VF_PORTS part")); goto cleanup; } if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports, ifla_port_policy)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("error parsing IFLA_VF_PORT part")); goto cleanup; } if (instanceId && tb_port[IFLA_PORT_INSTANCE_UUID] && !memcmp(instanceId, (unsigned char *) RTA_DATA(tb_port[IFLA_PORT_INSTANCE_UUID]), VIR_UUID_BUFLEN) && tb_port[IFLA_PORT_VF] && vf == *(uint32_t *)RTA_DATA(tb_port[IFLA_PORT_VF])) { found = true; break; } } if (!found) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find netlink response with " "expected parameters")); goto cleanup; } } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IFLA_VF_PORTS is missing")); goto cleanup; } }
static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq) { char buf[8192]; struct sockaddr_nl nladdr; struct iovec iov = { buf, sizeof(buf) }; struct ifaddrmsg *m; struct rtattr * rta_tb[IFA_MAX+1]; struct ifaddrs *I; while (1) { int status; struct nlmsghdr *h; struct msghdr msg = { (void*)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; status = recvmsg(fd, &msg, 0); if (status < 0) continue; if (status == 0) return; if (nladdr.nl_pid) /* Message not from kernel */ continue; h = (struct nlmsghdr*)buf; while (NLMSG_OK(h, status)) { if (h->nlmsg_seq != seq) goto skip_it; if (h->nlmsg_type == NLMSG_DONE) return; if (h->nlmsg_type == NLMSG_ERROR) return; if (h->nlmsg_type != RTM_NEWADDR) goto skip_it; m = NLMSG_DATA(h); if (m->ifa_family != AF_INET && m->ifa_family != AF_INET6) goto skip_it; if (m->ifa_flags&IFA_F_TENTATIVE) goto skip_it; memset(rta_tb, 0, sizeof(rta_tb)); parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m))); if (rta_tb[IFA_LOCAL] == NULL) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (rta_tb[IFA_LOCAL] == NULL) goto skip_it; I = malloc(sizeof(struct ifaddrs)); if (!I) return; memset(I, 0, sizeof(*I)); I->ifa_ifindex = m->ifa_index; I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf; I->ifa_addr->sa_family = m->ifa_family; if (m->ifa_family == AF_INET) { struct sockaddr_in *sin = (void*)I->ifa_addr; memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4); } else { struct sockaddr_in6 *sin = (void*)I->ifa_addr; memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16); if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) sin->sin6_scope_id = I->ifa_ifindex; } I->ifa_next = *ifa; *ifa = I; skip_it: h = NLMSG_NEXT(h, status); } if (msg.msg_flags & MSG_TRUNC) continue; } return; }
static struct if_nameindex * if_nameindex_netlink (void) { struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; struct if_nameindex *idx = NULL; if (__netlink_open (&nh) < 0) return NULL; /* Tell the kernel that we wish to get a list of all active interfaces. Collect all data for every interface. */ if (__netlink_request (&nh, RTM_GETLINK) < 0) goto exit_free; /* Count the interfaces. */ unsigned int nifs = 0; for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next) { struct nlmsghdr *nlh; size_t size = nlp->size; if (nlp->nlh == NULL) continue; /* Walk through all entries we got from the kernel and look, which message type they contain. */ for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) { /* Check if the message is what we want. */ if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) continue; if (nlh->nlmsg_type == NLMSG_DONE) break; /* ok */ if (nlh->nlmsg_type == RTM_NEWLINK) ++nifs; } } idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); if (idx == NULL) { nomem: __set_errno (ENOBUFS); goto exit_free; } /* Add the interfaces. */ nifs = 0; for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next) { struct nlmsghdr *nlh; size_t size = nlp->size; if (nlp->nlh == NULL) continue; /* Walk through all entries we got from the kernel and look, which message type they contain. */ for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) { /* Check if the message is what we want. */ if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) continue; if (nlh->nlmsg_type == NLMSG_DONE) break; /* ok */ if (nlh->nlmsg_type == RTM_NEWLINK) { struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); struct rtattr *rta = IFLA_RTA (ifim); size_t rtasize = IFLA_PAYLOAD (nlh); idx[nifs].if_index = ifim->ifi_index; while (RTA_OK (rta, rtasize)) { char *rta_data = RTA_DATA (rta); size_t rta_payload = RTA_PAYLOAD (rta); if (rta->rta_type == IFLA_IFNAME) { idx[nifs].if_name = __strndup (rta_data, rta_payload); if (idx[nifs].if_name == NULL) { idx[nifs].if_index = 0; __if_freenameindex (idx); idx = NULL; goto nomem; } break; } rta = RTA_NEXT (rta, rtasize); } ++nifs; } } } idx[nifs].if_index = 0; idx[nifs].if_name = NULL; exit_free: __netlink_free_handle (&nh); __netlink_close (&nh); return idx; }
int fillup_entry_info(netsnmp_arp_entry *entry, struct nlmsghdr *nlmp) { struct ndmsg *rtmp; struct in6_addr *in6p; struct rtattr *tb[NDA_MAX + 1], *rta; size_t in_len, out_len; unsigned int i; int length; char addr[40]; u_char *buf; u_char *hwaddr; rtmp = (struct ndmsg *) NLMSG_DATA(nlmp); if (nlmp->nlmsg_type != RTM_NEWNEIGH) { snmp_log(LOG_ERR, "Wrong netlink message type %d\n", nlmp->nlmsg_type); return -1; } if (rtmp->ndm_state != NUD_NOARP) { memset(tb, 0, sizeof(struct rtattr *) * (NDA_MAX + 1)); length = nlmp->nlmsg_len - NLMSG_LENGTH(sizeof(*rtmp)); if (length < 0) { snmp_log(LOG_ERR, "netlink message length %d < %d is invalid\n", nlmp->nlmsg_len, NLMSG_LENGTH(sizeof(*rtmp))); return -1; } /* * this is what the kernel-removed NDA_RTA define did */ rta = ((struct rtattr *) (((char *) (rtmp)) + NLMSG_ALIGN(sizeof(struct ndmsg)))); while (RTA_OK(rta, length)) { if (rta->rta_type <= NDA_MAX) tb[rta->rta_type] = rta; rta = RTA_NEXT(rta, length); } if (length) { snmp_log(LOG_ERR, "Received uneven number of netlink" " messages - %d bytes remaining\n", length); return -1; } /* * Fill up the index */ entry->if_index = rtmp->ndm_ifindex; /* * Fill up ip address */ if (tb[NDA_DST]) { memset(&addr, '\0', sizeof(addr)); in6p = (struct in6_addr *) RTA_DATA(tb[NDA_DST]); sprintf(addr, NIP6_FMT, NIP6(*in6p)); in_len = entry->arp_ipaddress_len = sizeof(entry->arp_ipaddress); netsnmp_assert(16 == in_len); out_len = 0; buf = entry->arp_ipaddress; if (1 != netsnmp_hex_to_binary(&buf, &in_len, &out_len, 0, addr, ":")) { snmp_log(LOG_ERR, "error parsing '%s', skipping\n", entry->arp_ipaddress); return -1; } netsnmp_assert(16 == out_len); entry->arp_ipaddress_len = out_len; } if (tb[NDA_LLADDR]) { memset(&addr, '\0', sizeof(addr)); hwaddr = RTA_DATA(tb[NDA_LLADDR]); entry->arp_physaddress_len = RTA_PAYLOAD(tb[NDA_LLADDR]); buf = entry->arp_physaddress; for (i = 0; i < entry->arp_physaddress_len; i++) entry->arp_physaddress[i] = hwaddr[i]; } switch (rtmp->ndm_state) { case NUD_INCOMPLETE: entry->arp_state = INETNETTOMEDIASTATE_INCOMPLETE; break; case NUD_REACHABLE: case NUD_PERMANENT: entry->arp_state = INETNETTOMEDIASTATE_REACHABLE; break; case NUD_STALE: entry->arp_state = INETNETTOMEDIASTATE_STALE; break; case NUD_DELAY: entry->arp_state = INETNETTOMEDIASTATE_DELAY; break; case NUD_PROBE: entry->arp_state = INETNETTOMEDIASTATE_PROBE; break; case NUD_FAILED: entry->arp_state = INETNETTOMEDIASTATE_INVALID; break; case NUD_NONE: entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN; break; default: snmp_log(LOG_ERR, "Unrecognized ARP entry state %d", rtmp->ndm_state); break; } switch (rtmp->ndm_state) { case NUD_INCOMPLETE: case NUD_FAILED: case NUD_NONE: entry->arp_type = INETNETTOMEDIATYPE_INVALID; break; case NUD_REACHABLE: case NUD_STALE: case NUD_DELAY: case NUD_PROBE: entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC; break; case NUD_PERMANENT: entry->arp_type = INETNETTOMEDIATYPE_STATIC; break; default: entry->arp_type = INETNETTOMEDIATYPE_LOCAL; break; } } else { return -1; /* could not create data for this interface */ } return 0; }
static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) { struct rtmsg *r = NLMSG_DATA(n); inet_prefix dst; inet_prefix src; inet_prefix via; inet_prefix prefsrc; __u32 table; static int ip6_multiple_tables; table = rtm_get_table(r, tb); if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN) ip6_multiple_tables = 1; if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED)) return 0; if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) { if (filter.tb) { if (filter.tb == RT_TABLE_LOCAL) { if (r->rtm_type != RTN_LOCAL) return 0; } else if (filter.tb == RT_TABLE_MAIN) { if (r->rtm_type == RTN_LOCAL) return 0; } else { return 0; } } } else { if (filter.tb > 0 && filter.tb != table) return 0; } if ((filter.protocol^r->rtm_protocol)&filter.protocolmask) return 0; if ((filter.scope^r->rtm_scope)&filter.scopemask) return 0; if ((filter.type^r->rtm_type)&filter.typemask) return 0; if ((filter.tos^r->rtm_tos)&filter.tosmask) return 0; if (filter.rdst.family && (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len)) return 0; if (filter.mdst.family && (r->rtm_family != filter.mdst.family || (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len))) return 0; if (filter.rsrc.family && (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len)) return 0; if (filter.msrc.family && (r->rtm_family != filter.msrc.family || (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len))) return 0; if (filter.rvia.family && r->rtm_family != filter.rvia.family) return 0; if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family) return 0; memset(&dst, 0, sizeof(dst)); dst.family = r->rtm_family; if (tb[RTA_DST]) memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8); if (filter.rsrc.family || filter.msrc.family) { memset(&src, 0, sizeof(src)); src.family = r->rtm_family; if (tb[RTA_SRC]) memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8); } if (filter.rvia.bitlen>0) { memset(&via, 0, sizeof(via)); via.family = r->rtm_family; if (tb[RTA_GATEWAY]) memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8); } if (filter.rprefsrc.bitlen>0) { memset(&prefsrc, 0, sizeof(prefsrc)); prefsrc.family = r->rtm_family; if (tb[RTA_PREFSRC]) memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8); } if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen)) return 0; if (filter.mdst.family && filter.mdst.bitlen >= 0 && inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len)) return 0; if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen)) return 0; if (filter.msrc.family && filter.msrc.bitlen >= 0 && inet_addr_match(&src, &filter.msrc, r->rtm_src_len)) return 0; if (filter.rvia.family && inet_addr_match(&via, &filter.rvia, filter.rvia.bitlen)) return 0; if (filter.rprefsrc.family && inet_addr_match(&prefsrc, &filter.rprefsrc, filter.rprefsrc.bitlen)) return 0; if (filter.realmmask) { __u32 realms = 0; if (tb[RTA_FLOW]) realms = rta_getattr_u32(tb[RTA_FLOW]); if ((realms^filter.realm)&filter.realmmask) return 0; } if (filter.iifmask) { int iif = 0; if (tb[RTA_IIF]) iif = *(int*)RTA_DATA(tb[RTA_IIF]); if ((iif^filter.iif)&filter.iifmask) return 0; } if (filter.oifmask) { int oif = 0; if (tb[RTA_OIF]) oif = *(int*)RTA_DATA(tb[RTA_OIF]); if ((oif^filter.oif)&filter.oifmask) return 0; } if (filter.markmask) { int mark = 0; if (tb[RTA_MARK]) mark = *(int *)RTA_DATA(tb[RTA_MARK]); if ((mark ^ filter.mark) & filter.markmask) return 0; } if (filter.flushb && r->rtm_family == AF_INET6 && r->rtm_dst_len == 0 && r->rtm_type == RTN_UNREACHABLE && tb[RTA_PRIORITY] && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1) return 0; return 1; }
int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac) { char buf[8192]; struct ndmsg req; struct nlmsghdr *nlhdr; if (!gw_ip || !hw_mac) { return -1; } // Send RTM_GETNEIGH request req.ndm_family = AF_INET; req.ndm_ifindex = if_nametoindex(iface); req.ndm_state = NUD_REACHABLE; req.ndm_type = NDA_LLADDR; int sock = send_nl_req(RTM_GETNEIGH, 1, &req, sizeof(req)); // Read responses unsigned 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; unsigned char mac[6]; struct in_addr dst_ip; int correct_ip = 0; rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr); if ((rt_msg->rtm_family != AF_INET)) { 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 NDA_LLADDR: assert(RTA_PAYLOAD(rt_attr) == IFHWADDRLEN); memcpy(mac, RTA_DATA(rt_attr), IFHWADDRLEN); break; case NDA_DST: assert(RTA_PAYLOAD(rt_attr) == sizeof(dst_ip)); memcpy(&dst_ip, RTA_DATA(rt_attr), sizeof(dst_ip)); if (memcmp(&dst_ip, gw_ip, sizeof(dst_ip)) == 0) { correct_ip = 1; } break; } rt_attr = RTA_NEXT(rt_attr, rt_len); } if (correct_ip) { memcpy(hw_mac, mac, IFHWADDRLEN); return 0; } nlhdr = NLMSG_NEXT(nlhdr, nl_len); } return -1; }
int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[RTA_MAX+1]; char abuf[256]; int host_len = -1; __u32 table; SPRINT_BUF(b1); static int hz; if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) { fprintf(stderr, "Not a route: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE) return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } host_len = calc_host_len(r); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); table = rtm_get_table(r, tb); if (!filter_nlmsg(n, tb, host_len)) return 0; if (filter.flushb) { struct nlmsghdr *fn; if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { if (flush_update()) return -1; } fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELROUTE; fn->nlmsg_flags = NLM_F_REQUEST; fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) return 0; } if (n->nlmsg_type == RTM_DELROUTE) fprintf(fp, "Deleted "); if (r->rtm_type != RTN_UNICAST && !filter.type) fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); if (tb[RTA_DST]) { if (r->rtm_dst_len != host_len) { fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[RTA_DST]), RTA_DATA(tb[RTA_DST]), abuf, sizeof(abuf)), r->rtm_dst_len ); } else { fprintf(fp, "%s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_DST]), RTA_DATA(tb[RTA_DST]), abuf, sizeof(abuf)) ); } } else if (r->rtm_dst_len) { fprintf(fp, "0/%d ", r->rtm_dst_len); } else { fprintf(fp, "default "); } if (tb[RTA_SRC]) { if (r->rtm_src_len != host_len) { fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[RTA_SRC]), RTA_DATA(tb[RTA_SRC]), abuf, sizeof(abuf)), r->rtm_src_len ); } else { fprintf(fp, "from %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_SRC]), RTA_DATA(tb[RTA_SRC]), abuf, sizeof(abuf)) ); } } else if (r->rtm_src_len) { fprintf(fp, "from 0/%u ", r->rtm_src_len); } if (r->rtm_tos && filter.tosmask != -1) { SPRINT_BUF(b1); fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); } if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) { fprintf(fp, "via %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_GATEWAY]), RTA_DATA(tb[RTA_GATEWAY]), abuf, sizeof(abuf))); } if (tb[RTA_OIF] && filter.oifmask != -1) fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); if (!(r->rtm_flags&RTM_F_CLONED)) { if (table != RT_TABLE_MAIN && !filter.tb) fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); if (r->rtm_protocol != RTPROT_BOOT && filter.protocolmask != -1) fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1))); if (r->rtm_scope != RT_SCOPE_UNIVERSE && filter.scopemask != -1) fprintf(fp, " scope %s ", rtnl_rtscope_n2a(r->rtm_scope, b1, sizeof(b1))); } if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) { /* Do not use format_host(). It is our local addr and symbolic name will not be useful. */ fprintf(fp, " src %s ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[RTA_PREFSRC]), RTA_DATA(tb[RTA_PREFSRC]), abuf, sizeof(abuf))); } if (tb[RTA_PRIORITY]) fprintf(fp, " metric %u ", rta_getattr_u32(tb[RTA_PRIORITY])); if (r->rtm_flags & RTNH_F_DEAD) fprintf(fp, "dead "); if (r->rtm_flags & RTNH_F_ONLINK) fprintf(fp, "onlink "); if (r->rtm_flags & RTNH_F_PERVASIVE) fprintf(fp, "pervasive "); if (r->rtm_flags & RTM_F_NOTIFY) fprintf(fp, "notify "); if (tb[RTA_MARK]) { unsigned int mark = *(unsigned int*)RTA_DATA(tb[RTA_MARK]); if (mark) { if (mark >= 16) fprintf(fp, " mark 0x%x", mark); else fprintf(fp, " mark %u", mark); } } if (tb[RTA_FLOW] && filter.realmmask != ~0U) { __u32 to = rta_getattr_u32(tb[RTA_FLOW]); __u32 from = to>>16; to &= 0xFFFF; fprintf(fp, "realm%s ", from ? "s" : ""); if (from) { fprintf(fp, "%s/", rtnl_rtrealm_n2a(from, b1, sizeof(b1))); } fprintf(fp, "%s ", rtnl_rtrealm_n2a(to, b1, sizeof(b1))); }
json_t* make_interface_file() { json_t *interfaces_json = json_object(); json_t *ifTable_json = json_object(); json_t *ifEntry_array = json_array(); struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } if (rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } struct nlmsg_list *linfo = NULL; if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } struct nlmsg_list *l, *n; for (l = linfo; l; l = n) { n = l->next; struct nlmsghdr *nlhdr = &(l->h); struct ifinfomsg *ifimsg = NLMSG_DATA(nlhdr); // Process Data of Netlink Message as ifinfomsg if (ifimsg->ifi_family != AF_UNSPEC && ifimsg->ifi_family != AF_INET6) { printf("error family: %d\n", ifimsg->ifi_family); continue; } // Add Each Parameter to json file json_t *interface_json = json_object(); json_t *linux_json = json_object(); json_object_set_new(interface_json, "ifIndex", json_integer(ifimsg->ifi_index)); json_object_set_new(linux_json, "ifi_type", json_integer(ifimsg->ifi_type)); json_object_set_new(linux_json, "ifi_flags", json_integer(ifimsg->ifi_flags)); // Analyze rtattr Message int len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifimsg));; struct rtattr *tb[IFLA_MAX+1]; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifimsg), len); if (tb[IFLA_IFNAME]) { // printf("\n%s\n", (char *)RTA_DATA(tb[IFLA_IFNAME])); json_object_set_new(interface_json, "ifDscr", json_string((char *)RTA_DATA(tb[IFLA_IFNAME]))); } if (tb[IFLA_MTU]) { // printf("%d\n", *(int *)RTA_DATA(tb[IFLA_MTU])); json_object_set_new(interface_json, "ifMtu", json_integer(*(int *)RTA_DATA(tb[IFLA_MTU]))); } static const char *oper_states[] = { "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN", "TESTING", "DORMANT", "UP" }; if (tb[IFLA_OPERSTATE]) { __u8 state = *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]); if (state >= sizeof(oper_states)/sizeof(oper_states[0])){ fprintf(stderr, "state %#x ", state); } else{ // printf("state %s ", oper_states[state]); json_object_set_new(interface_json, "ifOperStatus", json_string(oper_states[state])); } } if (tb[IFLA_ADDRESS]) { char abuf[64]; json_object_set_new(interface_json, "ifPhysAddress", json_string(ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), RTA_PAYLOAD(tb[IFLA_ADDRESS]), ifimsg->ifi_type, abuf, sizeof(abuf)))); } if (tb[IFLA_LINKINFO]) { struct rtattr *linkinfo[IFLA_INFO_MAX+1]; char *kind; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_KIND]){ json_object_set_new(interface_json, "IFLA_LINKINFO", json_integer((int)RTA_DATA(tb[IFLA_LINKINFO]))); // printf("%d\n", (int)RTA_DATA(tb[IFLA_LINKINFO])); // continue; } else { kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); if (strcmp(kind, "bridge") == 0 && tb[IFLA_IFNAME]) { json_object_set_new(interface_json, "ifType", json_string(kind)); char *bridge_name = (char *)RTA_DATA(tb[IFLA_IFNAME]); json_t *bridge_list_json = get_bridge_name(bridge_name); json_object_set_new(linux_json, "bridge", bridge_list_json); } else { continue; } } } json_object_set_new(interface_json, "linux", linux_json); json_array_append(ifEntry_array, interface_json); } json_object_set_new(ifTable_json, "ifEntry", ifEntry_array); json_object_set_new(interfaces_json, "ifTable", ifTable_json); free(l); rtnl_close(&rth); return interfaces_json; }
/* * With an existing policy of nlmsg, make new nlmsg for deleting the policy * and store it to buffer. */ static int xfrm_policy_keep(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct xfrm_buffer *xb = (struct xfrm_buffer *)arg; struct rtnl_handle *rth = xb->rth; struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[XFRMA_MAX+1]; __u8 ptype = XFRM_POLICY_TYPE_MAIN; struct nlmsghdr *new_n; struct xfrm_userpolicy_id *xpid; if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) { fprintf(stderr, "Not a policy: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*xpinfo)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } parse_rtattr(tb, XFRMA_MAX, XFRMP_RTA(xpinfo), len); if (tb[XFRMA_POLICY_TYPE]) { struct xfrm_userpolicy_type *upt; if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) { fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n"); return -1; } upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]); ptype = upt->type; } if (!xfrm_policy_filter_match(xpinfo, ptype)) return 0; if (xb->offset > xb->size) { fprintf(stderr, "Policy buffer overflow\n"); return -1; } new_n = (struct nlmsghdr *)(xb->buf + xb->offset); new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xpid)); new_n->nlmsg_flags = NLM_F_REQUEST; new_n->nlmsg_type = XFRM_MSG_DELPOLICY; new_n->nlmsg_seq = ++rth->seq; xpid = NLMSG_DATA(new_n); memcpy(&xpid->sel, &xpinfo->sel, sizeof(xpid->sel)); xpid->dir = xpinfo->dir; xpid->index = xpinfo->index; xb->offset += new_n->nlmsg_len; xb->nlmsg_count ++; return 0; }
static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, unsigned int flags) { struct ifinfomsg *r; struct nlmsghdr *nlh; unsigned char *b = skb->tail; nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags); r = NLMSG_DATA(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = change; RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); if (1) { u32 txqlen = dev->tx_queue_len; RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); } if (1) { u32 weight = dev->weight; RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); } if (1) { u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN; u8 link_mode = dev->link_mode; RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode); } if (1) { struct rtnl_link_ifmap map = { .mem_start = dev->mem_start, .mem_end = dev->mem_end, .base_addr = dev->base_addr, .irq = dev->irq, .dma = dev->dma, .port = dev->if_port, }; RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); } if (dev->addr_len) { RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); } if (1) { u32 mtu = dev->mtu; RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); } if (dev->ifindex != dev->iflink) { u32 iflink = dev->iflink; RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); } if (dev->qdisc_sleeping) RTA_PUT(skb, IFLA_QDISC, strlen(dev->qdisc_sleeping->ops->id) + 1, dev->qdisc_sleeping->ops->id); if (dev->master) { u32 master = dev->master->ifindex; RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); } if (dev->get_stats) { unsigned long *stats = (unsigned long*)dev->get_stats(dev); if (stats) { struct rtattr *a; __u32 *s; int i; int n = sizeof(struct rtnl_link_stats)/4; a = __RTA_PUT(skb, IFLA_STATS, n*4); s = RTA_DATA(a); for (i=0; i<n; i++) s[i] = stats[i]; } } nlh->nlmsg_len = skb->tail - b; return skb->len; nlmsg_failure: rtattr_failure: skb_trim(skb, b - skb->data); return -1; } static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { int idx; int s_idx = cb->args[0]; struct net_device *dev; read_lock(&dev_base_lock); for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) break; } read_unlock(&dev_base_lock); cb->args[0] = idx; return skb->len; }
/* n = the response to a CTRL_CMD_GETFAMILY message */ static int genl_get_mcast_group_id(struct nlmsghdr *n) { /* * Attribute table. Note the type name "rtattr" which means "route * attribute". This is a vestige of one of netlink's main uses: * routing. */ struct rtattr *tb[CTRL_ATTR_MAX + 1]; /* place for the generic netlink header in the incoming message */ struct genlmsghdr ghdr; /* length of the attribute and payload */ int len = n->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN); /* Pointer to the attribute portion of the message */ struct rtattr *attrs; if (len < 0) { printf("Netlink: CTRL_CMD_GETFAMILY response, " "wrong controller message len: %d\n", len); return -1; } if (n->nlmsg_type != GENL_ID_CTRL) { printf("Netlink: Not a controller message, nlmsg_len=%d " "nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type); return 0; } /* copy generic netlink header into structure */ memcpy(&ghdr, NLMSG_DATA(n), GENL_HDRLEN); if (ghdr.cmd != CTRL_CMD_GETFAMILY && ghdr.cmd != CTRL_CMD_DELFAMILY && ghdr.cmd != CTRL_CMD_NEWFAMILY && ghdr.cmd != CTRL_CMD_NEWMCAST_GRP && ghdr.cmd != CTRL_CMD_DELMCAST_GRP) { printf("Netlink: Unknown controller command %d\n", ghdr.cmd); return 0; } /* set attrs to point to the attribute */ attrs = (struct rtattr *)(NLMSG_DATA(n) + GENL_HDRLEN); /* Read the table from the message into "tb". This actually just */ /* places pointers into the message into tb[]. */ parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); /* if a family ID attribute is present, get it */ if (tb[CTRL_ATTR_FAMILY_ID]) { acpi_event_family_id = *((__u32 *)RTA_DATA(tb[CTRL_ATTR_FAMILY_ID])); } /* if a "multicast groups" attribute is present... */ if (tb[CTRL_ATTR_MCAST_GROUPS]) { struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1]; int i; /* get the group table within this attribute */ parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS, tb[CTRL_ATTR_MCAST_GROUPS]); /* for each group */ for (i = 0; i < GENL_MAX_FAM_GRPS; i++) /* if this group is valid */ if (tb2[i]) /* Parse the ID. If successful, we're done. */ if (!get_ctrl_grp_id(tb2[i])) return 0; } return -1; }
static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct ifinfomsg *ifm = NLMSG_DATA(nlh); struct rtattr **ida = arg; struct net_device *dev; int err, send_addr_notify = 0; if (ifm->ifi_index >= 0) dev = dev_get_by_index(ifm->ifi_index); else if (ida[IFLA_IFNAME - 1]) { char ifname[IFNAMSIZ]; if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], IFNAMSIZ) >= IFNAMSIZ) return -EINVAL; dev = dev_get_by_name(ifname); } else return -EINVAL; if (!dev) return -ENODEV; err = -EINVAL; if (ifm->ifi_flags) dev_change_flags(dev, ifm->ifi_flags); if (ida[IFLA_MAP - 1]) { struct rtnl_link_ifmap *u_map; struct ifmap k_map; if (!dev->set_config) { err = -EOPNOTSUPP; goto out; } if (!netif_device_present(dev)) { err = -ENODEV; goto out; } if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map))) goto out; u_map = RTA_DATA(ida[IFLA_MAP - 1]); k_map.mem_start = (unsigned long) u_map->mem_start; k_map.mem_end = (unsigned long) u_map->mem_end; k_map.base_addr = (unsigned short) u_map->base_addr; k_map.irq = (unsigned char) u_map->irq; k_map.dma = (unsigned char) u_map->dma; k_map.port = (unsigned char) u_map->port; err = dev->set_config(dev, &k_map); if (err) goto out; } if (ida[IFLA_ADDRESS - 1]) { struct sockaddr *sa; int len; if (!dev->set_mac_address) { err = -EOPNOTSUPP; goto out; } if (!netif_device_present(dev)) { err = -ENODEV; goto out; } if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) goto out; len = sizeof(sa_family_t) + dev->addr_len; sa = kmalloc(len, GFP_KERNEL); if (!sa) { err = -ENOMEM; goto out; } sa->sa_family = dev->type; memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]), dev->addr_len); err = dev->set_mac_address(dev, sa); kfree(sa); if (err) goto out; send_addr_notify = 1; } if (ida[IFLA_BROADCAST - 1]) { if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) goto out; memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), dev->addr_len); send_addr_notify = 1; } if (ida[IFLA_MTU - 1]) { if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32))) goto out; err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1]))); if (err) goto out; } if (ida[IFLA_TXQLEN - 1]) { if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32))) goto out; dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1])); } if (ida[IFLA_WEIGHT - 1]) { if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32))) goto out; dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); } if (ida[IFLA_OPERSTATE - 1]) { if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) goto out; set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1]))); } if (ida[IFLA_LINKMODE - 1]) { if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) goto out; write_lock_bh(&dev_base_lock); dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1])); write_unlock_bh(&dev_base_lock); } if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { char ifname[IFNAMSIZ]; if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], IFNAMSIZ) >= IFNAMSIZ) goto out; err = dev_change_name(dev, ifname); if (err) goto out; } #ifdef CONFIG_NET_WIRELESS_RTNETLINK if (ida[IFLA_WIRELESS - 1]) { /* Call Wireless Extensions. * Various stuff checked in there... */ err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); if (err) goto out; } #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ err = 0; out: if (send_addr_notify) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); dev_put(dev); return err; }
static int addr2mac_init_linux() { struct nlmsghdr *nlmsg; struct ndmsg *ndmsg; struct rtattr *rta, *tb[NDA_MAX]; struct sockaddr_nl snl; struct msghdr msg; struct iovec iov; struct timeval tv; pid_t pid; uint8_t buf[16384]; ssize_t ssize; ssize_t len; int rlen; int fd = -1; void *ip, *mac; int iptype; pid = getpid(); memset(buf, 0, sizeof(buf)); nlmsg = (struct nlmsghdr *)buf; nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); nlmsg->nlmsg_type = RTM_GETNEIGH; nlmsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH; nlmsg->nlmsg_seq = 0; nlmsg->nlmsg_pid = pid; ndmsg = NLMSG_DATA(nlmsg); ndmsg->ndm_family = AF_UNSPEC; if((fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { printerror(errno, strerror, __func__, "could not open netlink"); goto err; } len = nlmsg->nlmsg_len; if((ssize = send(fd, buf, len, 0)) < len) { if(ssize == -1) { printerror(errno, strerror, __func__, "could not send netlink"); } goto err; } for(;;) { iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_name = &snl; msg.msg_namelen = sizeof(snl); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; if((len = recvmsg(fd, &msg, 0)) == -1) { if(errno == EINTR) continue; printerror(errno, strerror, __func__, "could not recvmsg"); goto err; } gettimeofday_wrap(&tv); nlmsg = (struct nlmsghdr *)buf; while(NLMSG_OK(nlmsg, len)) { if(nlmsg->nlmsg_pid != pid || nlmsg->nlmsg_seq != 0) { goto skip; } if(nlmsg->nlmsg_type == NLMSG_DONE) { goto done; } if(nlmsg->nlmsg_type == NLMSG_ERROR) { scamper_debug(__func__, "nlmsg error"); goto err; } /* get current neighbour entries only */ if(nlmsg->nlmsg_type != RTM_NEWNEIGH) { goto skip; } /* make sure the address is reachable */ ndmsg = NLMSG_DATA(nlmsg); if((ndmsg->ndm_state & NUD_REACHABLE) == 0) { goto skip; } /* make sure we can process this address type */ switch(ndmsg->ndm_family) { case AF_INET: iptype = SCAMPER_ADDR_TYPE_IPV4; break; case AF_INET6: iptype = SCAMPER_ADDR_TYPE_IPV6; break; default: goto skip; } /* fill a table with parameters from the payload */ memset(tb, 0, sizeof(tb)); rlen = nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); for(rta = NDA_RTA(ndmsg); RTA_OK(rta,rlen); rta = RTA_NEXT(rta,rlen)) { if(rta->rta_type >= NDA_MAX) continue; tb[rta->rta_type] = rta; } /* * skip if we don't have a destination IP address, or if * we don't have an ethernet mac address */ if(tb[NDA_DST] == NULL || tb[NDA_LLADDR] == NULL || RTA_PAYLOAD(tb[NDA_LLADDR]) != 6) { goto skip; } ip = RTA_DATA(tb[NDA_DST]); mac = RTA_DATA(tb[NDA_LLADDR]); addr2mac_add(ndmsg->ndm_ifindex, iptype, ip, mac, tv.tv_sec+600); skip: nlmsg = NLMSG_NEXT(nlmsg, len); } } done: close(fd); return 0; err: close(fd); return -1; }
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) { struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); struct rtattr **ida = arg; struct net_device *dev; struct ifinfomsg *r; struct nlmsghdr *nlh; int err = -ENOBUFS; struct sk_buff *skb; unsigned char *b; char *iw_buf = NULL; int iw_buf_len = 0; if (ifm->ifi_index >= 0) dev = dev_get_by_index(ifm->ifi_index); else return -EINVAL; if (!dev) return -ENODEV; #ifdef CONFIG_NET_WIRELESS_RTNETLINK if (ida[IFLA_WIRELESS - 1]) { /* Call Wireless Extensions. We need to know the size before * we can alloc. Various stuff checked in there... */ err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); if (err) goto out; } #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ /* Create a skb big enough to include all the data. * Some requests are way bigger than 4k... Jean II */ skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), GFP_KERNEL); if (!skb) goto out; b = skb->tail; /* Put in the message the usual good stuff */ nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, RTM_NEWLINK, sizeof(*r)); r = NLMSG_DATA(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev->flags; r->ifi_change = 0; /* Put the wireless payload if it exist */ if(iw_buf != NULL) RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, iw_buf + IW_EV_POINT_OFF); nlh->nlmsg_len = skb->tail - b; /* Needed ? */ NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); if (err > 0) err = 0; out: if(iw_buf != NULL) kfree(iw_buf); dev_put(dev); return err; rtattr_failure: nlmsg_failure: kfree_skb(skb); goto out; }
int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct prefixmsg *prefix = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[RTA_MAX+1]; int family = preferred_family; if (n->nlmsg_type != RTM_NEWPREFIX) { fprintf(stderr, "Not a prefix: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*prefix)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (family == AF_UNSPEC) family = AF_INET6; if (family != AF_INET6) return 0; if (prefix->prefix_family != AF_INET6) { fprintf(stderr, "wrong family %d\n", prefix->prefix_family); return 0; } if (prefix->prefix_type != ND_OPT_PREFIX_INFORMATION) { fprintf(stderr, "wrong ND type %d\n", prefix->prefix_type); return 0; } parse_rtattr(tb, RTA_MAX, RTM_RTA(prefix), len); fprintf(fp, "prefix "); if (tb[PREFIX_ADDRESS]) { struct in6_addr *pfx; char abuf[256]; pfx = (struct in6_addr *)RTA_DATA(tb[PREFIX_ADDRESS]); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*pfx), pfx, abuf, sizeof(abuf))); } fprintf(fp, "/%u ", prefix->prefix_len); fprintf(fp, "dev %s ", ll_index_to_name(prefix->prefix_ifindex)); if (prefix->prefix_flags & IF_PREFIX_ONLINK) fprintf(fp, "onlink "); if (prefix->prefix_flags & IF_PREFIX_AUTOCONF) fprintf(fp, "autoconf "); if (tb[PREFIX_CACHEINFO]) { struct prefix_cacheinfo *pc; pc = (struct prefix_cacheinfo *)tb[PREFIX_CACHEINFO]; fprintf(fp, "valid %u ", pc->valid_time); fprintf(fp, "preferred %u ", pc->preferred_time); } fprintf(fp, "\n"); fflush(fp); return 0; }
static int netlink_getack(int fd) { struct { struct nlmsghdr nlh; char buf[SIZE_NLMSG]; } resp; struct iovec iov = { &resp, sizeof(resp), }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, }; ssize_t ret; struct nlmsghdr *nlh = &resp.nlh; ret = recvmsg(fd, &msg, 0); if (ret == -1) return -errno; if (msg.msg_flags & MSG_TRUNC) return -EIO; for (; NLMSG_OK(nlh, (size_t)ret); nlh = NLMSG_NEXT(nlh, ret)) { if (nlh->nlmsg_type == NLMSG_DONE) return 0; if (nlh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = NLMSG_DATA(nlh); return err->error; } } return -EIO; } /* Set local address */ static int netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local) { struct ifaddrmsg *ifa; struct rtattr *rta; uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*ifa)) + RTA_SPACE(1)); struct req { struct nlmsghdr nlh; char buf[512]; } req = { .nlh = { .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, .nlmsg_type = RTM_NEWADDR, .nlmsg_pid = getpid(), .nlmsg_len = reqlen, }, }; int fd; int error; struct sockaddr_nl addr = { .nl_family = AF_NETLINK, }; ifa = NLMSG_DATA(&req.nlh); ifa->ifa_family = AF_PHONET; ifa->ifa_prefixlen = 0; ifa->ifa_index = ifa_index; rta = IFA_RTA(ifa); rta->rta_type = IFA_LOCAL; rta->rta_len = RTA_LENGTH(1); *(uint8_t *)RTA_DATA(rta) = ifa_local; fd = netlink_socket(); if (fd == -1) return -errno; if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1) error = -errno; else error = netlink_getack(fd); close(fd); return error; } int g_pn_netlink_set_address(GIsiModem *idx, uint8_t local) { uint32_t ifindex = g_isi_modem_index(idx); if (ifindex == 0) return -ENODEV; if (local != PN_DEV_PC && local != PN_DEV_SOS) return -EINVAL; return netlink_setaddr(ifindex, local); }
static void rtnl_print_ifaddr(struct nlmsghdr *hdr) { struct ifaddrmsg *ifa = NLMSG_DATA(hdr); uint32_t attrs_len = IFA_PAYLOAD(hdr); struct rtattr *attr = IFA_RTA(ifa); struct ifa_cacheinfo *ci; char addr_str[256]; char flags[256]; tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family, colorize_start(bold), addr_family2str(ifa->ifa_family), colorize_end()); tprintf(", Prefix Len %d", ifa->ifa_prefixlen); tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags, colorize_start(bold), rtnl_addr_flags2str(ifa->ifa_flags, flags, sizeof(flags)), colorize_end()); tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope, colorize_start(bold), scope2str(ifa->ifa_scope), colorize_end()); tprintf(", Link Index %d ]\n", ifa->ifa_index); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case IFA_LOCAL: attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_ADDRESS: attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_BROADCAST: attr_fmt(attr, "Broadcast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_MULTICAST: attr_fmt(attr, "Multicast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_ANYCAST: attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; #ifdef IFA_FLAGS case IFA_FLAGS: attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr), colorize_start(bold), rtnl_addr_flags2str(RTA_INT(attr), flags, sizeof(flags)), colorize_end()); break; #endif case IFA_LABEL: attr_fmt(attr, "Label %s", RTA_STR(attr)); break; case IFA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); if (ci->ifa_valid == INFINITY) tprintf("valid lft(forever)"); else tprintf("valid lft(%us)", ci->ifa_valid); if (ci->ifa_prefered == INFINITY) tprintf(", prefrd lft(forever)"); else tprintf(", prefrd lft(%us)", ci->ifa_prefered); tprintf(", created on(%.2fs)", (double)ci->cstamp / 100); tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100); tprintf(", Len %lu\n", RTA_LEN(attr)); break; } } }
int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ndmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[NDA_MAX+1]; char abuf[256]; if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) { fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (filter.flushb && n->nlmsg_type != RTM_NEWNEIGH) return 0; if (filter.family && filter.family != r->ndm_family) return 0; if (filter.index && filter.index != r->ndm_ifindex) return 0; if (!(filter.state&r->ndm_state) && (r->ndm_state || !(filter.state&0x100)) && (r->ndm_family != AF_DECnet)) return 0; parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); if (tb[NDA_DST]) { if (filter.pfx.family) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = r->ndm_family; memcpy(&dst.data, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) return 0; } } if (filter.unused_only && tb[NDA_CACHEINFO]) { struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); if (ci->ndm_refcnt) return 0; } if (filter.flushb) { struct nlmsghdr *fn; if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { if (flush_update()) return -1; } fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELNEIGH; fn->nlmsg_flags = NLM_F_REQUEST; fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) return 0; } if (tb[NDA_DST]) { fprintf(fp, "%s ", format_host(r->ndm_family, RTA_PAYLOAD(tb[NDA_DST]), RTA_DATA(tb[NDA_DST]), abuf, sizeof(abuf))); } if (!filter.index && r->ndm_ifindex) fprintf(fp, "dev %s ", ll_index_to_name(r->ndm_ifindex)); if (tb[NDA_LLADDR]) { SPRINT_BUF(b1); fprintf(fp, "lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR]), ll_index_to_type(r->ndm_ifindex), b1, sizeof(b1))); } if (r->ndm_flags & NTF_ROUTER) { fprintf(fp, " router"); } if (tb[NDA_CACHEINFO] && show_stats) { struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); int hz = get_user_hz(); if (ci->ndm_refcnt) printf(" ref %d", ci->ndm_refcnt); fprintf(fp, " used %d/%d/%d", ci->ndm_used/hz, ci->ndm_confirmed/hz, ci->ndm_updated/hz); } if (tb[NDA_PROBES] && show_stats) { __u32 p = *(__u32 *) RTA_DATA(tb[NDA_PROBES]); fprintf(fp, " probes %u", p); } if (r->ndm_state) { int nud = r->ndm_state; fprintf(fp, " "); #define PRINT_FLAG(f) if (nud & NUD_##f) { \ nud &= ~NUD_##f; fprintf(fp, #f "%s", nud ? "," : ""); } PRINT_FLAG(INCOMPLETE); PRINT_FLAG(REACHABLE); PRINT_FLAG(STALE); PRINT_FLAG(DELAY); PRINT_FLAG(PROBE); PRINT_FLAG(FAILED); PRINT_FLAG(NOARP); PRINT_FLAG(PERMANENT); #undef PRINT_FLAG } fprintf(fp, "\n"); fflush(fp); return 0; }
static void rtnl_print_neigh(struct nlmsghdr *hdr) { struct ndmsg *ndm = NLMSG_DATA(hdr); uint32_t attrs_len = NDA_PAYLOAD(hdr); struct rtattr *attr = NDA_RTA(ndm); struct nda_cacheinfo *ci; int hz = get_user_hz(); char addr_str[256]; char hw_addr[30]; char states[256]; char flags[256]; tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family, colorize_start(bold), addr_family2str(ndm->ndm_family), colorize_end()); tprintf(", Link Index %d", ndm->ndm_ifindex); tprintf(", State %d (%s%s%s)", ndm->ndm_state, colorize_start(bold), flags2str(neigh_states, ndm->ndm_state, states, sizeof(states)), colorize_end()); tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags, colorize_start(bold), flags2str(neigh_flags, ndm->ndm_flags, flags, sizeof(flags)), colorize_end()); tprintf(", Type %d (%s%s%s)", ndm->ndm_type, colorize_start(bold), route_type2str(ndm->ndm_type), colorize_end()); tprintf(" ]\n"); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case NDA_DST: attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case NDA_LLADDR: attr_fmt(attr, "HW Address %s", device_addr2str(RTA_DATA(attr), RTA_LEN(attr), 0, hw_addr, sizeof(hw_addr))); break; case NDA_PROBES: attr_fmt(attr, "Probes %d", RTA_UINT32(attr)); break; case NDA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); tprintf("confirmed(%ds)", ci->ndm_confirmed / hz); tprintf(", used(%ds)", ci->ndm_used / hz); tprintf(", updated(%ds)", ci->ndm_updated / hz); tprintf(", refcnt(%d))", ci->ndm_refcnt); tprintf(", Len %lu\n", RTA_LEN(attr)); break; } } }
int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX+1]; int len = n->nlmsg_len; unsigned m_flag = 0; if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (filter.ifindex && ifi->ifi_index != filter.ifindex) return 0; if (filter.up && !(ifi->ifi_flags&IFF_UP)) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index); } if (filter.label && (!filter.family || filter.family == AF_PACKET) && fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) return 0; if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: %s", ifi->ifi_index, tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>"); if (tb[IFLA_LINK]) { SPRINT_BUF(b1); int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); if (iflink == 0) fprintf(fp, "@NONE: "); else { fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); m_flag = ll_index_to_flags(iflink); m_flag = !(m_flag & IFF_UP); } } else { fprintf(fp, ": "); } print_link_flags(fp, ifi->ifi_flags, m_flag); if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); if (tb[IFLA_QDISC]) fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC])); #ifdef IFLA_MASTER if (tb[IFLA_MASTER]) { SPRINT_BUF(b1); fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); } #endif if (tb[IFLA_OPERSTATE]) print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE])); if (filter.showqueue) print_queuelen(fp, (char*)RTA_DATA(tb[IFLA_IFNAME])); if (!filter.family || filter.family == AF_PACKET) { SPRINT_BUF(b1); fprintf(fp, "%s", _SL_); fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1))); if (tb[IFLA_ADDRESS]) { fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), RTA_PAYLOAD(tb[IFLA_ADDRESS]), ifi->ifi_type, b1, sizeof(b1))); } if (tb[IFLA_BROADCAST]) { if (ifi->ifi_flags&IFF_POINTOPOINT) fprintf(fp, " peer "); else fprintf(fp, " brd "); fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]), RTA_PAYLOAD(tb[IFLA_BROADCAST]), ifi->ifi_type, b1, sizeof(b1))); } } if (do_link && tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); if (do_link && tb[IFLA_IFALIAS]) fprintf(fp,"\n alias %s", (const char *) RTA_DATA(tb[IFLA_IFALIAS])); if (do_link && tb[IFLA_STATS64] && show_stats) { struct rtnl_link_stats64 slocal; struct rtnl_link_stats64 *s = RTA_DATA(tb[IFLA_STATS64]); if (((unsigned long)s) & (sizeof(unsigned long)-1)) { memcpy(&slocal, s, sizeof(slocal)); s = &slocal; } fprintf(fp, "%s", _SL_); fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", s->rx_compressed ? "compressed" : "", _SL_); fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu", (unsigned long long)s->rx_bytes, (unsigned long long)s->rx_packets, (unsigned long long)s->rx_errors, (unsigned long long)s->rx_dropped, (unsigned long long)s->rx_over_errors, (unsigned long long)s->multicast); if (s->rx_compressed) fprintf(fp, " %-7llu", (unsigned long long)s->rx_compressed); if (show_stats > 1) { fprintf(fp, "%s", _SL_); fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); fprintf(fp, " %-7llu %-7llu %-7llu %-7llu %-7llu", (unsigned long long)s->rx_length_errors, (unsigned long long)s->rx_crc_errors, (unsigned long long)s->rx_frame_errors, (unsigned long long)s->rx_fifo_errors, (unsigned long long)s->rx_missed_errors); } fprintf(fp, "%s", _SL_); fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", s->tx_compressed ? "compressed" : "", _SL_); fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu", (unsigned long long)s->tx_bytes, (unsigned long long)s->tx_packets, (unsigned long long)s->tx_errors, (unsigned long long)s->tx_dropped, (unsigned long long)s->tx_carrier_errors, (unsigned long long)s->collisions); if (s->tx_compressed) fprintf(fp, " %-7llu", (unsigned long long)s->tx_compressed); if (show_stats > 1) { fprintf(fp, "%s", _SL_); fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); fprintf(fp, " %-7llu %-7llu %-7llu %-7llu", (unsigned long long)s->tx_aborted_errors, (unsigned long long)s->tx_fifo_errors, (unsigned long long)s->tx_window_errors, (unsigned long long)s->tx_heartbeat_errors); } } if (do_link && !tb[IFLA_STATS64] && tb[IFLA_STATS] && show_stats) { struct rtnl_link_stats slocal; struct rtnl_link_stats *s = RTA_DATA(tb[IFLA_STATS]); if (((unsigned long)s) & (sizeof(unsigned long)-1)) { memcpy(&slocal, s, sizeof(slocal)); s = &slocal; } fprintf(fp, "%s", _SL_); fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", s->rx_compressed ? "compressed" : "", _SL_); fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", s->rx_bytes, s->rx_packets, s->rx_errors, s->rx_dropped, s->rx_over_errors, s->multicast ); if (s->rx_compressed) fprintf(fp, " %-7u", s->rx_compressed); if (show_stats > 1) { fprintf(fp, "%s", _SL_); fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); fprintf(fp, " %-7u %-7u %-7u %-7u %-7u", s->rx_length_errors, s->rx_crc_errors, s->rx_frame_errors, s->rx_fifo_errors, s->rx_missed_errors ); } fprintf(fp, "%s", _SL_); fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", s->tx_compressed ? "compressed" : "", _SL_); fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", s->tx_bytes, s->tx_packets, s->tx_errors, s->tx_dropped, s->tx_carrier_errors, s->collisions); if (s->tx_compressed) fprintf(fp, " %-7u", s->tx_compressed); if (show_stats > 1) { fprintf(fp, "%s", _SL_); fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); fprintf(fp, " %-7u %-7u %-7u %-7u", s->tx_aborted_errors, s->tx_fifo_errors, s->tx_window_errors, s->tx_heartbeat_errors ); } } if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST]; int rem = RTA_PAYLOAD(vflist); for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) print_vfinfo(fp, i); } fprintf(fp, "\n"); fflush(fp); return 0; }