int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { int h; struct ifinfomsg *ifi = NLMSG_DATA(n); struct idxmap *im, **imp; struct rtattr *tb[IFLA_MAX+1]; if (n->nlmsg_type != RTM_NEWLINK) return 0; if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) return -1; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); if (tb[IFLA_IFNAME] == NULL) return 0; h = ifi->ifi_index&0xF; for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next) if (im->index == ifi->ifi_index) break; if (im == NULL) { im = malloc(sizeof(*im)); if (im == NULL) return 0; im->next = *imp; im->index = ifi->ifi_index; *imp = im; } im->type = ifi->ifi_type; im->flags = ifi->ifi_flags; if (tb[IFLA_ADDRESS]) { int alen; im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]); if (alen > sizeof(im->addr)) alen = sizeof(im->addr); memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen); } else { im->alen = 0; memset(im->addr, 0, sizeof(im->addr)); } strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME])); return 0; }
int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ifaddrlblmsg *ifal = NLMSG_DATA(n); int len = n->nlmsg_len; int host_len = -1; struct rtattr *tb[IFAL_MAX+1]; char abuf[256]; if (n->nlmsg_type != RTM_NEWADDRLABEL && n->nlmsg_type != RTM_DELADDRLABEL) return 0; len -= NLMSG_LENGTH(sizeof(*ifal)); if (len < 0) return -1; parse_rtattr(tb, IFAL_MAX, IFAL_RTA(ifal), len); if (ifal->ifal_family == AF_INET) host_len = 32; else if (ifal->ifal_family == AF_INET6) host_len = 128; if (n->nlmsg_type == RTM_DELADDRLABEL) fprintf(fp, "Deleted "); if (tb[IFAL_ADDRESS]) { fprintf(fp, "prefix %s/%u ", format_host(ifal->ifal_family, RTA_PAYLOAD(tb[IFAL_ADDRESS]), RTA_DATA(tb[IFAL_ADDRESS]), abuf, sizeof(abuf)), ifal->ifal_prefixlen); } if (ifal->ifal_index) fprintf(fp, "dev %s ", ll_index_to_name(ifal->ifal_index)); if (tb[IFAL_LABEL] && RTA_PAYLOAD(tb[IFAL_LABEL]) == sizeof(int32_t)) { int32_t label; memcpy(&label, RTA_DATA(tb[IFAL_LABEL]), sizeof(label)); fprintf(fp, "label %d ", label); } fprintf(fp, "\n"); fflush(fp); return 0; }
/* Netlink flag Link update */ static int netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface_t *ifp; int len; ifi = NLMSG_DATA(h); if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) 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; /* ignore loopback device */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* find the VMAC interface (if any) */ ifp = if_get_by_vmac_base_ifindex(ifi->ifi_index); /* if found, reflect base interface flags on VMAC interface */ if (ifp) ifp->flags = ifi->ifi_flags; /* find the interface_t */ ifp = if_get_by_ifindex(ifi->ifi_index); if (!ifp) return -1; /* * Update flags. * VMAC interfaces should never update it own flags, only be reflected * by the base interface flags, see above. */ if (!ifp->vmac) ifp->flags = ifi->ifi_flags; return 0; }
int get_rtstat_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *m, void *arg) { #ifndef IFLA_RTSTATS return -1; #else struct ifinfomsg *ifi = NLMSG_DATA(m); struct rtattr * tb[IFLA_MAX+1]; int len = m->nlmsg_len; struct rtstat_ent *n; unsigned long ival[RTMAXS]; int i; if (m->nlmsg_type != RTM_NEWLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (!(ifi->ifi_flags&IFF_UP)) return 0; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL || tb[IFLA_RTSTATS] == NULL) return 0; n = malloc(sizeof(*n)); if (!n) abort(); n->ifindex = ifi->ifi_index; n->name = strdup(RTA_DATA(tb[IFLA_IFNAME])); memcpy(&ival, RTA_DATA(tb[IFLA_RTSTATS]), sizeof(ival)); for (i=0; i<RTMAXS; i++) { n->ival[i] = ival[i]; } n->next = rtstat_db; rtstat_db = n; return 0; #endif }
static int hfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) { struct rtattr *tb[TCA_HFSC_MAX+1]; struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL; if (opt == NULL) return 0; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)); if (tb[TCA_HFSC_RSC]) { if (RTA_PAYLOAD(tb[TCA_HFSC_RSC]) < sizeof(*rsc)) fprintf(stderr, "HFSC: truncated realtime option\n"); else rsc = RTA_DATA(tb[TCA_HFSC_RSC]); } if (tb[TCA_HFSC_FSC]) { if (RTA_PAYLOAD(tb[TCA_HFSC_FSC]) < sizeof(*fsc)) fprintf(stderr, "HFSC: truncated linkshare option\n"); else fsc = RTA_DATA(tb[TCA_HFSC_FSC]); } if (tb[TCA_HFSC_USC]) { if (RTA_PAYLOAD(tb[TCA_HFSC_USC]) < sizeof(*usc)) fprintf(stderr, "HFSC: truncated upperlimit option\n"); else usc = RTA_DATA(tb[TCA_HFSC_USC]); } if (rsc != NULL && fsc != NULL && memcmp(rsc, fsc, sizeof(*rsc)) == 0) hfsc_print_sc(f, "sc", rsc); else { if (rsc != NULL) hfsc_print_sc(f, "rt", rsc); if (fsc != NULL) hfsc_print_sc(f, "ls", fsc); } if (usc != NULL) hfsc_print_sc(f, "ul", usc); return 0; }
static int print_ila_mapping(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct genlmsghdr *ghdr; struct rtattr *tb[ILA_ATTR_MAX + 1]; int len = n->nlmsg_len; if (n->nlmsg_type != genl_family) return 0; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) return -1; ghdr = NLMSG_DATA(n); parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); print_ila_locid(fp, ILA_ATTR_LOCATOR_MATCH, tb, ADDR_BUF_SIZE); print_ila_locid(fp, ILA_ATTR_LOCATOR, tb, ADDR_BUF_SIZE); if (tb[ILA_ATTR_IFINDEX]) fprintf(fp, "%-16s", ll_index_to_name(rta_getattr_u32( tb[ILA_ATTR_IFINDEX]))); else fprintf(fp, "%-10s ", "-"); if (tb[ILA_ATTR_CSUM_MODE]) fprintf(fp, "%s", ila_csum_mode2name(rta_getattr_u8( tb[ILA_ATTR_CSUM_MODE]))); else fprintf(fp, "%-10s ", "-"); if (tb[ILA_ATTR_IDENT_TYPE]) fprintf(fp, "%s", ila_ident_type2name(rta_getattr_u8( tb[ILA_ATTR_IDENT_TYPE]))); else fprintf(fp, "-"); fprintf(fp, "\n"); return 0; }
/* * parse ematch meta */ int parse_ematch_meta(char *msg, char *mp, void *p, int len) { struct rtattr *meta[__TCA_EM_META_MAX]; struct tcf_meta_hdr *hdr = NULL; struct tcf_meta_val *left = NULL, *right = NULL; parse_rtattr(meta, TCA_EM_META_MAX, p, len); if(meta[TCA_EM_META_HDR]) { if(RTA_PAYLOAD(meta[TCA_EM_META_HDR]) < sizeof(*hdr)) { rec_log("error: %s: TCA_EM_META_HDR: payload too short", __func__); return(1); } hdr = (struct tcf_meta_hdr *)RTA_DATA(meta[TCA_EM_META_HDR]); left = &(hdr->left); right = &(hdr->right); } else { rec_log("error: %s: TCA_EM_META_HDR: no attribute", __func__); return(1); } mp = add_log(msg, mp, "match=("); if(meta[TCA_EM_META_LVALUE]) { if(parse_tca_em_meta_value(msg, &mp, left, meta[TCA_EM_META_LVALUE])) return(1); } else { rec_log("error: %s: TCA_EM_META_LVALUE: no attribute", __func__); return(1); } mp = add_log(msg, mp, "%s ", conv_tcf_em_opnd(left->op, 0)); if(meta[TCA_EM_META_RVALUE]) { if(parse_tca_em_meta_value(msg, &mp, right, meta[TCA_EM_META_RVALUE])) return(1); } else { rec_log("error: %s: TCA_EM_META_RVALUE: no attribute", __func__); return(1); } mp = add_log(msg, mp, ") "); rec_log("%s", msg); return(0); }
static int get_netstat_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *m, void *arg) { struct ifinfomsg *ifi = NLMSG_DATA(m); struct rtattr * tb[IFLA_MAX+1]; int len = m->nlmsg_len; struct ifstat_ent *n; uint64_t ival[MAXS]; int i; if (m->nlmsg_type != RTM_NEWLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (!(ifi->ifi_flags&IFF_UP)) return 0; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS64] == NULL) return 0; n = malloc(sizeof(*n)); if (!n) abort(); n->ifindex = ifi->ifi_index; n->name = strdup(RTA_DATA(tb[IFLA_IFNAME])); memcpy(&ival, RTA_DATA(tb[IFLA_STATS64]), sizeof(ival)); for (i=0; i<MAXS; i++) { #undef DO_L2_STATS #ifdef DO_L2_STATS if(i == 2) n->ival[i] = n->ival[i]+4; /* RX CRC */ if(i == 3) n->ival[i] = n->ival[i]+18; /* TX 14+4 E-hdr + CRC */ #endif n->val[i] = ival[i]; } n->next = kern_db; kern_db = n; return 0; }
static int get_netnsid_from_name(const char *name) { struct { struct nlmsghdr n; struct rtgenmsg g; char buf[1024]; } req, answer; struct rtattr *tb[NETNSA_MAX + 1]; struct rtgenmsg *rthdr; int len, fd; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETNSID; req.g.rtgen_family = AF_UNSPEC; fd = netns_get_fd(name); if (fd < 0) return fd; addattr32(&req.n, 1024, NETNSA_FD, fd); if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) { close(fd); return -2; } close(fd); /* Validate message and parse attributes */ if (answer.n.nlmsg_type == NLMSG_ERROR) return -1; rthdr = NLMSG_DATA(&answer.n); len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr)); if (len < 0) return -1; parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); if (tb[NETNSA_NSID]) return rta_getattr_u32(tb[NETNSA_NSID]); return -1; }
int TunManager::getAddrRespParser(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { // only cares about RTM_NEWADDR if (n->nlmsg_type != RTM_NEWADDR) { return 0; } struct ifaddrmsg *ifa = static_cast<struct ifaddrmsg *>(NLMSG_DATA(n)); struct rtattr *tb[IFA_MAX + 1]; int len = n->nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { throw FbossError("Wrong length for RTM_GETADDR response ", len, " vs ", NLMSG_LENGTH(sizeof(*ifa))); } // only care about v4 and v6 address if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) { VLOG(3) << "Skip address from device @ index " << static_cast<int>(ifa->ifa_index) << " because of its address family " << static_cast<int>(ifa->ifa_family); return 0; } parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len); if (tb[IFA_ADDRESS] == nullptr) { VLOG(3) << "Device @ index " << static_cast<int>(ifa->ifa_index) << " does not have address at family " << static_cast<int>(ifa->ifa_family); return 0; } IPAddress addr; const void *data = RTA_DATA(tb[IFA_ADDRESS]); if (ifa->ifa_family == AF_INET) { addr = IPAddress(*static_cast<const in_addr *>(data)); } else { addr = IPAddress(*static_cast<const in6_addr *>(data)); } TunManager *mgr = static_cast<TunManager *>(arg); mgr->addProbedAddr(ifa->ifa_index, addr, ifa->ifa_prefixlen); return 0; }
int print_mpls(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtattr *tb[MPLS_ATTR_MAX + 1]; struct genlmsghdr *ghdr = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *attrs; if (n->nlmsg_type != PF_MPLS) { fprintf(stderr, "Not a controller message, nlmsg_len=%d " "nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type); return 0; } len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); parse_rtattr(tb, MPLS_ATTR_MAX, attrs, len); switch (ghdr->cmd) { case MPLS_CMD_NEWILM: return print_ilm(n,arg,tb); case MPLS_CMD_NEWNHLFE: return print_nhlfe(n,arg,tb); case MPLS_CMD_NEWXC: return print_xc(n,arg,tb); case MPLS_CMD_SETLABELSPACE: return print_labelspace(n,arg,tb); default: return 0; } #if 0 if (n->nlmsg_type >= MPLS_RTM_ADDTUNNEL && n->nlmsg_type <= MPLS_RTM_DELTUNNEL) { return print_tunnel(n,arg, tb); } #endif return 0; }
int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct br_port_msg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[MDBA_MAX+1]; if (n->nlmsg_type != RTM_GETMDB && n->nlmsg_type != RTM_NEWMDB && n->nlmsg_type != RTM_DELMDB) { fprintf(stderr, "Not RTM_GETMDB, RTM_NEWMDB or RTM_DELMDB: %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_index && filter_index != r->ifindex) return 0; parse_rtattr(tb, MDBA_MAX, MDBA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); if (tb[MDBA_MDB]) { struct rtattr *i; int rem = RTA_PAYLOAD(tb[MDBA_MDB]); for (i = RTA_DATA(tb[MDBA_MDB]); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) br_print_mdb_entry(fp, r->ifindex, i); } if (tb[MDBA_ROUTER]) { if (show_details) { fprintf(fp, "router ports on %s: ", ll_index_to_name(r->ifindex)); br_print_router_ports(fp, tb[MDBA_ROUTER]); } } return 0; }
static int xfrm_report_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct xfrm_user_report *xrep = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[XFRMA_MAX+1]; __u16 family; if (n->nlmsg_type != XFRM_MSG_REPORT) { fprintf(stderr, "Not a report: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*xrep)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } family = xrep->sel.family; if (family == AF_UNSPEC) family = preferred_family; fprintf(fp, "report "); fprintf(fp, "proto %s ", strxf_xfrmproto(xrep->proto)); fprintf(fp, "%s", _SL_); xfrm_selector_print(&xrep->sel, family, fp, " sel "); parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len); xfrm_xfrma_print(tb, family, fp, " "); if (oneline) fprintf(fp, "\n"); return 0; }
/** * returns non-local addresses for specified interface */ void ipaddr_global_get(int *count, char **bufPtr, int ifindex, struct nlmsg_list *ainfo) { int cnt=0; char * buf=0, * tmpbuf=0; char addr[16]; struct rtattr * rta_tb[IFA_MAX+1]; int pos; for ( ;ainfo ; ainfo = ainfo->next) { struct nlmsghdr *n = &ainfo->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if ( (ifa->ifa_family == AF_INET6) && (ifa->ifa_index == ifindex) ) { memset(rta_tb, 0, sizeof(*rta_tb)); 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]; memcpy(addr,(char*)RTA_DATA(rta_tb[IFLA_ADDRESS]),16); if ( (addr[0]==0xfe && addr[1]==0x80) || /* link local */ (addr[0]==0xff) ) { /* multicast */ continue; /* ignore non link-scoped addrs */ } /* ifa->ifa_flags & 128 - permenent */ /* printf("flags:%d : ",ifa->ifa_flags); */ pos = cnt*16; buf = (char*) malloc( pos + 16); if (pos > 0) { memcpy(buf,tmpbuf, pos); /* copy old addrs */ } memcpy(buf+pos,addr,16); /* copy new addr */ if (pos > 0) { free(tmpbuf); } tmpbuf = buf; cnt++; } } *count = cnt; *bufPtr = buf; }
int netlink_receive_one(struct nlmsghdr *hdr, void *arg) { struct rtattr *tb[NETLINK_DIAG_MAX+1]; struct netlink_diag_msg *m; struct netlink_sk_desc *sd; unsigned long *groups; m = NLMSG_DATA(hdr); pr_info("Collect netlink sock 0x%x\n", m->ndiag_ino); sd = xmalloc(sizeof(*sd)); if (!sd) return -1; sd->protocol = m->ndiag_protocol; sd->portid = m->ndiag_portid; sd->dst_portid = m->ndiag_dst_portid; sd->dst_group = m->ndiag_dst_group; sd->state = m->ndiag_state; parse_rtattr(tb, NETLINK_DIAG_MAX, (struct rtattr *)(m + 1), hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*m))); if (tb[NETLINK_DIAG_GROUPS]) { sd->gsize = RTA_PAYLOAD(tb[NETLINK_DIAG_GROUPS]); groups = RTA_DATA(tb[NETLINK_DIAG_GROUPS]); sd->groups = xmalloc(sd->gsize); if (!sd->groups) { xfree(sd); return -1; } memcpy(sd->groups, groups, sd->gsize); } else { sd->groups = NULL; sd->gsize = 0; } return sk_collect_one(m->ndiag_ino, PF_NETLINK, &sd->sd); }
/* * debug ematch meta */ void debug_ematch_meta(int lev, void *p, int len) { struct rtattr *meta[__TCA_EM_META_MAX]; struct tcf_meta_hdr *hdr = NULL; parse_rtattr(meta, TCA_EM_META_MAX, p, len); if(meta[TCA_EM_META_HDR]) hdr = debug_tca_em_meta_hdr(lev, meta[TCA_EM_META_HDR], "TCA_EM_META_HDR"); if(!hdr) return; if(meta[TCA_EM_META_LVALUE]) debug_tca_em_meta_value(lev, meta[TCA_EM_META_LVALUE], "TCA_EM_META_LVALUE", &(hdr->left)); if(meta[TCA_EM_META_RVALUE]) debug_tca_em_meta_value(lev, meta[TCA_EM_META_RVALUE], "TCA_EM_META_RVALUE", &(hdr->right)); }
static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[RTA_MAX+1]; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (tb[RTA_PRIORITY]) { n->nlmsg_type = RTM_DELRULE; n->nlmsg_flags = NLM_F_REQUEST; if (rtnl_talk(&rth, n, 0, 0, NULL, NULL, NULL) < 0) return -2; } return 0; }
int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct tcamsg *t = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[TCAA_MAX+1]; len -= NLMSG_LENGTH(sizeof(*t)); if (len < 0) { fprintf(stderr, "Wrong len %d\n", len); return -1; } parse_rtattr(tb, TCAA_MAX, TA_RTA(t), len); if (NULL == tb[TCA_ACT_TAB]) { if (n->nlmsg_type != RTM_GETACTION) fprintf(stderr, "print_action: NULL kind\n"); return -1; } if (n->nlmsg_type == RTM_DELACTION) { if (n->nlmsg_flags & NLM_F_ROOT) { fprintf(fp, "Flushed table "); tab_flush = 1; } else { fprintf(fp, "deleted action "); } } if (n->nlmsg_type == RTM_NEWACTION) fprintf(fp, "Added action "); tc_print_action(fp, tb[TCA_ACT_TAB]); return 0; }
/**************************************************************** NAME : print_addr 00/06/02 18:24:09 AIM : REMARK : ****************************************************************/ static int get_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; iplist_ctx *ctx = (iplist_ctx *)arg; struct rtattr *rta_tb[IFA_MAX+1]; /* sanity check */ len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } /* check the message type */ if (n->nlmsg_type != RTM_NEWADDR ) return 0; /* check it is ipv4 */ if( ifa->ifa_family != AF_INET) return 0; /* check it is the good interface */ if( ifa->ifa_index != ctx->ifindex ) return 0; /* parse the attribute */ memset(rta_tb, 0, sizeof(rta_tb)); parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), len); if (!rta_tb[IFA_LOCAL]) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (rta_tb[IFA_LOCAL]) { u_char *src = RTA_DATA(rta_tb[IFA_LOCAL]); if( ctx->nb_elem >= ctx->max_elem ) return 0; ctx->addr[ctx->nb_elem++] = (src[0]<<24) + (src[1]<<16) + (src[2]<<8) + src[3]; } return 0; }
static void ipoe_up_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h) { struct rtattr *tb[PKT_ATTR_MAX + 1]; struct rtattr *tb2[IPOE_ATTR_MAX + 1]; struct genlmsghdr *ghdr = NLMSG_DATA(h); int len = h->nlmsg_len; struct rtattr *attrs; int i; int ifindex; struct iphdr *iph; struct ethhdr *eth; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) { log_warn("ipoe: wrong controller message length %d\n", len); return; } attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN); parse_rtattr(tb, PKT_ATTR_MAX, attrs, len); for (i = 1; i < PKT_ATTR_MAX; i++) { if (!tb[i]) break; parse_rtattr_nested(tb2, IPOE_ATTR_MAX, tb[i]); if (!tb2[IPOE_ATTR_ETH_HDR] || !tb2[IPOE_ATTR_IP_HDR] || !tb2[IPOE_ATTR_IFINDEX]) continue; ifindex = *(uint32_t *)(RTA_DATA(tb2[IPOE_ATTR_IFINDEX])); iph = (struct iphdr *)(RTA_DATA(tb2[IPOE_ATTR_IP_HDR])); eth = (struct ethhdr *)(RTA_DATA(tb2[IPOE_ATTR_ETH_HDR])); ipoe_recv_up(ifindex, eth, iph); } }
int ll_remember_index(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { int h; struct ifinfomsg *ifi = NLMSG_DATA(n); struct ll_cache *im, **imp; struct rtattr *tb[IFLA_MAX+1]; if (n->nlmsg_type != RTM_NEWLINK) return 0; if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) return -1; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); if (tb[IFLA_IFNAME] == NULL) return 0; h = ifi->ifi_index & (IDXMAP_SIZE - 1); for (imp = &idx_head[h]; (im=*imp)!=NULL; imp = &im->idx_next) if (im->index == ifi->ifi_index) break; if (im == NULL) { im = malloc(sizeof(*im)); if (im == NULL) return 0; im->idx_next = *imp; im->index = ifi->ifi_index; *imp = im; } im->type = ifi->ifi_type; im->flags = ifi->ifi_flags; strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME])); return 0; }
static int meta_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data, int data_len) { struct rtattr *tb[TCA_EM_META_MAX+1]; struct tcf_meta_hdr *meta_hdr; if (parse_rtattr(tb, TCA_EM_META_MAX, data, data_len) < 0) return -1; if (tb[TCA_EM_META_HDR] == NULL) { fprintf(stderr, "Missing meta header\n"); return -1; } if (RTA_PAYLOAD(tb[TCA_EM_META_HDR]) < sizeof(*meta_hdr)) { fprintf(stderr, "Meta header size mismatch\n"); return -1; } meta_hdr = RTA_DATA(tb[TCA_EM_META_HDR]); if (print_object(fd, &meta_hdr->left, tb[TCA_EM_META_LVALUE]) < 0) return -1; switch (meta_hdr->left.op) { case TCF_EM_OPND_EQ: fprintf(fd, " eq "); break; case TCF_EM_OPND_LT: fprintf(fd, " lt "); break; case TCF_EM_OPND_GT: fprintf(fd, " gt "); break; } return print_object(fd, &meta_hdr->right, tb[TCA_EM_META_RVALUE]); }
static int xfrm_policy_flush_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtattr *tb[XFRMA_MAX+1]; FILE *fp = (FILE *)arg; int len = n->nlmsg_len; len -= NLMSG_SPACE(0); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } fprintf(fp, "Flushed policy "); parse_rtattr(tb, XFRMA_MAX, NLMSG_DATA(n), len); if (tb[XFRMA_POLICY_TYPE]) { struct xfrm_userpolicy_type *upt; fprintf(fp, "ptype "); if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) fprintf(fp, "(ERROR truncated)"); upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]); fprintf(fp, "%s ", strxf_ptype(upt->type)); } fprintf(fp, "%s", _SL_); if (oneline) fprintf(fp, "\n"); fflush(fp); return 0; }
int cthd_nl_wrapper::genl_print_acpi_event_message(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtattr *tb[ACPI_GENL_ATTR_MAX + 1]; struct genlmsghdr *ghdr = (struct genlmsghdr *)NLMSG_DATA(n); FILE *fp = (FILE *) arg; int len = n->nlmsg_len; struct rtattr *attrs; if (n->nlmsg_type != acpi_event_family_id) { fprintf(stderr, "Not a acpi event message, nlmsg_len=%d " "nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type); return 0; } len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) { fprintf(stderr, "wrong controller message len %d\n", len); return -1; } attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN); parse_rtattr(tb, ACPI_GENL_ATTR_MAX, attrs, len); if (tb[ACPI_GENL_ATTR_EVENT]) { struct acpi_genl_event *event = (struct acpi_genl_event *)RTA_DATA(tb[ACPI_GENL_ATTR_EVENT]); fprintf(fp, "\n%20s %15s %08x %08x\n", event->device_class, event->bus_id, event->type, event->data); fflush(fp); return 0; } return -1; }
static int get_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *m, void *arg) { struct ifinfomsg *ifi = NLMSG_DATA(m); struct rtattr *tb[IFLA_MAX+1]; int len = m->nlmsg_len; struct ifstat_ent *n; int i; if (m->nlmsg_type != RTM_NEWLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (!(ifi->ifi_flags&IFF_UP)) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS] == NULL) return 0; n = malloc(sizeof(*n)); if (!n) abort(); n->ifindex = ifi->ifi_index; n->name = strdup(RTA_DATA(tb[IFLA_IFNAME])); memcpy(&n->ival, RTA_DATA(tb[IFLA_STATS]), sizeof(n->ival)); memset(&n->rate, 0, sizeof(n->rate)); for (i = 0; i < MAXS; i++) n->val[i] = n->ival[i]; n->next = kern_db; kern_db = n; return 0; }
/* Netlink flag Link update */ static int netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface *ifp; int len; ifi = NLMSG_DATA(h); if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) 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; /* ignore loopback device */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* find the interface */ ifp = if_get_by_ifindex(ifi->ifi_index); if (!ifp) return -1; /* Update flags */ ifp->flags = ifi->ifi_flags; return 0; }
int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[XFRMA_MAX+1]; if (n->nlmsg_type != XFRM_MSG_NEWSA && n->nlmsg_type != XFRM_MSG_DELSA) { // fprintf(stderr, "Not a state: %08x %08x %08x\n", // n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*xsinfo)); if (len < 0) { // fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (!xfrm_state_filter_match(xsinfo)) return 0; parse_rtattr(tb, XFRMA_MAX, XFRMS_RTA(xsinfo), len); if (n->nlmsg_type == XFRM_MSG_DELSA) fprintf(fp, "Deleted "); xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL); if (oneline) fprintf(fp, "\n"); return 0; }
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 (tb[IFLA_GROUP]) { int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); if (filter.group != -1 && group != filter.group) return -1; } if (tb[IFLA_MASTER]) { int master = *(int*)RTA_DATA(tb[IFLA_MASTER]); if (filter.master > 0 && master != filter.master) return -1; } else if (filter.master > 0) return -1; if (filter.kind) { if (tb[IFLA_LINKINFO]) { char *kind = parse_link_kind(tb[IFLA_LINKINFO]); if (strcmp(kind, filter.kind)) return -1; } else { return -1; } } if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: ", ifi->ifi_index); color_fprintf(fp, COLOR_IFNAME, "%s", tb[IFLA_IFNAME] ? rta_getattr_str(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 { if (tb[IFLA_LINK_NETNSID]) fprintf(fp, "@if%d: ", iflink); 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 ", rta_getattr_str(tb[IFLA_QDISC])); if (tb[IFLA_MASTER]) { SPRINT_BUF(b1); fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); } if (tb[IFLA_PHYS_PORT_ID]) { SPRINT_BUF(b1); fprintf(fp, "portid %s ", hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_PORT_ID]), RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]), b1, sizeof(b1))); } if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (do_link && tb[IFLA_LINKMODE]) print_linkmode(fp, tb[IFLA_LINKMODE]); if (tb[IFLA_GROUP]) { SPRINT_BUF(b1); int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); fprintf(fp, "group %s ", rtnl_group_n2a(group, b1, sizeof(b1))); } if (filter.showqueue) print_queuelen(fp, tb); if (!filter.family || filter.family == AF_PACKET || show_details) { SPRINT_BUF(b1); fprintf(fp, "%s", _SL_); fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1))); if (tb[IFLA_ADDRESS]) { color_fprintf(fp, COLOR_MAC, "%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 (tb[IFLA_LINK_NETNSID]) { int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]); if (id >= 0) fprintf(fp, " link-netnsid %d", id); else fprintf(fp, " link-netnsid unknown"); } if (tb[IFLA_PROMISCUITY] && show_details) fprintf(fp, " promiscuity %u ", *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); if (tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); if (do_link && tb[IFLA_AF_SPEC] && show_details) print_af_spec(fp, tb[IFLA_AF_SPEC]); if ((do_link || show_details) && tb[IFLA_IFALIAS]) { fprintf(fp, "%s alias %s", _SL_, rta_getattr_str(tb[IFLA_IFALIAS])); } if (do_link && show_stats) { fprintf(fp, "%s", _SL_); __print_link_stats(fp, tb); } if ((do_link || show_details) && 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 1; }
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; int deprecated = 0; /* Use local copy of ifa_flags to not interfere with filtering code */ unsigned int ifa_flags; 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))); ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]); 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_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]) { if (ifa->ifa_family == AF_INET) color_fprintf(fp, COLOR_INET, "%s", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); else if (ifa->ifa_family == AF_INET6) color_fprintf(fp, COLOR_INET6, "%s", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); else fprintf(fp, "%s", format_host(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]), ifa->ifa_family == AF_INET ? 4 : 16) == 0) { fprintf(fp, "/%d ", ifa->ifa_prefixlen); } else { fprintf(fp, " peer %s/%d ", format_host(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 ", format_host(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 ", format_host(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_flags & IFA_F_SECONDARY) { ifa_flags &= ~IFA_F_SECONDARY; if (ifa->ifa_family == AF_INET6) fprintf(fp, "temporary "); else fprintf(fp, "secondary "); } if (ifa_flags & IFA_F_TENTATIVE) { ifa_flags &= ~IFA_F_TENTATIVE; fprintf(fp, "tentative "); } if (ifa_flags & IFA_F_DEPRECATED) { ifa_flags &= ~IFA_F_DEPRECATED; deprecated = 1; fprintf(fp, "deprecated "); } if (ifa_flags & IFA_F_HOMEADDRESS) { ifa_flags &= ~IFA_F_HOMEADDRESS; fprintf(fp, "home "); } if (ifa_flags & IFA_F_NODAD) { ifa_flags &= ~IFA_F_NODAD; fprintf(fp, "nodad "); } if (ifa_flags & IFA_F_MANAGETEMPADDR) { ifa_flags &= ~IFA_F_MANAGETEMPADDR; fprintf(fp, "mngtmpaddr "); } if (ifa_flags & IFA_F_NOPREFIXROUTE) { ifa_flags &= ~IFA_F_NOPREFIXROUTE; fprintf(fp, "noprefixroute "); } if (ifa_flags & IFA_F_MCAUTOJOIN) { ifa_flags &= ~IFA_F_MCAUTOJOIN; fprintf(fp, "autojoin "); } if (!(ifa_flags & IFA_F_PERMANENT)) { fprintf(fp, "dynamic "); } else ifa_flags &= ~IFA_F_PERMANENT; if (ifa_flags & IFA_F_DADFAILED) { ifa_flags &= ~IFA_F_DADFAILED; fprintf(fp, "dadfailed "); } if (ifa_flags) fprintf(fp, "flags %02x ", ifa_flags); if (rta_tb[IFA_LABEL]) fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL])); if (rta_tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); fprintf(fp, "%s", _SL_); fprintf(fp, " valid_lft "); if (ci->ifa_valid == INFINITY_LIFE_TIME) fprintf(fp, "forever"); else fprintf(fp, "%usec", ci->ifa_valid); fprintf(fp, " preferred_lft "); if (ci->ifa_prefered == INFINITY_LIFE_TIME) fprintf(fp, "forever"); else { if (deprecated) fprintf(fp, "%dsec", ci->ifa_prefered); else fprintf(fp, "%usec", ci->ifa_prefered); } } fprintf(fp, "\n"); fflush(fp); return 0; }
static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo) { struct nlmsg_list *l, **lp; lp = &linfo->head; while ( (l = *lp) != NULL) { int ok = 0; int missing_net_address = 1; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a = ainfo->head; a; a = a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); struct rtattr *tb[IFA_MAX + 1]; unsigned int ifa_flags; if (ifa->ifa_index != ifi->ifi_index) continue; missing_net_address = 0; if (filter.family && filter.family != ifa->ifa_family) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); ifa_flags = get_ifa_flags(ifa, tb[IFA_FLAGS]); if ((filter.flags ^ ifa_flags) & filter.flagmask) continue; if (filter.pfx.family || filter.label) { if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (missing_net_address && (filter.family == AF_UNSPEC || filter.family == AF_PACKET)) ok = 1; if (!ok) { *lp = l->next; free(l); } else lp = &l->next; } }