| 341 | } |
| 342 | |
| 343 | void |
| 344 | dump_nhops_sysctl(int fibnum, int af, struct nhops_dump *nd) |
| 345 | { |
| 346 | size_t needed; |
| 347 | int mib[7]; |
| 348 | char *buf, *next, *lim; |
| 349 | struct rt_msghdr *rtm; |
| 350 | struct nhop_external *nh; |
| 351 | struct nhops_map *nh_map; |
| 352 | size_t nh_count, nh_size; |
| 353 | |
| 354 | mib[0] = CTL_NET; |
| 355 | mib[1] = PF_ROUTE; |
| 356 | mib[2] = 0; |
| 357 | mib[3] = af; |
| 358 | mib[4] = NET_RT_NHOP; |
| 359 | mib[5] = 0; |
| 360 | mib[6] = fibnum; |
| 361 | if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) |
| 362 | err(EX_OSERR, "sysctl: net.route.0.%d.nhdump.%d estimate", af, |
| 363 | fibnum); |
| 364 | if ((buf = malloc(needed)) == NULL) |
| 365 | errx(2, "malloc(%lu)", (unsigned long)needed); |
| 366 | if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) |
| 367 | err(1, "sysctl: net.route.0.%d.nhdump.%d", af, fibnum); |
| 368 | lim = buf + needed; |
| 369 | |
| 370 | /* |
| 371 | * nexhops are received unsorted. Collect everything first, sort and then display |
| 372 | * sorted. |
| 373 | */ |
| 374 | nh_count = 0; |
| 375 | nh_size = 16; |
| 376 | nh_map = calloc(nh_size, sizeof(struct nhops_map)); |
| 377 | for (next = buf; next < lim; next += rtm->rtm_msglen) { |
| 378 | rtm = (struct rt_msghdr *)next; |
| 379 | if (rtm->rtm_version != RTM_VERSION) |
| 380 | continue; |
| 381 | |
| 382 | if (nh_count >= nh_size) { |
| 383 | nh_size *= 2; |
| 384 | nh_map = realloc(nh_map, nh_size * sizeof(struct nhops_map)); |
| 385 | } |
| 386 | |
| 387 | nh = (struct nhop_external *)(rtm + 1); |
| 388 | nh_map[nh_count].idx = nh->nh_idx; |
| 389 | nh_map[nh_count].rtm = rtm; |
| 390 | nh_count++; |
| 391 | } |
| 392 | |
| 393 | if (nh_count > 0) |
| 394 | qsort(nh_map, nh_count, sizeof(struct nhops_map), cmp_nh_idx); |
| 395 | nd->nh_buf = buf; |
| 396 | nd->nh_count = nh_count; |
| 397 | nd->nh_map = nh_map; |
| 398 | } |
| 399 | |
| 400 | static void |