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 |