1 1.256 skrll /* $NetBSD: rtsock.c,v 1.256 2022/08/27 08:36:41 skrll Exp $ */ 2 1.30 itojun 3 1.30 itojun /* 4 1.30 itojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 1.30 itojun * All rights reserved. 6 1.75 perry * 7 1.30 itojun * Redistribution and use in source and binary forms, with or without 8 1.30 itojun * modification, are permitted provided that the following conditions 9 1.30 itojun * are met: 10 1.30 itojun * 1. Redistributions of source code must retain the above copyright 11 1.30 itojun * notice, this list of conditions and the following disclaimer. 12 1.30 itojun * 2. Redistributions in binary form must reproduce the above copyright 13 1.30 itojun * notice, this list of conditions and the following disclaimer in the 14 1.30 itojun * documentation and/or other materials provided with the distribution. 15 1.30 itojun * 3. Neither the name of the project nor the names of its contributors 16 1.30 itojun * may be used to endorse or promote products derived from this software 17 1.30 itojun * without specific prior written permission. 18 1.75 perry * 19 1.30 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 1.30 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.30 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.30 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 1.30 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.30 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.30 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.30 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.30 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.30 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.30 itojun * SUCH DAMAGE. 30 1.30 itojun */ 31 1.11 cgd 32 1.1 cgd /* 33 1.10 mycroft * Copyright (c) 1988, 1991, 1993 34 1.10 mycroft * The Regents of the University of California. All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Redistribution and use in source and binary forms, with or without 37 1.1 cgd * modification, are permitted provided that the following conditions 38 1.1 cgd * are met: 39 1.1 cgd * 1. Redistributions of source code must retain the above copyright 40 1.1 cgd * notice, this list of conditions and the following disclaimer. 41 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 cgd * notice, this list of conditions and the following disclaimer in the 43 1.1 cgd * documentation and/or other materials provided with the distribution. 44 1.64 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 cgd * may be used to endorse or promote products derived from this software 46 1.1 cgd * without specific prior written permission. 47 1.1 cgd * 48 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 cgd * SUCH DAMAGE. 59 1.1 cgd * 60 1.26 fvdl * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 61 1.1 cgd */ 62 1.54 lukem 63 1.54 lukem #include <sys/cdefs.h> 64 1.256 skrll __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.256 2022/08/27 08:36:41 skrll Exp $"); 65 1.31 thorpej 66 1.133 matt #ifdef _KERNEL_OPT 67 1.31 thorpej #include "opt_inet.h" 68 1.120 christos #include "opt_compat_netbsd.h" 69 1.120 christos #endif 70 1.1 cgd 71 1.5 mycroft #include <sys/param.h> 72 1.5 mycroft #include <sys/systm.h> 73 1.10 mycroft #include <sys/proc.h> 74 1.5 mycroft #include <sys/socket.h> 75 1.5 mycroft #include <sys/socketvar.h> 76 1.5 mycroft #include <sys/domain.h> 77 1.5 mycroft #include <sys/protosw.h> 78 1.17 christos #include <sys/sysctl.h> 79 1.84 elad #include <sys/kauth.h> 80 1.145 rmind #include <sys/kmem.h> 81 1.99 ad #include <sys/intr.h> 82 1.237 ozaki #include <sys/condvar.h> 83 1.245 pgoyette #include <sys/compat_stub.h> 84 1.17 christos 85 1.5 mycroft #include <net/if.h> 86 1.178 ozaki #include <net/if_llatbl.h> 87 1.178 ozaki #include <net/if_types.h> 88 1.5 mycroft #include <net/route.h> 89 1.5 mycroft #include <net/raw_cb.h> 90 1.1 cgd 91 1.178 ozaki #include <netinet/in_var.h> 92 1.178 ozaki #include <netinet/if_inarp.h> 93 1.178 ozaki 94 1.129 kefren #include <netmpls/mpls.h> 95 1.129 kefren 96 1.120 christos #include <compat/net/if.h> 97 1.133 matt #include <compat/net/route.h> 98 1.237 ozaki 99 1.245 pgoyette #ifdef COMPAT_RTSOCK 100 1.245 pgoyette #undef COMPAT_RTSOCK 101 1.200 ozaki #endif 102 1.1 cgd 103 1.245 pgoyette static int if_addrflags(struct ifaddr *); 104 1.212 roy 105 1.245 pgoyette #include <net/rtsock_shared.c> 106 1.1 cgd 107 1.240 ozaki /* 108 1.240 ozaki * XXX avoid using void * once msghdr compat disappears. 109 1.240 ozaki */ 110 1.240 ozaki void 111 1.240 ozaki rt_setmetrics(void *in, struct rtentry *out) 112 1.240 ozaki { 113 1.240 ozaki const struct rt_xmsghdr *rtm = in; 114 1.240 ozaki 115 1.240 ozaki _rt_setmetrics(rtm->rtm_inits, rtm, out); 116 1.240 ozaki } 117 1.10 mycroft 118 1.178 ozaki int 119 1.178 ozaki rt_msg3(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, 120 1.178 ozaki int *lenp) 121 1.178 ozaki { 122 1.178 ozaki return rt_msg2(type, rtinfo, cpv, w, lenp); 123 1.178 ozaki } 124 1.1 cgd 125 1.196 roy static int 126 1.196 roy if_addrflags(struct ifaddr *ifa) 127 1.196 roy { 128 1.196 roy 129 1.196 roy switch (ifa->ifa_addr->sa_family) { 130 1.196 roy #ifdef INET 131 1.196 roy case AF_INET: 132 1.254 roy return ifatoia(ifa)->ia4_flags; 133 1.196 roy #endif 134 1.196 roy #ifdef INET6 135 1.196 roy case AF_INET6: 136 1.254 roy return ifatoia6(ifa)->ia6_flags; 137 1.196 roy #endif 138 1.196 roy default: 139 1.196 roy return 0; 140 1.196 roy } 141 1.196 roy } 142 1.78 dyoung 143 1.10 mycroft 144 1.215 ozaki /* 145 1.215 ozaki * Send a routing message as mimicing that a cloned route is added. 146 1.215 ozaki */ 147 1.215 ozaki void 148 1.255 roy rt_clonedmsg(int type, const struct sockaddr *src, const struct sockaddr *dst, 149 1.255 roy const uint8_t *lladdr, const struct ifnet *ifp) 150 1.215 ozaki { 151 1.215 ozaki struct rt_addrinfo info; 152 1.215 ozaki /* Mimic flags exactly */ 153 1.215 ozaki #define RTF_LLINFO 0x400 154 1.215 ozaki #define RTF_CLONED 0x2000 155 1.252 roy int flags = RTF_DONE; 156 1.215 ozaki union { 157 1.215 ozaki struct sockaddr sa; 158 1.215 ozaki struct sockaddr_storage ss; 159 1.215 ozaki struct sockaddr_dl sdl; 160 1.215 ozaki } u; 161 1.215 ozaki 162 1.252 roy if (type != RTM_MISS) 163 1.252 roy flags |= RTF_HOST | RTF_CLONED | RTF_LLINFO; 164 1.252 roy if (type == RTM_ADD || type == RTM_CHANGE) 165 1.251 roy flags |= RTF_UP; 166 1.215 ozaki memset(&info, 0, sizeof(info)); 167 1.255 roy info.rti_info[RTAX_AUTHOR] = src; 168 1.215 ozaki info.rti_info[RTAX_DST] = dst; 169 1.215 ozaki sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, ifp->if_type, 170 1.252 roy NULL, 0, lladdr, ifp->if_addrlen); 171 1.215 ozaki info.rti_info[RTAX_GATEWAY] = &u.sa; 172 1.215 ozaki 173 1.251 roy rt_missmsg(type, &info, flags, 0); 174 1.215 ozaki #undef RTF_LLINFO 175 1.215 ozaki #undef RTF_CLONED 176 1.215 ozaki } 177 1.245 pgoyette 178 1.245 pgoyette 179 1.245 pgoyette /* 180 1.245 pgoyette * The remaining code implements the routing-table sysctl node. It is 181 1.245 pgoyette * compiled only for the non-COMPAT case. 182 1.245 pgoyette */ 183 1.215 ozaki 184 1.10 mycroft /* 185 1.10 mycroft * This is used in dumping the kernel table via sysctl(). 186 1.1 cgd */ 187 1.40 simonb static int 188 1.94 dyoung sysctl_dumpentry(struct rtentry *rt, void *v) 189 1.1 cgd { 190 1.120 christos struct rt_walkarg *w = v; 191 1.10 mycroft int error = 0, size; 192 1.10 mycroft struct rt_addrinfo info; 193 1.1 cgd 194 1.10 mycroft if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 195 1.10 mycroft return 0; 196 1.48 thorpej memset(&info, 0, sizeof(info)); 197 1.114 dyoung info.rti_info[RTAX_DST] = rt_getkey(rt); 198 1.114 dyoung info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 199 1.114 dyoung info.rti_info[RTAX_NETMASK] = rt_mask(rt); 200 1.142 kefren info.rti_info[RTAX_TAG] = rt_gettag(rt); 201 1.16 cgd if (rt->rt_ifp) { 202 1.91 dyoung const struct ifaddr *rtifa; 203 1.114 dyoung info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr; 204 1.91 dyoung /* rtifa used to be simply rt->rt_ifa. If rt->rt_ifa != NULL, 205 1.91 dyoung * then rt_get_ifa() != NULL. So this ought to still be safe. 206 1.91 dyoung * --dyoung 207 1.91 dyoung */ 208 1.91 dyoung rtifa = rt_get_ifa(rt); 209 1.114 dyoung info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 210 1.16 cgd if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 211 1.114 dyoung info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; 212 1.16 cgd } 213 1.29 chopps if ((error = rt_msg2(RTM_GET, &info, 0, w, &size))) 214 1.95 dyoung return error; 215 1.29 chopps if (w->w_where && w->w_tmem && w->w_needed <= 0) { 216 1.133 matt struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)w->w_tmem; 217 1.10 mycroft 218 1.10 mycroft rtm->rtm_flags = rt->rt_flags; 219 1.10 mycroft rtm->rtm_use = rt->rt_use; 220 1.133 matt rtm_setmetrics(rt, rtm); 221 1.83 christos KASSERT(rt->rt_ifp != NULL); 222 1.10 mycroft rtm->rtm_index = rt->rt_ifp->if_index; 223 1.10 mycroft rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 224 1.10 mycroft rtm->rtm_addrs = info.rti_addrs; 225 1.21 christos if ((error = copyout(rtm, w->w_where, size)) != 0) 226 1.10 mycroft w->w_where = NULL; 227 1.10 mycroft else 228 1.93 christos w->w_where = (char *)w->w_where + size; 229 1.10 mycroft } 230 1.95 dyoung return error; 231 1.10 mycroft } 232 1.1 cgd 233 1.40 simonb static int 234 1.195 roy sysctl_iflist_if(struct ifnet *ifp, struct rt_walkarg *w, 235 1.195 roy struct rt_addrinfo *info, size_t len) 236 1.195 roy { 237 1.195 roy struct if_xmsghdr *ifm; 238 1.195 roy int error; 239 1.195 roy 240 1.195 roy ifm = (struct if_xmsghdr *)w->w_tmem; 241 1.195 roy ifm->ifm_index = ifp->if_index; 242 1.195 roy ifm->ifm_flags = ifp->if_flags; 243 1.253 thorpej if_export_if_data(ifp, &ifm->ifm_data, false); 244 1.195 roy ifm->ifm_addrs = info->rti_addrs; 245 1.195 roy if ((error = copyout(ifm, w->w_where, len)) == 0) 246 1.195 roy w->w_where = (char *)w->w_where + len; 247 1.195 roy return error; 248 1.195 roy } 249 1.195 roy 250 1.195 roy static int 251 1.195 roy sysctl_iflist_addr(struct rt_walkarg *w, struct ifaddr *ifa, 252 1.195 roy struct rt_addrinfo *info) 253 1.195 roy { 254 1.195 roy int len, error; 255 1.195 roy 256 1.196 roy if ((error = rt_msg2(RTM_XNEWADDR, info, 0, w, &len))) 257 1.195 roy return error; 258 1.195 roy if (w->w_where && w->w_tmem && w->w_needed <= 0) { 259 1.195 roy struct ifa_xmsghdr *ifam; 260 1.195 roy 261 1.195 roy ifam = (struct ifa_xmsghdr *)w->w_tmem; 262 1.195 roy ifam->ifam_index = ifa->ifa_ifp->if_index; 263 1.195 roy ifam->ifam_flags = ifa->ifa_flags; 264 1.195 roy ifam->ifam_metric = ifa->ifa_metric; 265 1.195 roy ifam->ifam_addrs = info->rti_addrs; 266 1.196 roy ifam->ifam_pid = 0; 267 1.196 roy ifam->ifam_addrflags = if_addrflags(ifa); 268 1.195 roy if ((error = copyout(w->w_tmem, w->w_where, len)) == 0) 269 1.195 roy w->w_where = (char *)w->w_where + len; 270 1.195 roy } 271 1.195 roy return error; 272 1.195 roy } 273 1.195 roy 274 1.195 roy static int 275 1.120 christos sysctl_iflist(int af, struct rt_walkarg *w, int type) 276 1.10 mycroft { 277 1.39 augustss struct ifnet *ifp; 278 1.39 augustss struct ifaddr *ifa; 279 1.10 mycroft struct rt_addrinfo info; 280 1.195 roy int cmd, len, error = 0; 281 1.186 ozaki int s; 282 1.186 ozaki struct psref psref; 283 1.206 ozaki int bound; 284 1.10 mycroft 285 1.195 roy switch (type) { 286 1.195 roy case NET_RT_IFLIST: 287 1.195 roy cmd = RTM_IFINFO; 288 1.195 roy break; 289 1.196 roy case NET_RT_OOOIFLIST: 290 1.195 roy cmd = RTM_OOIFINFO; 291 1.195 roy break; 292 1.196 roy case NET_RT_OOIFLIST: 293 1.195 roy cmd = RTM_OIFINFO; 294 1.196 roy break; 295 1.196 roy case NET_RT_OIFLIST: 296 1.196 roy cmd = RTM_IFINFO; 297 1.195 roy break; 298 1.195 roy default: 299 1.203 ozaki #ifdef RTSOCK_DEBUG 300 1.203 ozaki printf("%s: unsupported IFLIST type %d\n", __func__, type); 301 1.195 roy #endif 302 1.195 roy return EINVAL; 303 1.195 roy } 304 1.195 roy 305 1.48 thorpej memset(&info, 0, sizeof(info)); 306 1.186 ozaki 307 1.206 ozaki bound = curlwp_bind(); 308 1.186 ozaki s = pserialize_read_enter(); 309 1.186 ozaki IFNET_READER_FOREACH(ifp) { 310 1.205 ozaki int _s; 311 1.10 mycroft if (w->w_arg && w->w_arg != ifp->if_index) 312 1.10 mycroft continue; 313 1.191 ozaki if (IFADDR_READER_EMPTY(ifp)) 314 1.81 rpaulo continue; 315 1.186 ozaki 316 1.207 ozaki if_acquire(ifp, &psref); 317 1.186 ozaki pserialize_read_exit(s); 318 1.186 ozaki 319 1.114 dyoung info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 320 1.195 roy if ((error = rt_msg2(cmd, &info, NULL, w, &len)) != 0) 321 1.186 ozaki goto release_exit; 322 1.114 dyoung info.rti_info[RTAX_IFP] = NULL; 323 1.29 chopps if (w->w_where && w->w_tmem && w->w_needed <= 0) { 324 1.245 pgoyette switch (type) { 325 1.245 pgoyette case NET_RT_OIFLIST: /* old _70 */ 326 1.246 pgoyette if (!rtsock_iflist_70_hook.hooked) { 327 1.245 pgoyette error = EINVAL; 328 1.245 pgoyette break; 329 1.245 pgoyette } 330 1.245 pgoyette /* FALLTHROUGH */ 331 1.245 pgoyette case NET_RT_IFLIST: /* current */ 332 1.245 pgoyette error = sysctl_iflist_if(ifp, w, &info, len); 333 1.245 pgoyette break; 334 1.245 pgoyette case NET_RT_OOIFLIST: /* old _50 */ 335 1.248 pgoyette MODULE_HOOK_CALL(rtsock_iflist_50_hook, 336 1.245 pgoyette (ifp, w, &info, len), enosys(), error); 337 1.245 pgoyette break; 338 1.245 pgoyette case NET_RT_OOOIFLIST: /* old _14 */ 339 1.248 pgoyette MODULE_HOOK_CALL(rtsock_iflist_14_hook, 340 1.245 pgoyette (ifp, w, &info, len), enosys(), error); 341 1.245 pgoyette break; 342 1.245 pgoyette default: 343 1.245 pgoyette error = EINVAL; 344 1.245 pgoyette } 345 1.245 pgoyette if (error != 0) { 346 1.245 pgoyette if (error == ENOSYS) 347 1.245 pgoyette error = EINVAL; 348 1.195 roy goto release_exit; 349 1.245 pgoyette } 350 1.10 mycroft } 351 1.205 ozaki _s = pserialize_read_enter(); 352 1.191 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 353 1.205 ozaki struct psref _psref; 354 1.10 mycroft if (af && af != ifa->ifa_addr->sa_family) 355 1.10 mycroft continue; 356 1.205 ozaki ifa_acquire(ifa, &_psref); 357 1.205 ozaki pserialize_read_exit(_s); 358 1.205 ozaki 359 1.114 dyoung info.rti_info[RTAX_IFA] = ifa->ifa_addr; 360 1.114 dyoung info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 361 1.114 dyoung info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 362 1.245 pgoyette switch (type) { 363 1.245 pgoyette case NET_RT_IFLIST: 364 1.245 pgoyette error = sysctl_iflist_addr(w, ifa, &info); 365 1.245 pgoyette break; 366 1.245 pgoyette case NET_RT_OIFLIST: 367 1.245 pgoyette case NET_RT_OOIFLIST: 368 1.245 pgoyette case NET_RT_OOOIFLIST: 369 1.248 pgoyette MODULE_HOOK_CALL(rtsock_iflist_70_hook, 370 1.245 pgoyette (w, ifa, &info), enosys(), error); 371 1.245 pgoyette break; 372 1.245 pgoyette default: 373 1.245 pgoyette error = EINVAL; 374 1.245 pgoyette } 375 1.205 ozaki 376 1.205 ozaki _s = pserialize_read_enter(); 377 1.205 ozaki ifa_release(ifa, &_psref); 378 1.208 ozaki if (error != 0) { 379 1.208 ozaki pserialize_read_exit(_s); 380 1.186 ozaki goto release_exit; 381 1.208 ozaki } 382 1.10 mycroft } 383 1.205 ozaki pserialize_read_exit(_s); 384 1.115 christos info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 385 1.115 christos info.rti_info[RTAX_BRD] = NULL; 386 1.186 ozaki 387 1.186 ozaki s = pserialize_read_enter(); 388 1.207 ozaki if_release(ifp, &psref); 389 1.10 mycroft } 390 1.186 ozaki pserialize_read_exit(s); 391 1.190 ozaki curlwp_bindx(bound); 392 1.186 ozaki 393 1.95 dyoung return 0; 394 1.186 ozaki 395 1.186 ozaki release_exit: 396 1.207 ozaki if_release(ifp, &psref); 397 1.190 ozaki curlwp_bindx(bound); 398 1.186 ozaki return error; 399 1.1 cgd } 400 1.1 cgd 401 1.40 simonb static int 402 1.65 atatat sysctl_rtable(SYSCTLFN_ARGS) 403 1.1 cgd { 404 1.65 atatat void *where = oldp; 405 1.65 atatat size_t *given = oldlenp; 406 1.256 skrll int i, error = EINVAL; 407 1.10 mycroft u_char af; 408 1.120 christos struct rt_walkarg w; 409 1.1 cgd 410 1.66 atatat if (namelen == 1 && name[0] == CTL_QUERY) 411 1.95 dyoung return sysctl_query(SYSCTLFN_CALL(rnode)); 412 1.66 atatat 413 1.164 matt if (newp) 414 1.95 dyoung return EPERM; 415 1.10 mycroft if (namelen != 3) 416 1.95 dyoung return EINVAL; 417 1.10 mycroft af = name[0]; 418 1.29 chopps w.w_tmemneeded = 0; 419 1.29 chopps w.w_tmemsize = 0; 420 1.29 chopps w.w_tmem = NULL; 421 1.29 chopps again: 422 1.29 chopps /* we may return here if a later [re]alloc of the t_mem buffer fails */ 423 1.29 chopps if (w.w_tmemneeded) { 424 1.244 maxv w.w_tmem = kmem_zalloc(w.w_tmemneeded, KM_SLEEP); 425 1.29 chopps w.w_tmemsize = w.w_tmemneeded; 426 1.29 chopps w.w_tmemneeded = 0; 427 1.29 chopps } 428 1.29 chopps w.w_op = name[1]; 429 1.29 chopps w.w_arg = name[2]; 430 1.10 mycroft w.w_given = *given; 431 1.1 cgd w.w_needed = 0 - w.w_given; 432 1.29 chopps w.w_where = where; 433 1.1 cgd 434 1.250 ozaki KERNEL_LOCK_UNLESS_NET_MPSAFE(); 435 1.256 skrll const int s = splsoftnet(); 436 1.10 mycroft switch (w.w_op) { 437 1.10 mycroft 438 1.10 mycroft case NET_RT_DUMP: 439 1.10 mycroft case NET_RT_FLAGS: 440 1.219 ozaki #if defined(INET) || defined(INET6) 441 1.178 ozaki /* 442 1.178 ozaki * take care of llinfo entries, the caller must 443 1.178 ozaki * specify an AF 444 1.178 ozaki */ 445 1.178 ozaki if (w.w_op == NET_RT_FLAGS && 446 1.178 ozaki (w.w_arg == 0 || w.w_arg & RTF_LLDATA)) { 447 1.178 ozaki if (af != 0) 448 1.219 ozaki error = lltable_sysctl_dump(af, &w); 449 1.178 ozaki else 450 1.178 ozaki error = EINVAL; 451 1.178 ozaki break; 452 1.178 ozaki } 453 1.219 ozaki #endif 454 1.178 ozaki 455 1.224 ozaki for (i = 1; i <= AF_MAX; i++) { 456 1.224 ozaki if (af == 0 || af == i) { 457 1.224 ozaki error = rt_walktree(i, sysctl_dumpentry, &w); 458 1.224 ozaki if (error != 0) 459 1.224 ozaki break; 460 1.224 ozaki #if defined(INET) || defined(INET6) 461 1.224 ozaki /* 462 1.224 ozaki * Return ARP/NDP entries too for 463 1.224 ozaki * backward compatibility. 464 1.224 ozaki */ 465 1.224 ozaki error = lltable_sysctl_dump(i, &w); 466 1.224 ozaki if (error != 0) 467 1.224 ozaki break; 468 1.224 ozaki #endif 469 1.224 ozaki } 470 1.224 ozaki } 471 1.10 mycroft break; 472 1.10 mycroft 473 1.245 pgoyette case NET_RT_OOOIFLIST: /* compat_14 */ 474 1.245 pgoyette case NET_RT_OOIFLIST: /* compat_50 */ 475 1.245 pgoyette case NET_RT_OIFLIST: /* compat_70 */ 476 1.245 pgoyette case NET_RT_IFLIST: /* current */ 477 1.32 bouyer error = sysctl_iflist(af, &w, w.w_op); 478 1.133 matt break; 479 1.1 cgd } 480 1.10 mycroft splx(s); 481 1.250 ozaki KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); 482 1.29 chopps 483 1.29 chopps /* check to see if we couldn't allocate memory with NOWAIT */ 484 1.29 chopps if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded) 485 1.29 chopps goto again; 486 1.29 chopps 487 1.10 mycroft if (w.w_tmem) 488 1.202 ozaki kmem_free(w.w_tmem, w.w_tmemsize); 489 1.1 cgd w.w_needed += w.w_given; 490 1.10 mycroft if (where) { 491 1.93 christos *given = (char *)w.w_where - (char *)where; 492 1.10 mycroft if (*given < w.w_needed) 493 1.95 dyoung return ENOMEM; 494 1.10 mycroft } else { 495 1.10 mycroft *given = (11 * w.w_needed) / 10; 496 1.10 mycroft } 497 1.95 dyoung return error; 498 1.1 cgd } 499 1.1 cgd 500 1.249 pgoyette void 501 1.249 pgoyette sysctl_net_route_setup(struct sysctllog **clog, int pf, const char *name) 502 1.65 atatat { 503 1.85 elad const struct sysctlnode *rnode = NULL; 504 1.85 elad 505 1.85 elad sysctl_createv(clog, 0, NULL, &rnode, 506 1.67 atatat CTLFLAG_PERMANENT, 507 1.249 pgoyette CTLTYPE_NODE, name, 508 1.71 atatat SYSCTL_DESCR("PF_ROUTE information"), 509 1.65 atatat NULL, 0, NULL, 0, 510 1.249 pgoyette CTL_NET, pf, CTL_EOL); 511 1.133 matt 512 1.67 atatat sysctl_createv(clog, 0, NULL, NULL, 513 1.67 atatat CTLFLAG_PERMANENT, 514 1.71 atatat CTLTYPE_NODE, "rtable", 515 1.71 atatat SYSCTL_DESCR("Routing table information"), 516 1.65 atatat sysctl_rtable, 0, NULL, 0, 517 1.249 pgoyette CTL_NET, pf, 0 /* any protocol */, CTL_EOL); 518 1.133 matt 519 1.85 elad sysctl_createv(clog, 0, &rnode, NULL, 520 1.85 elad CTLFLAG_PERMANENT, 521 1.85 elad CTLTYPE_STRUCT, "stats", 522 1.85 elad SYSCTL_DESCR("Routing statistics"), 523 1.85 elad NULL, 0, &rtstat, sizeof(rtstat), 524 1.85 elad CTL_CREATE, CTL_EOL); 525 1.65 atatat } 526