| 193 | } |
| 194 | |
| 195 | static void |
| 196 | dump_nhgrp_sysctl(int fibnum, int af, struct nhops_dump *nd) |
| 197 | { |
| 198 | size_t needed; |
| 199 | int mib[7]; |
| 200 | char *buf, *next, *lim; |
| 201 | struct rt_msghdr *rtm; |
| 202 | struct nhgrp_external *nhg; |
| 203 | struct nhops_map *nhg_map; |
| 204 | size_t nhg_count, nhg_size; |
| 205 | |
| 206 | mib[0] = CTL_NET; |
| 207 | mib[1] = PF_ROUTE; |
| 208 | mib[2] = 0; |
| 209 | mib[3] = af; |
| 210 | mib[4] = NET_RT_NHGRP; |
| 211 | mib[5] = 0; |
| 212 | mib[6] = fibnum; |
| 213 | if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) |
| 214 | err(EX_OSERR, "sysctl: net.route.0.%d.nhgrpdump.%d estimate", |
| 215 | af, fibnum); |
| 216 | if ((buf = malloc(needed)) == NULL) |
| 217 | errx(2, "malloc(%lu)", (unsigned long)needed); |
| 218 | if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) |
| 219 | err(1, "sysctl: net.route.0.%d.nhgrpdump.%d", af, fibnum); |
| 220 | lim = buf + needed; |
| 221 | |
| 222 | /* |
| 223 | * nexhops groups are received unsorted. Collect everything first, |
| 224 | * and sort prior displaying. |
| 225 | */ |
| 226 | nhg_count = 0; |
| 227 | nhg_size = 16; |
| 228 | nhg_map = calloc(nhg_size, sizeof(struct nhops_map)); |
| 229 | for (next = buf; next < lim; next += rtm->rtm_msglen) { |
| 230 | rtm = (struct rt_msghdr *)next; |
| 231 | if (rtm->rtm_version != RTM_VERSION) |
| 232 | continue; |
| 233 | |
| 234 | if (nhg_count >= nhg_size) { |
| 235 | nhg_size *= 2; |
| 236 | nhg_map = realloc(nhg_map, nhg_size * sizeof(struct nhops_map)); |
| 237 | } |
| 238 | |
| 239 | nhg = (struct nhgrp_external *)(rtm + 1); |
| 240 | nhg_map[nhg_count].idx = nhg->nhg_idx; |
| 241 | nhg_map[nhg_count].rtm = rtm; |
| 242 | nhg_count++; |
| 243 | } |
| 244 | |
| 245 | if (nhg_count > 0) |
| 246 | qsort(nhg_map, nhg_count, sizeof(struct nhops_map), cmp_nhg_idx); |
| 247 | nd->nh_buf = buf; |
| 248 | nd->nh_count = nhg_count; |
| 249 | nd->nh_map = nhg_map; |
| 250 | } |
| 251 | |
| 252 | static void |