Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/netstat/nhops.c
| Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
| }; | }; | ||||
| struct nhop_map { | struct nhop_map { | ||||
| struct nhop_entry *ptr; | struct nhop_entry *ptr; | ||||
| size_t size; | size_t size; | ||||
| }; | }; | ||||
| static struct nhop_map global_nhop_map; | static struct nhop_map global_nhop_map; | ||||
| static void nhop_map_update(struct nhop_map *map, uint32_t idx, | |||||
| char *gw, char *ifname); | |||||
| static struct nhop_entry *nhop_get(struct nhop_map *map, uint32_t idx); | static struct nhop_entry *nhop_get(struct nhop_map *map, uint32_t idx); | ||||
| static struct ifmap_entry *ifmap; | static struct ifmap_entry *ifmap; | ||||
| static size_t ifmap_size; | static size_t ifmap_size; | ||||
| static void | static void | ||||
| print_sockaddr_buf(char *buf, size_t bufsize, const struct sockaddr *sa) | print_sockaddr_buf(char *buf, size_t bufsize, const struct sockaddr *sa) | ||||
| ▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " | ||||
| wid_dst, wid_dst, "IFA", | wid_dst, wid_dst, "IFA", | ||||
| wid_gw, wid_gw, "Gateway", | wid_gw, wid_gw, "Gateway", | ||||
| wid_flags, wid_flags, "Flags", | wid_flags, wid_flags, "Flags", | ||||
| wid_if, wid_if, "Netif", | wid_if, wid_if, "Netif", | ||||
| wid_prepend, "Refcnt"); | wid_prepend, "Refcnt"); | ||||
| } | } | ||||
| } | } | ||||
| static void | void | ||||
| nhop_map_update(struct nhop_map *map, uint32_t idx, char *gw, char *ifname) | nhop_map_update(struct nhop_map *map, uint32_t idx, char *gw, char *ifname) | ||||
| { | { | ||||
| if (idx >= map->size) { | if (idx >= map->size) { | ||||
| uint32_t new_size; | uint32_t new_size; | ||||
| size_t sz; | size_t sz; | ||||
| if (map->size == 0) | if (map->size == 0) | ||||
| new_size = 32; | new_size = 32; | ||||
| else | else | ||||
| ▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | if (Wflag && nh->prepend_len) { | ||||
| char *prepend_hex = "AABBCCDDEE"; | char *prepend_hex = "AABBCCDDEE"; | ||||
| xo_emit(" {:nhop-prepend/%*s}", wid_prepend, prepend_hex); | xo_emit(" {:nhop-prepend/%*s}", wid_prepend, prepend_hex); | ||||
| } | } | ||||
| xo_emit("\n"); | xo_emit("\n"); | ||||
| xo_close_instance(name); | xo_close_instance(name); | ||||
| } | } | ||||
| struct nhops_map { | |||||
| uint32_t idx; | |||||
| struct rt_msghdr *rtm; | |||||
| }; | |||||
| static int | static int | ||||
| cmp_nh_idx(const void *_a, const void *_b) | cmp_nh_idx(const void *_a, const void *_b) | ||||
| { | { | ||||
| const struct nhops_map *a, *b; | const struct nhops_map *a, *b; | ||||
| a = _a; | a = _a; | ||||
| b = _b; | b = _b; | ||||
| if (a->idx > b->idx) | if (a->idx > b->idx) | ||||
| return (1); | return (1); | ||||
| else if (a->idx < b->idx) | else if (a->idx < b->idx) | ||||
| return (-1); | return (-1); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static void | void | ||||
| print_nhops_sysctl(int fibnum, int af) | dump_nhops_sysctl(int fibnum, int af, struct nhops_dump *nd) | ||||
| { | { | ||||
| size_t needed; | size_t needed; | ||||
| int mib[7]; | int mib[7]; | ||||
| char *buf, *next, *lim; | char *buf, *next, *lim; | ||||
| struct rt_msghdr *rtm; | struct rt_msghdr *rtm; | ||||
| struct nhop_external *nh; | struct nhop_external *nh; | ||||
| int fam; | |||||
| struct nhops_map *nh_map; | struct nhops_map *nh_map; | ||||
| size_t nh_count, nh_size; | size_t nh_count, nh_size; | ||||
| mib[0] = CTL_NET; | mib[0] = CTL_NET; | ||||
| mib[1] = PF_ROUTE; | mib[1] = PF_ROUTE; | ||||
| mib[2] = 0; | mib[2] = 0; | ||||
| mib[3] = af; | mib[3] = af; | ||||
| mib[4] = NET_RT_NHOP; | mib[4] = NET_RT_NHOP; | ||||
| mib[5] = 0; | mib[5] = 0; | ||||
| mib[6] = fibnum; | mib[6] = fibnum; | ||||
| if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) | if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) | ||||
| err(EX_OSERR, "sysctl: net.route.0.%d.nhdump.%d estimate", af, | err(EX_OSERR, "sysctl: net.route.0.%d.nhdump.%d estimate", af, | ||||
| fibnum); | fibnum); | ||||
| if ((buf = malloc(needed)) == NULL) | if ((buf = malloc(needed)) == NULL) | ||||
| errx(2, "malloc(%lu)", (unsigned long)needed); | errx(2, "malloc(%lu)", (unsigned long)needed); | ||||
| if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) | if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) | ||||
| err(1, "sysctl: net.route.0.%d.nhdump.%d", af, fibnum); | err(1, "sysctl: net.route.0.%d.nhdump.%d", af, fibnum); | ||||
| lim = buf + needed; | lim = buf + needed; | ||||
| xo_open_container("nhop-table"); | |||||
| xo_open_list("rt-family"); | |||||
| /* | /* | ||||
| * nexhops are received unsorted. Collect everything first, sort and then display | * nexhops are received unsorted. Collect everything first, sort and then display | ||||
| * sorted. | * sorted. | ||||
| */ | */ | ||||
| nh_count = 0; | nh_count = 0; | ||||
| nh_size = 16; | nh_size = 16; | ||||
| nh_map = calloc(nh_size, sizeof(struct nhops_map)); | nh_map = calloc(nh_size, sizeof(struct nhops_map)); | ||||
| for (next = buf; next < lim; next += rtm->rtm_msglen) { | for (next = buf; next < lim; next += rtm->rtm_msglen) { | ||||
| rtm = (struct rt_msghdr *)next; | rtm = (struct rt_msghdr *)next; | ||||
| if (rtm->rtm_version != RTM_VERSION) | if (rtm->rtm_version != RTM_VERSION) | ||||
| continue; | continue; | ||||
| if (nh_count >= nh_size) { | if (nh_count >= nh_size) { | ||||
| nh_size *= 2; | nh_size *= 2; | ||||
| nh_map = realloc(nh_map, nh_size * sizeof(struct nhops_map)); | nh_map = realloc(nh_map, nh_size * sizeof(struct nhops_map)); | ||||
| } | } | ||||
| nh = (struct nhop_external *)(rtm + 1); | nh = (struct nhop_external *)(rtm + 1); | ||||
| nh_map[nh_count].idx = nh->nh_idx; | nh_map[nh_count].idx = nh->nh_idx; | ||||
| nh_map[nh_count].rtm = rtm; | nh_map[nh_count].rtm = rtm; | ||||
| nh_count++; | nh_count++; | ||||
| } | } | ||||
| if (nh_count > 0) { | if (nh_count > 0) | ||||
| qsort(nh_map, nh_count, sizeof(struct nhops_map), cmp_nh_idx); | qsort(nh_map, nh_count, sizeof(struct nhops_map), cmp_nh_idx); | ||||
| nh = (struct nhop_external *)(nh_map[0].rtm + 1); | nd->nh_buf = buf; | ||||
| nd->nh_count = nh_count; | |||||
| nd->nh_map = nh_map; | |||||
| } | |||||
| static void | |||||
| print_nhops_sysctl(int fibnum, int af) | |||||
| { | |||||
| struct nhops_dump nd; | |||||
| struct nhop_external *nh; | |||||
| int fam; | |||||
| struct rt_msghdr *rtm; | |||||
| dump_nhops_sysctl(fibnum, af, &nd); | |||||
| xo_open_container("nhop-table"); | |||||
| xo_open_list("rt-family"); | |||||
| if (nd.nh_count > 0) { | |||||
| nh = (struct nhop_external *)(nd.nh_map[0].rtm + 1); | |||||
| fam = nh->nh_family; | fam = nh->nh_family; | ||||
| wid_dst = WID_GW_DEFAULT(fam); | wid_dst = WID_GW_DEFAULT(fam); | ||||
| wid_gw = WID_GW_DEFAULT(fam); | wid_gw = WID_GW_DEFAULT(fam); | ||||
| wid_nhidx = 5; | wid_nhidx = 5; | ||||
| wid_nhtype = 12; | wid_nhtype = 12; | ||||
| wid_refcnt = 6; | wid_refcnt = 6; | ||||
| wid_flags = 6; | wid_flags = 6; | ||||
| wid_pksent = 8; | wid_pksent = 8; | ||||
| wid_mtu = 6; | wid_mtu = 6; | ||||
| wid_if = WID_IF_DEFAULT(fam); | wid_if = WID_IF_DEFAULT(fam); | ||||
| xo_open_instance("rt-family"); | xo_open_instance("rt-family"); | ||||
| pr_family(fam); | pr_family(fam); | ||||
| xo_open_list("nh-entry"); | xo_open_list("nh-entry"); | ||||
| print_nhop_header(fam); | print_nhop_header(fam); | ||||
| for (size_t i = 0; i < nh_count; i++) { | for (size_t i = 0; i < nd.nh_count; i++) { | ||||
| rtm = nh_map[i].rtm; | rtm = nd.nh_map[i].rtm; | ||||
| nh = (struct nhop_external *)(rtm + 1); | nh = (struct nhop_external *)(rtm + 1); | ||||
| print_nhop_entry_sysctl("nh-entry", rtm, nh); | print_nhop_entry_sysctl("nh-entry", rtm, nh); | ||||
| } | } | ||||
| xo_close_list("nh-entry"); | xo_close_list("nh-entry"); | ||||
| xo_close_instance("rt-family"); | xo_close_instance("rt-family"); | ||||
| } | } | ||||
| xo_close_list("rt-family"); | xo_close_list("rt-family"); | ||||
| xo_close_container("nhop-table"); | xo_close_container("nhop-table"); | ||||
| free(buf); | free(nd.nh_buf); | ||||
| } | } | ||||
| static void | static void | ||||
| p_nhflags(int f, const char *format) | p_nhflags(int f, const char *format) | ||||
| { | { | ||||
| struct bits *p; | struct bits *p; | ||||
| char *pretty_name = "nh_flags_pretty"; | char *pretty_name = "nh_flags_pretty"; | ||||
| Show All 35 Lines | |||||