int print_rule(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; int host_len = -1; __u32 table; struct rtattr * tb[FRA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWRULE && n->nlmsg_type != RTM_DELRULE) return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; parse_rtattr(tb, FRA_MAX, RTM_RTA(r), len); if (r->rtm_family == AF_INET) host_len = 32; else if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_DECnet) host_len = 16; else if (r->rtm_family == AF_IPX) host_len = 80; if (n->nlmsg_type == RTM_DELRULE) fprintf(fp, "Deleted "); if (tb[FRA_PRIORITY]) fprintf(fp, "%u:\t", *(unsigned*)RTA_DATA(tb[FRA_PRIORITY])); else fprintf(fp, "0:\t"); if (r->rtm_flags & FIB_RULE_INVERT) fprintf(fp, "not "); if (tb[FRA_SRC]) { if (r->rtm_src_len != host_len) { fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[FRA_SRC]), RTA_DATA(tb[FRA_SRC]), abuf, sizeof(abuf)), r->rtm_src_len ); } else { fprintf(fp, "from %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[FRA_SRC]), RTA_DATA(tb[FRA_SRC]), abuf, sizeof(abuf)) ); } } else if (r->rtm_src_len) { fprintf(fp, "from 0/%d ", r->rtm_src_len); } else { fprintf(fp, "from all "); } if (tb[FRA_DST]) { if (r->rtm_dst_len != host_len) { fprintf(fp, "to %s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[FRA_DST]), RTA_DATA(tb[FRA_DST]), abuf, sizeof(abuf)), r->rtm_dst_len ); } else { fprintf(fp, "to %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[FRA_DST]), RTA_DATA(tb[FRA_DST]), abuf, sizeof(abuf))); } } else if (r->rtm_dst_len) { fprintf(fp, "to 0/%d ", r->rtm_dst_len); } if (r->rtm_tos) { SPRINT_BUF(b1); fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); } if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) { __u32 mark = 0, mask = 0; if (tb[FRA_FWMARK]) mark = *(__u32*)RTA_DATA(tb[FRA_FWMARK]); if (tb[FRA_FWMASK] && (mask = *(__u32*)RTA_DATA(tb[FRA_FWMASK])) != 0xFFFFFFFF) fprintf(fp, "fwmark 0x%x/0x%x ", mark, mask); else fprintf(fp, "fwmark 0x%x ", mark); } if (tb[FRA_IFNAME]) { fprintf(fp, "iif %s ", (char*)RTA_DATA(tb[FRA_IFNAME])); if (r->rtm_flags & FIB_RULE_DEV_DETACHED) fprintf(fp, "[detached] "); } table = rtm_get_table(r, tb); if (table) fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); if (tb[FRA_FLOW]) { __u32 to = *(__u32*)RTA_DATA(tb[FRA_FLOW]); __u32 from = to>>16; to &= 0xFFFF; if (from) { fprintf(fp, "realms %s/", rtnl_rtrealm_n2a(from, b1, sizeof(b1))); } fprintf(fp, "%s ", rtnl_rtrealm_n2a(to, b1, sizeof(b1))); } if (r->rtm_type == RTN_NAT) { if (tb[RTA_GATEWAY]) { fprintf(fp, "map-to %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_GATEWAY]), RTA_DATA(tb[RTA_GATEWAY]), abuf, sizeof(abuf))); } else fprintf(fp, "masquerade"); } else if (r->rtm_type == FR_ACT_GOTO) { fprintf(fp, "goto "); if (tb[FRA_GOTO]) fprintf(fp, "%u", *(__u32 *) RTA_DATA(tb[FRA_GOTO])); else fprintf(fp, "none"); if (r->rtm_flags & FIB_RULE_UNRESOLVED) fprintf(fp, " [unresolved]"); } else if (r->rtm_type == FR_ACT_NOP) fprintf(fp, "nop"); else if (r->rtm_type != RTN_UNICAST) fprintf(fp, "%s", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); fprintf(fp, "\n"); fflush(fp); return 0; }
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]; inet_prefix dst; inet_prefix src; inet_prefix prefsrc; inet_prefix via; int host_len = -1; SPRINT_BUF(b1); 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; } if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_INET) host_len = 32; else if (r->rtm_family == AF_DECnet) host_len = 16; else if (r->rtm_family == AF_IPX) host_len = 80; if (r->rtm_family == AF_INET6) { if (filter.tb) { if (filter.tb < 0) { if (!(r->rtm_flags&RTM_F_CLONED)) return 0; } else { if (r->rtm_flags&RTM_F_CLONED) return 0; 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 != r->rtm_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; parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 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); } 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); } 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 = *(__u32*)RTA_DATA(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.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; 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 0 if (tb[RTA_MP_ALGO]) { __u32 mp_alg = *(__u32*) RTA_DATA(tb[RTA_MP_ALGO]); if (mp_alg > IP_MP_ALG_NONE) { fprintf(fp, "mpath %s ", mp_alg < IP_MP_ALG_MAX ? mp_alg_names[mp_alg] : "unknown"); } } #endif 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 (r->rtm_table != RT_TABLE_MAIN && !filter.tb) fprintf(fp, " table %s ", rtnl_rttable_n2a(r->rtm_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 %d ", *(__u32*)RTA_DATA(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_EQUALIZE) fprintf(fp, "equalize "); if (r->rtm_flags & RTM_F_NOTIFY) fprintf(fp, "notify "); if (tb[RTA_FLOW] && filter.realmmask != ~0U) { __u32 to = *(__u32*)RTA_DATA(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))); }
int print_mroute(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]; char obuf[256]; SPRINT_BUF(b1); __u32 table; int iif = 0; int family; if ((n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) || !(n->nlmsg_flags & NLM_F_MULTI)) { fprintf(stderr, "Not a multicast route: %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 (r->rtm_type != RTN_MULTICAST) { fprintf(stderr, "Not a multicast route (type: %s)\n", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); return 0; } parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); table = rtm_get_table(r, tb); if (filter.tb > 0 && filter.tb != table) return 0; if (tb[RTA_IIF]) iif = *(int*)RTA_DATA(tb[RTA_IIF]); if (filter.iif && filter.iif != iif) return 0; if (filter.af && filter.af != r->rtm_family) return 0; if (tb[RTA_DST] && filter.mdst.bitlen > 0 && inet_addr_match(RTA_DATA(tb[RTA_DST]), &filter.mdst, filter.mdst.bitlen)) return 0; if (tb[RTA_SRC] && filter.msrc.bitlen > 0 && inet_addr_match(RTA_DATA(tb[RTA_SRC]), &filter.msrc, filter.msrc.bitlen)) return 0; family = r->rtm_family == RTNL_FAMILY_IPMR ? AF_INET : AF_INET6; if (n->nlmsg_type == RTM_DELROUTE) fprintf(fp, "Deleted "); if (tb[RTA_SRC]) len = snprintf(obuf, sizeof(obuf), "(%s, ", rt_addr_n2a(family, RTA_PAYLOAD(tb[RTA_SRC]), RTA_DATA(tb[RTA_SRC]), abuf, sizeof(abuf))); else len = sprintf(obuf, "(unknown, "); if (tb[RTA_DST]) snprintf(obuf + len, sizeof(obuf) - len, "%s)", rt_addr_n2a(family, RTA_PAYLOAD(tb[RTA_DST]), RTA_DATA(tb[RTA_DST]), abuf, sizeof(abuf))); else snprintf(obuf + len, sizeof(obuf) - len, "unknown) "); fprintf(fp, "%-32s Iif: ", obuf); if (iif) fprintf(fp, "%-10s ", ll_index_to_name(iif)); else fprintf(fp, "unresolved "); if (tb[RTA_MULTIPATH]) { struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); int first = 1; len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); for (;;) { if (len < sizeof(*nh)) break; if (nh->rtnh_len > len) break; if (first) { fprintf(fp, "Oifs: "); first = 0; } fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); if (nh->rtnh_hops > 1) fprintf(fp, "(ttl %d) ", nh->rtnh_hops); else fprintf(fp, " "); len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); } } if (show_stats && tb[RTA_MFC_STATS]) { struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); fprintf(fp, "%s %"PRIu64" packets, %"PRIu64" bytes", _SL_, (uint64_t)mfcs->mfcs_packets, (uint64_t)mfcs->mfcs_bytes); if (mfcs->mfcs_wrong_if) fprintf(fp, ", %"PRIu64" arrived on wrong iif.", (uint64_t)mfcs->mfcs_wrong_if); } fprintf(fp, "\n"); fflush(fp); return 0; }
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))); }
static int print_rule(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; int host_len = -1; struct rtattr * tb[RTA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWRULE) return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (r->rtm_family == AF_INET) host_len = 32; else if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_DECnet) host_len = 16; else if (r->rtm_family == AF_IPX) host_len = 80; if (tb[RTA_PRIORITY]) fprintf(fp, "%u:\t", *(unsigned*)RTA_DATA(tb[RTA_PRIORITY])); else fprintf(fp, "0:\t"); 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/%d ", r->rtm_src_len); } else { fprintf(fp, "from all "); } if (tb[RTA_DST]) { if (r->rtm_dst_len != host_len) { fprintf(fp, "to %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, "to %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, "to 0/%d ", r->rtm_dst_len); } if (r->rtm_tos) { SPRINT_BUF(b1); fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); } if (tb[RTA_PROTOINFO]) { fprintf(fp, "fwmark %#x ", *(__u32*)RTA_DATA(tb[RTA_PROTOINFO])); } if (tb[RTA_IIF]) { fprintf(fp, "iif %s ", (char*)RTA_DATA(tb[RTA_IIF])); } if (r->rtm_table) fprintf(fp, "lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1, sizeof(b1))); if (tb[RTA_FLOW]) { __u32 to = *(__u32*)RTA_DATA(tb[RTA_FLOW]); __u32 from = to>>16; to &= 0xFFFF; if (from) { fprintf(fp, "realms %s/", rtnl_rtrealm_n2a(from, b1, sizeof(b1))); } fprintf(fp, "%s ", rtnl_rtrealm_n2a(to, b1, sizeof(b1))); } if (r->rtm_type == RTN_NAT) { if (tb[RTA_GATEWAY]) { fprintf(fp, "map-to %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_GATEWAY]), RTA_DATA(tb[RTA_GATEWAY]), abuf, sizeof(abuf))); } else fprintf(fp, "masquerade"); } else if (r->rtm_type != RTN_UNICAST) fprintf(fp, "%s", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); fprintf(fp, "\n"); fflush(fp); return 0; }
static int print_route(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]; inet_prefix dst; inet_prefix src; int host_len = -1; SPRINT_BUF(b1); 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) { bb_error_msg("wrong nlmsg len %d", len); return -1; } if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_INET) host_len = 32; if (r->rtm_family == AF_INET6) { if (filter.tb) { if (filter.tb < 0) { if (!(r->rtm_flags&RTM_F_CLONED)) { return 0; } } else { if (r->rtm_flags&RTM_F_CLONED) { return 0; } 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 != r->rtm_table) { 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; } memset(tb, 0, sizeof(tb)); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 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.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; 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 = ++filter.rth->seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; 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 (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 (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 %d ", *(__u32*)RTA_DATA(tb[RTA_PRIORITY])); } if (r->rtm_family == AF_INET6) { struct rta_cacheinfo *ci = NULL; if (tb[RTA_CACHEINFO]) { ci = RTA_DATA(tb[RTA_CACHEINFO]); } if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) { static int hz; if (!hz) { hz = get_hz(); } if (r->rtm_flags & RTM_F_CLONED) { fprintf(fp, "%s cache ", _SL_); } if (ci->rta_expires) { fprintf(fp, " expires %dsec", ci->rta_expires/hz); } if (ci->rta_error != 0) { fprintf(fp, " error %d", ci->rta_error); } } else if (ci) { if (ci->rta_error != 0) fprintf(fp, " error %d", ci->rta_error); } } if (tb[RTA_IIF] && filter.iifmask != -1) { fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF]))); } fprintf(fp, "\n"); fflush(fp); return 0; }