| 2464 | } |
| 2465 | |
| 2466 | static int |
| 2467 | sysctl_rtsock(SYSCTL_HANDLER_ARGS) |
| 2468 | { |
| 2469 | struct epoch_tracker et; |
| 2470 | int *name = (int *)arg1; |
| 2471 | u_int namelen = arg2; |
| 2472 | struct rib_head *rnh = NULL; /* silence compiler. */ |
| 2473 | int i, lim, error = EINVAL; |
| 2474 | int fib = 0; |
| 2475 | u_char af; |
| 2476 | struct walkarg w; |
| 2477 | |
| 2478 | name ++; |
| 2479 | namelen--; |
| 2480 | if (req->newptr) |
| 2481 | return (EPERM); |
| 2482 | if (name[1] == NET_RT_DUMP || name[1] == NET_RT_NHOP || name[1] == NET_RT_NHGRP) { |
| 2483 | if (namelen == 3) |
| 2484 | fib = req->td->td_proc->p_fibnum; |
| 2485 | else if (namelen == 4) |
| 2486 | fib = (name[3] == RT_ALL_FIBS) ? |
| 2487 | req->td->td_proc->p_fibnum : name[3]; |
| 2488 | else |
| 2489 | return ((namelen < 3) ? EISDIR : ENOTDIR); |
| 2490 | if (fib < 0 || fib >= rt_numfibs) |
| 2491 | return (EINVAL); |
| 2492 | } else if (namelen != 3) |
| 2493 | return ((namelen < 3) ? EISDIR : ENOTDIR); |
| 2494 | af = name[0]; |
| 2495 | if (af > AF_MAX) |
| 2496 | return (EINVAL); |
| 2497 | bzero(&w, sizeof(w)); |
| 2498 | w.w_op = name[1]; |
| 2499 | w.w_arg = name[2]; |
| 2500 | w.w_req = req; |
| 2501 | |
| 2502 | error = sysctl_wire_old_buffer(req, 0); |
| 2503 | if (error) |
| 2504 | return (error); |
| 2505 | |
| 2506 | /* |
| 2507 | * Allocate reply buffer in advance. |
| 2508 | * All rtsock messages has maximum length of u_short. |
| 2509 | */ |
| 2510 | w.w_tmemsize = 65536; |
| 2511 | w.w_tmem = malloc(w.w_tmemsize, M_TEMP, M_WAITOK); |
| 2512 | |
| 2513 | NET_EPOCH_ENTER(et); |
| 2514 | switch (w.w_op) { |
| 2515 | case NET_RT_DUMP: |
| 2516 | case NET_RT_FLAGS: |
| 2517 | if (af == 0) { /* dump all tables */ |
| 2518 | i = 1; |
| 2519 | lim = AF_MAX; |
| 2520 | } else /* dump only one table */ |
| 2521 | i = lim = af; |
| 2522 | |
| 2523 | /* |
nothing calls this directly
no test coverage detected