| 852 | #endif /* INET */ |
| 853 | |
| 854 | static int |
| 855 | udp_pcblist(SYSCTL_HANDLER_ARGS) |
| 856 | { |
| 857 | struct xinpgen xig; |
| 858 | struct epoch_tracker et; |
| 859 | struct inpcb *inp; |
| 860 | int error; |
| 861 | |
| 862 | if (req->newptr != 0) |
| 863 | return (EPERM); |
| 864 | |
| 865 | if (req->oldptr == 0) { |
| 866 | int n; |
| 867 | |
| 868 | n = V_udbinfo.ipi_count; |
| 869 | n += imax(n / 8, 10); |
| 870 | req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xinpcb); |
| 871 | return (0); |
| 872 | } |
| 873 | |
| 874 | if ((error = sysctl_wire_old_buffer(req, 0)) != 0) |
| 875 | return (error); |
| 876 | |
| 877 | bzero(&xig, sizeof(xig)); |
| 878 | xig.xig_len = sizeof xig; |
| 879 | xig.xig_count = V_udbinfo.ipi_count; |
| 880 | xig.xig_gen = V_udbinfo.ipi_gencnt; |
| 881 | xig.xig_sogen = so_gencnt; |
| 882 | error = SYSCTL_OUT(req, &xig, sizeof xig); |
| 883 | if (error) |
| 884 | return (error); |
| 885 | |
| 886 | NET_EPOCH_ENTER(et); |
| 887 | for (inp = CK_LIST_FIRST(V_udbinfo.ipi_listhead); |
| 888 | inp != NULL; |
| 889 | inp = CK_LIST_NEXT(inp, inp_list)) { |
| 890 | INP_RLOCK(inp); |
| 891 | if (inp->inp_gencnt <= xig.xig_gen && |
| 892 | cr_canseeinpcb(req->td->td_ucred, inp) == 0) { |
| 893 | struct xinpcb xi; |
| 894 | |
| 895 | in_pcbtoxinpcb(inp, &xi); |
| 896 | INP_RUNLOCK(inp); |
| 897 | error = SYSCTL_OUT(req, &xi, sizeof xi); |
| 898 | if (error) |
| 899 | break; |
| 900 | } else |
| 901 | INP_RUNLOCK(inp); |
| 902 | } |
| 903 | NET_EPOCH_EXIT(et); |
| 904 | |
| 905 | if (!error) { |
| 906 | /* |
| 907 | * Give the user an updated idea of our state. If the |
| 908 | * generation differs from what we told her before, she knows |
| 909 | * that something happened while we were processing this |
| 910 | * request, and it might be necessary to retry. |
| 911 | */ |
nothing calls this directly
no test coverage detected