void xfrm_selector_print(struct xfrm_selector *sel, __u16 family, FILE *fp, const char *prefix) { char abuf[256]; __u16 f; f = sel->family; if (f == AF_UNSPEC) f = family; if (f == AF_UNSPEC) f = preferred_family; if (prefix) fprintf(fp, prefix); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s/%u ", rt_addr_n2a(f, sizeof(sel->saddr), &sel->saddr, abuf, sizeof(abuf)), sel->prefixlen_s); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "dst %s/%u ", rt_addr_n2a(f, sizeof(sel->daddr), &sel->daddr, abuf, sizeof(abuf)), sel->prefixlen_d); if (sel->proto) fprintf(fp, "proto %s ", strxf_proto(sel->proto)); switch (sel->proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_SCTP: default: /* XXX */ if (sel->sport_mask) fprintf(fp, "sport %u ", ntohs(sel->sport)); if (sel->dport_mask) fprintf(fp, "dport %u ", ntohs(sel->dport)); break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: /* type/code is stored at sport/dport in selector */ if (sel->sport_mask) fprintf(fp, "type %u ", ntohs(sel->sport)); if (sel->dport_mask) fprintf(fp, "code %u ", ntohs(sel->dport)); break; } if (sel->ifindex > 0) { char buf[IFNAMSIZ]; memset(buf, '\0', sizeof(buf)); if_indextoname(sel->ifindex, buf); fprintf(fp, "dev %s ", buf); } if (show_stats > 0) fprintf(fp, "uid %u", sel->user); fprintf(fp, "%s", _SL_); }
static int xfrm_ae_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct xfrm_aevent_id *id = NLMSG_DATA(n); char abuf[256]; fprintf(fp, "Async event "); xfrm_ae_flags_print(id->flags, arg); fprintf(fp,"\n\t"); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family, sizeof(id->saddr), &id->saddr, abuf, sizeof(abuf))); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "dst %s ", rt_addr_n2a(id->sa_id.family, sizeof(id->sa_id.daddr), &id->sa_id.daddr, abuf, sizeof(abuf))); fprintf(fp, " reqid 0x%x", id->reqid); fprintf(fp, " protocol %s ", strxf_proto(id->sa_id.proto)); fprintf(fp, " SPI 0x%x", ntohl(id->sa_id.spi)); fprintf(fp, "\n"); fflush(fp); return 0; }
void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id, __u8 mode, __u32 reqid, __u16 family, int force_spi, FILE *fp, const char *prefix, const char *title) { char abuf[256]; if (title) fputs(title, fp); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s ", rt_addr_n2a(family, sizeof(*saddr), saddr, abuf, sizeof(abuf))); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "dst %s", rt_addr_n2a(family, sizeof(id->daddr), &id->daddr, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); if (prefix) fputs(prefix, fp); fprintf(fp, "\t"); fprintf(fp, "proto %s ", strxf_xfrmproto(id->proto)); if (show_stats > 0 || force_spi || id->spi) { __u32 spi = ntohl(id->spi); fprintf(fp, "spi 0x%08x", spi); if (show_stats > 0) fprintf(fp, "(%u)", spi); fprintf(fp, " "); } fprintf(fp, "reqid %u", reqid); if (show_stats > 0) fprintf(fp, "(0x%08x)", reqid); fprintf(fp, " "); fprintf(fp, "mode "); switch (mode) { case XFRM_MODE_TRANSPORT: fprintf(fp, "transport"); break; case XFRM_MODE_TUNNEL: fprintf(fp, "tunnel"); break; case XFRM_MODE_ROUTEOPTIMIZATION: fprintf(fp, "ro"); break; case XFRM_MODE_IN_TRIGGER: fprintf(fp, "in_trigger"); break; case XFRM_MODE_BEET: fprintf(fp, "beet"); break; default: fprintf(fp, "%u", mode); break; } fprintf(fp, "%s", _SL_); }
void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id, __u8 mode, __u32 reqid, __u16 family, int force_spi, FILE *fp, const char *prefix, const char *title) { char abuf[256]; if (title) fprintf(fp, title); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s ", rt_addr_n2a(family, sizeof(*saddr), saddr, abuf, sizeof(abuf))); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "dst %s", rt_addr_n2a(family, sizeof(id->daddr), &id->daddr, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); if (prefix) fprintf(fp, prefix); fprintf(fp, "\t"); fprintf(fp, "proto %s ", strxf_xfrmproto(id->proto)); if (show_stats > 0 || force_spi || id->spi) { __u32 spi = ntohl(id->spi); fprintf(fp, "spi 0x%08x", spi); if (show_stats > 0) fprintf(fp, "(%u)", spi); fprintf(fp, " "); } fprintf(fp, "reqid %u", reqid); if (show_stats > 0) fprintf(fp, "(0x%08x)", reqid); fprintf(fp, " "); fprintf(fp, "mode "); switch (mode) { case 0: fprintf(fp, "transport"); break; case 1: fprintf(fp, "tunnel"); break; default: fprintf(fp, "%u", mode); break; } fprintf(fp, "%s", _SL_); }
const char *format_host(int af, int len, void *addr, char *buf, int buflen) { if (resolve_hosts) { struct hostent *h_ent; if (len <= 0) { switch (af) { case AF_INET: len = 4; break; case AF_INET6: len = 16; break; default:; } } if (len > 0) { h_ent = gethostbyaddr(addr, len, af); if (h_ent != NULL) { safe_strncpy(buf, h_ent->h_name, buflen); return buf; } } } return rt_addr_n2a(af, addr, buf, buflen); }
const char *format_host(int af, int len, const void *addr, char *buf, int buflen) { #ifdef RESOLVE_HOSTNAMES if (resolve_hosts) { const char *n; if (len <= 0) { switch (af) { case AF_INET: len = 4; break; case AF_INET6: len = 16; break; case AF_IPX: len = 10; break; #ifdef AF_DECnet /* I see no reasons why gethostbyname may not work for DECnet */ case AF_DECnet: len = 2; break; #endif default: ; } } if (len > 0 && (n = resolve_address(addr, len, af)) != NULL) return n; } #endif return rt_addr_n2a(af, len, addr, buf, buflen); }
static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a) { char buf[256]; buf[0] = 0; fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*a), a, buf, sizeof(buf))); }
const char *format_host(int af, int len, void *addr, char *buf, int buflen) { #ifdef RESOLVE_HOSTNAMES if (resolve_hosts) { struct hostent *h_ent; if (len <= 0) { switch (af) { case AF_INET: len = 4; break; case AF_INET6: len = 16; break; case AF_IPX: len = 10; break; #ifdef AF_DECnet /* I see no reasons why gethostbyname may not work for DECnet */ case AF_DECnet: len = 2; break; #endif default: ; } } if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) { snprintf(buf, buflen-1, "%s", h_ent->h_name); return buf; } } #endif return rt_addr_n2a(af, len, addr, buf, buflen); }
boost::asio::ip::address_v6 get_ipv6_address(const nlmsghdr *in, const nlmsghdr *an) { boost::asio::ip::address_v6 unspec; if (in->nlmsg_type != RTM_NEWLINK) return unspec; if (an->nlmsg_type != RTM_NEWADDR) return unspec; ifinfomsg* ifi = (ifinfomsg*)NLMSG_DATA(in); ifaddrmsg* ifa = (ifaddrmsg*)NLMSG_DATA(an); __u32 ilen = in->nlmsg_len; if (ilen < NLMSG_LENGTH(sizeof(*ifi))) return unspec; ilen -= NLMSG_LENGTH(sizeof(*ifi)); __u32 alen = an->nlmsg_len; if (alen < NLMSG_LENGTH(sizeof(*ifa))) return unspec; alen -= NLMSG_LENGTH(sizeof(*ifa)); /* NOTE: ifi_index and ifa_index should have the same type (int), but for * some reason they are not... So instead of a normal (in)equality comparison * we do a bit-wise compare. */ if (ifi->ifi_index ^ ifa->ifa_index) return unspec; if (ifi->ifi_family != AF_INET6 || ifa->ifa_family != AF_INET6) return unspec; rtattr* tbi[IFLA_MAX+1]; memset(tbi, 0, sizeof(tbi)); parse_rtattr(tbi, IFLA_MAX, IFLA_RTA(ifi), ilen); if (tbi[IFLA_IFNAME] == NULL) return unspec; rtattr* tba[IFA_MAX+1]; memset(tba, 0, sizeof(tba)); parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), alen); char abuf[256]; rt_addr_n2a(ifa->ifa_family, RTA_PAYLOAD(tba[IFA_ADDRESS]), RTA_DATA(tba[IFA_ADDRESS]), abuf, sizeof(abuf)); std::string ipaddr = abuf; try { boost::asio::ip::address_v6 addr(boost::asio::ip::address_v6::from_string(ipaddr)); addr.scope_id(ifi->ifi_index); return addr; } catch(...) { return unspec; } }
static void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, FILE *fp) { fprintf(fp, "dst %s ", rt_addr_n2a(sa_id->family, sizeof(sa_id->daddr), &sa_id->daddr)); fprintf(fp, " reqid 0x%x", reqid); fprintf(fp, " protocol %s ", strxf_proto(sa_id->proto)); fprintf(fp, " SPI 0x%x", ntohl(sa_id->spi)); }
const char *format_host(int af, int len, const void *addr, char *buf, int buflen) { #ifdef RESOLVE_HOSTNAMES if (resolve_hosts) { const char *n; len = len <= 0 ? af_byte_len(af) : len; if (len > 0 && (n = resolve_address(addr, len, af)) != NULL) return n; } #endif return rt_addr_n2a(af, len, addr, buf, buflen); }
static int xfrm_ae_print(struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct xfrm_aevent_id *id = NLMSG_DATA(n); fprintf(fp, "Async event "); xfrm_ae_flags_print(id->flags, arg); fprintf(fp, "\n\t"); fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family, sizeof(id->saddr), &id->saddr)); xfrm_usersa_print(&id->sa_id, id->reqid, fp); fprintf(fp, "\n"); fflush(fp); return 0; }
static int xfrm_ae_print(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct xfrm_aevent_id *id = NLMSG_DATA(n); char abuf[256]; fprintf(fp, "Async event "); xfrm_ae_flags_print(id->flags, arg); fprintf(fp,"\n\t"); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family, sizeof(id->saddr), &id->saddr, abuf, sizeof(abuf))); xfrm_usersa_print(&id->sa_id, id->reqid, fp); fprintf(fp, "\n"); fflush(fp); return 0; }
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp, const char *prefix) { if (tb[XFRMA_MARK]) { struct rtattr *rta = tb[XFRMA_MARK]; struct xfrm_mark *m = (struct xfrm_mark *) RTA_DATA(rta); fprintf(fp, "\tmark %d/0x%x\n", m->v, m->m); } if (tb[XFRMA_ALG_AUTH]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AEAD]) { struct rtattr *rta = tb[XFRMA_ALG_AEAD]; xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_CRYPT]) { struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_COMP]) { struct rtattr *rta = tb[XFRMA_ALG_COMP]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ENCAP]) { struct xfrm_encap_tmpl *e; char abuf[256]; if (prefix) fputs(prefix, fp); fprintf(fp, "encap "); if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); fprintf(fp, "type "); switch (e->encap_type) { case 1: fprintf(fp, "espinudp-nonike "); break; case 2: fprintf(fp, "espinudp "); break; default: fprintf(fp, "%u ", e->encap_type); break; } fprintf(fp, "sport %u ", ntohs(e->encap_sport)); fprintf(fp, "dport %u ", ntohs(e->encap_dport)); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "addr %s", rt_addr_n2a(family, sizeof(e->encap_oa), &e->encap_oa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_TMPL]) { struct rtattr *rta = tb[XFRMA_TMPL]; xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), RTA_PAYLOAD(rta), family, fp, prefix); } if (tb[XFRMA_COADDR]) { char abuf[256]; xfrm_address_t *coa; if (prefix) fputs(prefix, fp); fprintf(fp, "coa "); coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]); if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*coa), coa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_LASTUSED]) { __u64 lastused; if (prefix) fputs(prefix, fp); fprintf(fp, "lastused "); if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } lastused = *(__u64 *)RTA_DATA(tb[XFRMA_LASTUSED]); fprintf(fp, "%s", strxf_time(lastused)); fprintf(fp, "%s", _SL_); } }
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; /* 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))); 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))); ifa_flags = ifa->ifa_flags; if (ifa->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->ifa_flags&IFA_F_TENTATIVE) { ifa_flags &= ~IFA_F_TENTATIVE; fprintf(fp, "tentative "); } if (ifa->ifa_flags&IFA_F_DEPRECATED) { ifa_flags &= ~IFA_F_DEPRECATED; deprecated = 1; fprintf(fp, "deprecated "); } if (ifa->ifa_flags&IFA_F_HOMEADDRESS) { ifa_flags &= ~IFA_F_HOMEADDRESS; fprintf(fp, "home "); } if (ifa->ifa_flags&IFA_F_NODAD) { ifa_flags &= ~IFA_F_NODAD; fprintf(fp, "nodad "); } if (!(ifa->ifa_flags&IFA_F_PERMANENT)) { fprintf(fp, "dynamic "); } else ifa_flags &= ~IFA_F_PERMANENT; if (ifa->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 bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { unsigned ifindex; if (!tb) return; if (tb[IFLA_BOND_MODE]) { const char *mode = get_name(mode_tbl, rta_getattr_u8(tb[IFLA_BOND_MODE])); fprintf(f, "mode %s ", mode); } if (tb[IFLA_BOND_ACTIVE_SLAVE] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "active_slave %s ", n); else fprintf(f, "active_slave %u ", ifindex); } if (tb[IFLA_BOND_MIIMON]) fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON])); if (tb[IFLA_BOND_UPDELAY]) fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY])); if (tb[IFLA_BOND_DOWNDELAY]) fprintf(f, "downdelay %u ", rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY])); if (tb[IFLA_BOND_USE_CARRIER]) fprintf(f, "use_carrier %u ", rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER])); if (tb[IFLA_BOND_ARP_INTERVAL]) fprintf(f, "arp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL])); if (tb[IFLA_BOND_ARP_IP_TARGET]) { struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1]; char buf[INET_ADDRSTRLEN]; int i; parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, tb[IFLA_BOND_ARP_IP_TARGET]); if (iptb[0]) fprintf(f, "arp_ip_target "); for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { if (iptb[i]) fprintf(f, "%s", rt_addr_n2a(AF_INET, RTA_PAYLOAD(iptb[i]), RTA_DATA(iptb[i]), buf, INET_ADDRSTRLEN)); if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1]) fprintf(f, ","); } if (iptb[0]) fprintf(f, " "); } if (tb[IFLA_BOND_ARP_VALIDATE]) { const char *arp_validate = get_name(arp_validate_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE])); fprintf(f, "arp_validate %s ", arp_validate); } if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { const char *arp_all_targets = get_name(arp_all_targets_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); fprintf(f, "arp_all_targets %s ", arp_all_targets); } if (tb[IFLA_BOND_PRIMARY] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "primary %s ", n); else fprintf(f, "primary %u ", ifindex); } if (tb[IFLA_BOND_PRIMARY_RESELECT]) { const char *primary_reselect = get_name(primary_reselect_tbl, rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT])); fprintf(f, "primary_reselect %s ", primary_reselect); } if (tb[IFLA_BOND_FAIL_OVER_MAC]) { const char *fail_over_mac = get_name(fail_over_mac_tbl, rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC])); fprintf(f, "fail_over_mac %s ", fail_over_mac); } if (tb[IFLA_BOND_XMIT_HASH_POLICY]) { const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl, rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY])); fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy); } if (tb[IFLA_BOND_RESEND_IGMP]) fprintf(f, "resend_igmp %u ", rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP])); if (tb[IFLA_BOND_NUM_PEER_NOTIF]) fprintf(f, "num_grat_arp %u ", rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF])); if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) fprintf(f, "all_slaves_active %u ", rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE])); if (tb[IFLA_BOND_MIN_LINKS]) fprintf(f, "min_links %u ", rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS])); if (tb[IFLA_BOND_LP_INTERVAL]) fprintf(f, "lp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL])); if (tb[IFLA_BOND_PACKETS_PER_SLAVE]) fprintf(f, "packets_per_slave %u ", rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE])); if (tb[IFLA_BOND_AD_LACP_RATE]) { const char *lacp_rate = get_name(lacp_rate_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE])); fprintf(f, "lacp_rate %s ", lacp_rate); } if (tb[IFLA_BOND_AD_SELECT]) { const char *ad_select = get_name(ad_select_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_SELECT])); fprintf(f, "ad_select %s ", ad_select); } if (tb[IFLA_BOND_AD_INFO]) { struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1]; parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX, tb[IFLA_BOND_AD_INFO]); if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR]) fprintf(f, "ad_aggregator %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR])); if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS]) fprintf(f, "ad_num_ports %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS])); if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]) fprintf(f, "ad_actor_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]) fprintf(f, "ad_partner_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) { unsigned char *p = RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]); SPRINT_BUF(b); fprintf(f, "ad_partner_mac %s ", ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); } } if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) { fprintf(f, "ad_actor_sys_prio %u ", rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO])); } if (tb[IFLA_BOND_AD_USER_PORT_KEY]) { fprintf(f, "ad_user_port_key %u ", rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY])); } if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) { /* We assume the l2 address is an Ethernet MAC address */ SPRINT_BUF(b1); fprintf(f, "ad_actor_system %s ", ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), 1 /*ARPHDR_ETHER*/, b1, sizeof(b1))); } if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) { fprintf(f, "tlb_dynamic_lb %u ", rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB])); } }
static void print_tunnel(struct ip_tunnel_parm *p) { struct ip_tunnel_6rd ip6rd; char s1[1024]; char s2[1024]; memset(&ip6rd, 0, sizeof(ip6rd)); /* Do not use format_host() for local addr, * symbolic name will not be useful. */ printf("%s: %s/ip remote %s local %s ", p->name, tnl_strproto(p->iph.protocol), p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1)) : "any", p->iph.saddr ? rt_addr_n2a(AF_INET, &p->iph.saddr, s2, sizeof(s2)) : "any"); if (p->iph.protocol == IPPROTO_IPV6 && (p->i_flags & SIT_ISATAP)) { struct ip_tunnel_prl prl[16]; int i; memset(prl, 0, sizeof(prl)); prl[0].datalen = sizeof(prl) - sizeof(prl[0]); prl[0].addr = htonl(INADDR_ANY); if (!tnl_prl_ioctl(SIOCGETPRL, p->name, prl)) for (i = 1; i < sizeof(prl) / sizeof(prl[0]); i++) { if (prl[i].addr != htonl(INADDR_ANY)) { printf(" %s %s ", (prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr", format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1))); } } } if (p->link) { const char *n = ll_index_to_name(p->link); if (n) printf(" dev %s ", n); } if (p->iph.ttl) printf(" ttl %d ", p->iph.ttl); else printf(" ttl inherit "); if (p->iph.tos) { SPRINT_BUF(b1); printf(" tos"); if (p->iph.tos&1) printf(" inherit"); if (p->iph.tos&~1) printf("%c%s ", p->iph.tos&1 ? '/' : ' ', rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1))); } if (!(p->iph.frag_off&htons(IP_DF))) printf(" nopmtudisc"); if (p->iph.protocol == IPPROTO_IPV6 && !tnl_ioctl_get_6rd(p->name, &ip6rd) && ip6rd.prefixlen) { printf(" 6rd-prefix %s/%u ", inet_ntop(AF_INET6, &ip6rd.prefix, s1, sizeof(s1)), ip6rd.prefixlen); if (ip6rd.relay_prefix) { printf("6rd-relay_prefix %s/%u ", format_host(AF_INET, 4, &ip6rd.relay_prefix, s1, sizeof(s1)), ip6rd.relay_prefixlen); } } if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key) printf(" key %u", ntohl(p->i_key)); else if ((p->i_flags|p->o_flags)&GRE_KEY) { if (p->i_flags&GRE_KEY) printf(" ikey %u ", ntohl(p->i_key)); if (p->o_flags&GRE_KEY) printf(" okey %u ", ntohl(p->o_key)); } if (p->i_flags&GRE_SEQ) printf("%s Drop packets out of sequence.\n", _SL_); if (p->i_flags&GRE_CSUM) printf("%s Checksum in received packet is required.", _SL_); if (p->o_flags&GRE_SEQ) printf("%s Sequence packets on output.", _SL_); if (p->o_flags&GRE_CSUM) printf("%s Checksum output packets.", _SL_); }
static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { char s1[256]; char s2[64]; int flags = 0; __u32 flowinfo = 0; if (!tb) return; if (tb[IFLA_IPTUN_FLAGS]) flags = rta_getattr_u32(tb[IFLA_IPTUN_FLAGS]); if (tb[IFLA_IPTUN_FLOWINFO]) flowinfo = rta_getattr_u32(tb[IFLA_IPTUN_FLOWINFO]); if (tb[IFLA_IPTUN_PROTO]) { switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) { case IPPROTO_IPIP: fprintf(f, "ipip6 "); break; case IPPROTO_IPV6: fprintf(f, "ip6ip6 "); break; case 0: fprintf(f, "any "); break; } } if (tb[IFLA_IPTUN_REMOTE]) { fprintf(f, "remote %s ", rt_addr_n2a(AF_INET6, RTA_PAYLOAD(tb[IFLA_IPTUN_REMOTE]), RTA_DATA(tb[IFLA_IPTUN_REMOTE]), s1, sizeof(s1))); } if (tb[IFLA_IPTUN_LOCAL]) { fprintf(f, "local %s ", rt_addr_n2a(AF_INET6, RTA_PAYLOAD(tb[IFLA_IPTUN_LOCAL]), RTA_DATA(tb[IFLA_IPTUN_LOCAL]), s1, sizeof(s1))); } if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); const char *n = if_indextoname(link, s2); if (n) fprintf(f, "dev %s ", n); else fprintf(f, "dev %u ", link); } if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) printf("encaplimit none "); else if (tb[IFLA_IPTUN_ENCAP_LIMIT]) fprintf(f, "encaplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT])); if (tb[IFLA_IPTUN_TTL]) fprintf(f, "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL])); if (flags & IP6_TNL_F_USE_ORIG_TCLASS) printf("tclass inherit "); else if (tb[IFLA_IPTUN_FLOWINFO]) { __u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS); printf("tclass 0x%02x ", (__u8)(val >> 20)); } if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) printf("flowlabel inherit "); else printf("flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); printf("(flowinfo 0x%08x) ", ntohl(flowinfo)); if (flags & IP6_TNL_F_RCV_DSCP_COPY) printf("dscp inherit "); if (flags & IP6_TNL_F_MIP6_DEV) fprintf(f, "mip6 "); if (flags & IP6_TNL_F_USE_ORIG_FWMARK) fprintf(f, "fwmark inherit "); }
void xfrm_selector_print(struct xfrm_selector *sel, __u16 family, FILE *fp, const char *prefix) { char abuf[256]; __u16 f; f = sel->family; if (f == AF_UNSPEC) f = family; if (f == AF_UNSPEC) f = preferred_family; if (prefix) fputs(prefix, fp); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "src %s/%u ", rt_addr_n2a(f, sizeof(sel->saddr), &sel->saddr, abuf, sizeof(abuf)), sel->prefixlen_s); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "dst %s/%u ", rt_addr_n2a(f, sizeof(sel->daddr), &sel->daddr, abuf, sizeof(abuf)), sel->prefixlen_d); if (sel->proto) fprintf(fp, "proto %s ", strxf_proto(sel->proto)); switch (sel->proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_SCTP: case IPPROTO_DCCP: default: /* XXX */ if (sel->sport_mask) fprintf(fp, "sport %u ", ntohs(sel->sport)); if (sel->dport_mask) fprintf(fp, "dport %u ", ntohs(sel->dport)); break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: /* type/code is stored at sport/dport in selector */ if (sel->sport_mask) fprintf(fp, "type %u ", ntohs(sel->sport)); if (sel->dport_mask) fprintf(fp, "code %u ", ntohs(sel->dport)); break; case IPPROTO_GRE: if (sel->sport_mask || sel->dport_mask) fprintf(fp, "key %u ", (((__u32)ntohs(sel->sport)) << 16) + ntohs(sel->dport)); break; case IPPROTO_MH: if (sel->sport_mask) fprintf(fp, "type %u ", ntohs(sel->sport)); if (sel->dport_mask) { if (show_stats > 0) fprintf(fp, "(dport) 0x%.4x ", sel->dport); } break; } if (sel->ifindex > 0) fprintf(fp, "dev %s ", ll_index_to_name(sel->ifindex)); if (show_stats > 0) fprintf(fp, "uid %u", sel->user); fprintf(fp, "%s", _SL_); }
int delete_route(char *address, int netmask) { struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } struct iplink_req req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.n.nlmsg_type = RTM_DELROUTE; req.rtm.rtm_family = AF_UNSPEC; req.rtm.rtm_table = RT_TABLE_MAIN; req.rtm.rtm_scope = RT_SCOPE_NOWHERE; inet_prefix dst; get_prefix(&dst, address, req.rtm.rtm_family); req.rtm.rtm_family = dst.family; if (req.rtm.rtm_family == AF_UNSPEC) { req.rtm.rtm_family = AF_INET; } req.rtm.rtm_dst_len = netmask; if (dst.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } ll_init_map(&rth); struct nlmsghdr *answer; int errnum = rtnl_talkE(&rth, &req.n, 0, 0, &answer, NULL, NULL); if (errnum < 0) { exit(2); } if (answer) { switch (errnum) { case 0: // Success fprintf(stderr, "delete route to %s\n", address); break; case 3: // No such device // fprintf(stderr, "already deleted.\n"); break; default: fprintf(stderr, "ERROR!\terrno: %d\n", errnum); perror("Netlink"); exit(2); break; } } else { fprintf(stderr, "Something Wrong!\n"); exit(2); } return 0; } int delete_all_route() { struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } int preferred_family = AF_PACKET; if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); exit(1); } struct nlmsg_list *rinfo = NULL; if (rtnl_dump_filter(&rth, store_nlmsg, &rinfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } struct nlmsg_list *r, *n; for (r = rinfo; r; r = n) { n = r->next; struct nlmsghdr *nlhdr = &(r->h); if (nlhdr->nlmsg_type != RTM_NEWROUTE && nlhdr->nlmsg_type != RTM_DELROUTE) { fprintf(stderr, "Not a route: %08x %08x %08x\n", nlhdr->nlmsg_len, nlhdr->nlmsg_type, nlhdr->nlmsg_flags); return 0; } struct rtmsg *rtm = NLMSG_DATA(nlhdr); int len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } // Analyze rtattr Message struct rtattr *tb[RTA_MAX + 1]; parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); char dst_address[64] = ""; char abuf[256]; int host_len = calc_host_len(rtm); if (tb[RTA_DST]) { if (rtm->rtm_dst_len != host_len) { sprintf(dst_address, "%s/%d", rt_addr_n2a(rtm->rtm_family, RTA_PAYLOAD(tb[RTA_DST]), RTA_DATA(tb[RTA_DST]), abuf, sizeof(abuf)), rtm->rtm_dst_len); } else { sprintf(dst_address, "%s", format_host(rtm->rtm_family, RTA_PAYLOAD(tb[RTA_DST]), RTA_DATA(tb[RTA_DST]), abuf, sizeof(abuf))); } } else if (rtm->rtm_dst_len) { sprintf(dst_address, "0/%d", rtm->rtm_dst_len); } else { sprintf(dst_address, "default"); } if (strncmp(dst_address, "127.0.0.0", 9) != 0 && strcmp(dst_address, "ff00::") != 0) { delete_route((char *) dst_address, rtm->rtm_dst_len); } } printf("delete all routes.\n\n"); free(r); rtnl_close(&rth); return 0; } // network is unreachableを回避するため、全経路を登録し終えるまでwhileループを回す void modify_route(json_t *ipRouteEntry_json, int default_flag) { int end = 0; while (end == 0) { end = 1; int i; for (i = 0; i < (int) json_array_size(ipRouteEntry_json); i++) { json_t *route_json = json_array_get(ipRouteEntry_json, i); json_t *linux_json = json_object_get(route_json, "linux"); struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } struct iplink_req req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; req.n.nlmsg_type = RTM_NEWROUTE; req.rtm.rtm_family = AF_UNSPEC; req.rtm.rtm_type = (int) json_number_value(json_object_get(route_json, "ipRouteType")); if (req.rtm.rtm_type >= 5) { // 5以降は定義されていない req.rtm.rtm_type = 1; } req.rtm.rtm_protocol = (int) json_number_value(json_object_get(route_json, "ipRouteProto")); req.rtm.rtm_scope = (int) json_number_value(json_object_get(linux_json, "rtm_scope")); req.rtm.rtm_table = (int) json_number_value(json_object_get(linux_json, "rtm_table")); req.rtm.rtm_dst_len = (int) json_number_value(json_object_get(route_json, "ipRouteMask")); char *route_name = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; const char *key; json_t *value; json_object_foreach(route_json, key, value) { if (strcmp(key, "ipRouteDest") == 0) { inet_prefix dst; route_name = (char *) json_string_value(value); get_prefix(&dst, route_name, req.rtm.rtm_family); if (req.rtm.rtm_family == AF_UNSPEC) { req.rtm.rtm_family = dst.family; } if (dst.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } } if (strcmp(key, "ipRouteIfIndex") == 0) { addattr32(&req.n, sizeof(req), RTA_OIF, json_integer_value(value)); } if (strcmp(key, "ipRouteNextHop") == 0) { inet_prefix addr; get_addr(&addr, (char *) json_string_value(value), req.rtm.rtm_family); if (req.rtm.rtm_family == AF_UNSPEC) { req.rtm.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); } if (strcmp(key, "ipRouteMetric1") == 0) { addattr32(&req.n, sizeof(req), RTA_PRIORITY, json_integer_value(value)); } if (strcmp(key, "ipRouteInfo") == 0) { inet_prefix addr; get_addr(&addr, (char *) json_string_value(value), req.rtm.rtm_family); if (req.rtm.rtm_family == AF_UNSPEC) { req.rtm.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); } } ll_init_map(&rth); if (req.rtm.rtm_family == AF_UNSPEC) { req.rtm.rtm_family = AF_INET; } struct nlmsghdr *answer; int errnum = rtnl_talkE(&rth, &req.n, 0, 0, &answer, NULL, NULL); if (errnum < 0) { exit(2); } if (answer) { switch (errnum) { case 0: // Success fprintf(stderr, "arrange route to %s/%d\n", route_name, req.rtm.rtm_dst_len); break; case 17: // File exists // fprintf(stderr, "route already exists.\n"); break; case 19: // No such device // fprintf(stderr, "No such device"); break; case 101: // Network is unreachable end = 0; break; default: fprintf(stderr, "ERROR!\terrno: %d\n", errnum); perror("Netlink"); exit(2); break; } } else { fprintf(stderr, "Something Wrong!\n"); exit(2); } } } } int read_route_file(json_t *routes_json) { // routeの削除 delete_all_route(); json_t *ipRouteEntry_json = json_object_get(routes_json, "ipRouteEntry"); // defaultへの経路はGatewayへの経路が登録されてからでないとnetwork is unreachableになるので // defaultへの経路とそうでないものを分ける modify_route(ipRouteEntry_json, 0); modify_route(ipRouteEntry_json, 1); fprintf(stderr, "Success arranging all routes!\n\n"); 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; }
static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a) { fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*a), a)); }
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp, const char *prefix) { if (tb[XFRMA_MARK]) { struct rtattr *rta = tb[XFRMA_MARK]; struct xfrm_mark *m = (struct xfrm_mark *) RTA_DATA(rta); fprintf(fp, "\tmark %#x/%#x", m->v, m->m); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_ALG_AUTH] && !tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH_TRUNC]; xfrm_auth_trunc_print((struct xfrm_algo_auth *) RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AEAD]) { struct rtattr *rta = tb[XFRMA_ALG_AEAD]; xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_CRYPT]) { struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_COMP]) { struct rtattr *rta = tb[XFRMA_ALG_COMP]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ENCAP]) { struct xfrm_encap_tmpl *e; char abuf[256]; if (prefix) fputs(prefix, fp); fprintf(fp, "encap "); if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); fprintf(fp, "type "); switch (e->encap_type) { case 1: fprintf(fp, "espinudp-nonike "); break; case 2: fprintf(fp, "espinudp "); break; default: fprintf(fp, "%u ", e->encap_type); break; } fprintf(fp, "sport %u ", ntohs(e->encap_sport)); fprintf(fp, "dport %u ", ntohs(e->encap_dport)); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "addr %s", rt_addr_n2a(family, sizeof(e->encap_oa), &e->encap_oa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_TMPL]) { struct rtattr *rta = tb[XFRMA_TMPL]; xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_COADDR]) { char abuf[256]; xfrm_address_t *coa; if (prefix) fputs(prefix, fp); fprintf(fp, "coa "); coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]); if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*coa), coa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_LASTUSED]) { __u64 lastused; if (prefix) fputs(prefix, fp); fprintf(fp, "lastused "); if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } lastused = rta_getattr_u64(tb[XFRMA_LASTUSED]); fprintf(fp, "%s", strxf_time(lastused)); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_REPLAY_VAL]) { struct xfrm_replay_state *replay; if (prefix) fputs(prefix, fp); fprintf(fp, "anti-replay context: "); if (RTA_PAYLOAD(tb[XFRMA_REPLAY_VAL]) < sizeof(*replay)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } replay = (struct xfrm_replay_state *)RTA_DATA(tb[XFRMA_REPLAY_VAL]); fprintf(fp, "seq 0x%x, oseq 0x%x, bitmap 0x%08x", replay->seq, replay->oseq, replay->bitmap); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_REPLAY_ESN_VAL]) { struct xfrm_replay_state_esn *replay; unsigned int i, j; if (prefix) fputs(prefix, fp); fprintf(fp, "anti-replay esn context:"); if (RTA_PAYLOAD(tb[XFRMA_REPLAY_ESN_VAL]) < sizeof(*replay)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } fprintf(fp, "%s", _SL_); replay = (struct xfrm_replay_state_esn *)RTA_DATA(tb[XFRMA_REPLAY_ESN_VAL]); if (prefix) fputs(prefix, fp); fprintf(fp, " seq-hi 0x%x, seq 0x%x, oseq-hi 0x%0x, oseq 0x%0x", replay->seq_hi, replay->seq, replay->oseq_hi, replay->oseq); fprintf(fp, "%s", _SL_); if (prefix) fputs(prefix, fp); fprintf(fp, " replay_window %u, bitmap-length %u", replay->replay_window, replay->bmp_len); for (i = replay->bmp_len, j = 0; i; i--) { if (j++ % 8 == 0) { fprintf(fp, "%s", _SL_); if (prefix) fputs(prefix, fp); fprintf(fp, " "); } fprintf(fp, "%08x ", replay->bmp[i - 1]); } fprintf(fp, "%s", _SL_); } }
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_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 void print_tunnel(struct ip_tunnel_parm *p) { char s1[1024]; char s2[1024]; char s3[64]; char s4[64]; inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3)); inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4)); /* Do not use format_host() for local addr, * symbolic name will not be useful. */ printf("%s: %s/ip remote %s local %s ", p->name, tnl_strproto(p->iph.protocol), p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1)) : "any", p->iph.saddr ? rt_addr_n2a(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2)) : "any"); if (p->link) { char *n = tnl_ioctl_get_ifname(p->link); if (n) printf(" dev %s ", n); } if (p->iph.ttl) printf(" ttl %d ", p->iph.ttl); else printf(" ttl inherit "); if (p->iph.tos) { SPRINT_BUF(b1); printf(" tos"); if (p->iph.tos&1) printf(" inherit"); if (p->iph.tos&~1) printf("%c%s ", p->iph.tos&1 ? '/' : ' ', rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1))); } if (!(p->iph.frag_off&htons(IP_DF))) printf(" nopmtudisc"); if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key) printf(" key %s", s3); else if ((p->i_flags|p->o_flags)&GRE_KEY) { if (p->i_flags&GRE_KEY) printf(" ikey %s ", s3); if (p->o_flags&GRE_KEY) printf(" okey %s ", s4); } if (p->i_flags&GRE_SEQ) printf("%s Drop packets out of sequence.\n", _SL_); if (p->i_flags&GRE_CSUM) printf("%s Checksum in received packet is required.", _SL_); if (p->o_flags&GRE_SEQ) printf("%s Sequence packets on output.", _SL_); if (p->o_flags&GRE_CSUM) printf("%s Checksum output packets.", _SL_); }
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_addrinfo(struct sockaddr_nl ATTRIBUTE_UNUSED *who, struct nlmsghdr *n, void ATTRIBUTE_UNUSED *arg) { FILE *fp = (FILE*)arg; struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; 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) { bb_error_msg("wrong nlmsg len %d", len); return -1; } if (filter.flushb && n->nlmsg_type != RTM_NEWADDR) return 0; 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]; 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) { 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.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 = ++filter.rth->seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; return 0; } if (n->nlmsg_type == RTM_DELADDR) fprintf(fp, "Deleted "); if (filter.oneline) 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 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; 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; fprintf(fp, "deprecated "); } if (!(ifa->ifa_flags&IFA_F_PERMANENT)) { fprintf(fp, "dynamic "); } else ifa->ifa_flags &= ~IFA_F_PERMANENT; 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]; fputc(_SL_, fp); if (ci->ifa_valid == 0xFFFFFFFFU) sprintf(buf, "valid_lft forever"); else sprintf(buf, "valid_lft %dsec", ci->ifa_valid); if (ci->ifa_prefered == 0xFFFFFFFFU) sprintf(buf+strlen(buf), " preferred_lft forever"); else sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered); fprintf(fp, " %s", buf); } fputc('\n', fp); fflush(fp); return 0; }
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp, const char *prefix) { if (tb[XFRMA_ALG_AUTH]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_CRYPT]) { struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_COMP]) { struct rtattr *rta = tb[XFRMA_ALG_COMP]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ENCAP]) { struct xfrm_encap_tmpl *e; char abuf[256]; if (prefix) fprintf(fp, prefix); fprintf(fp, "encap "); if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); fprintf(fp, "type "); switch (e->encap_type) { case 1: fprintf(fp, "espinudp-nonike "); break; case 2: fprintf(fp, "espinudp "); break; default: fprintf(fp, "%u ", e->encap_type); break; } fprintf(fp, "sport %u ", ntohs(e->encap_sport)); fprintf(fp, "dport %u ", ntohs(e->encap_dport)); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "addr %s", rt_addr_n2a(family, sizeof(e->encap_oa), &e->encap_oa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_TMPL]) { struct rtattr *rta = tb[XFRMA_TMPL]; xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), RTA_PAYLOAD(rta), family, fp, prefix); } }