1 /* 2 * Copyright (c) 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 34 * $Id: rtsock.c,v 1.15 1995/10/13 16:01:59 wollman Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/proc.h> 41 #include <sys/mbuf.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/domain.h> 45 #include <sys/protosw.h> 46 47 #include <net/if.h> 48 #include <net/route.h> 49 #include <net/raw_cb.h> 50 51 struct sockaddr route_dst = { 2, PF_ROUTE, }; 52 struct sockaddr route_src = { 2, PF_ROUTE, }; 53 struct sockproto route_proto = { PF_ROUTE, }; 54 55 struct walkarg { 56 int w_op, w_arg, w_given, w_needed, w_tmemsize; 57 caddr_t w_where, w_tmem; 58 }; 59 60 static struct mbuf * 61 rt_msg1 __P((int, struct rt_addrinfo *)); 62 static int rt_msg2 __P((int, 63 struct rt_addrinfo *, caddr_t, struct walkarg *)); 64 static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 65 extern int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); 66 extern int sysctl_iflist __P((int af, struct walkarg *w)); 67 extern int sysctl_rtable __P((int *name, u_int namelen, void* where, 68 size_t *given, void *new, size_t newlen)); 69 70 /* Sleazy use of local variables throughout file, warning!!!! */ 71 #define dst info.rti_info[RTAX_DST] 72 #define gate info.rti_info[RTAX_GATEWAY] 73 #define netmask info.rti_info[RTAX_NETMASK] 74 #define genmask info.rti_info[RTAX_GENMASK] 75 #define ifpaddr info.rti_info[RTAX_IFP] 76 #define ifaaddr info.rti_info[RTAX_IFA] 77 #define brdaddr info.rti_info[RTAX_BRD] 78 79 /*ARGSUSED*/ 80 int 81 route_usrreq(so, req, m, nam, control) 82 register struct socket *so; 83 int req; 84 struct mbuf *m, *nam, *control; 85 { 86 register int error = 0; 87 register struct rawcb *rp = sotorawcb(so); 88 int s; 89 90 if (req == PRU_ATTACH) { 91 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 92 so->so_pcb = (caddr_t)rp; 93 if (so->so_pcb) 94 bzero(so->so_pcb, sizeof(*rp)); 95 } 96 if (req == PRU_DETACH && rp) { 97 int af = rp->rcb_proto.sp_protocol; 98 if (af == AF_INET) 99 route_cb.ip_count--; 100 else if (af == AF_IPX) 101 route_cb.ipx_count--; 102 else if (af == AF_NS) 103 route_cb.ns_count--; 104 else if (af == AF_ISO) 105 route_cb.iso_count--; 106 route_cb.any_count--; 107 } 108 s = splnet(); 109 error = raw_usrreq(so, req, m, nam, control); 110 rp = sotorawcb(so); 111 if (req == PRU_ATTACH && rp) { 112 int af = rp->rcb_proto.sp_protocol; 113 if (error) { 114 free((caddr_t)rp, M_PCB); 115 splx(s); 116 return (error); 117 } 118 if (af == AF_INET) 119 route_cb.ip_count++; 120 else if (af == AF_IPX) 121 route_cb.ipx_count++; 122 else if (af == AF_NS) 123 route_cb.ns_count++; 124 else if (af == AF_ISO) 125 route_cb.iso_count++; 126 rp->rcb_faddr = &route_src; 127 route_cb.any_count++; 128 soisconnected(so); 129 so->so_options |= SO_USELOOPBACK; 130 } 131 splx(s); 132 return (error); 133 } 134 135 /*ARGSUSED*/ 136 int 137 route_output(m, so) 138 register struct mbuf *m; 139 struct socket *so; 140 { 141 register struct rt_msghdr *rtm = 0; 142 register struct rtentry *rt = 0; 143 struct rtentry *saved_nrt = 0; 144 struct radix_node_head *rnh; 145 struct rt_addrinfo info; 146 int len, error = 0; 147 struct ifnet *ifp = 0; 148 struct ifaddr *ifa = 0; 149 150 #define senderr(e) { error = e; goto flush;} 151 if (m == 0 || ((m->m_len < sizeof(long)) && 152 (m = m_pullup(m, sizeof(long))) == 0)) 153 return (ENOBUFS); 154 if ((m->m_flags & M_PKTHDR) == 0) 155 panic("route_output"); 156 len = m->m_pkthdr.len; 157 if (len < sizeof(*rtm) || 158 len != mtod(m, struct rt_msghdr *)->rtm_msglen) { 159 dst = 0; 160 senderr(EINVAL); 161 } 162 R_Malloc(rtm, struct rt_msghdr *, len); 163 if (rtm == 0) { 164 dst = 0; 165 senderr(ENOBUFS); 166 } 167 m_copydata(m, 0, len, (caddr_t)rtm); 168 if (rtm->rtm_version != RTM_VERSION) { 169 dst = 0; 170 senderr(EPROTONOSUPPORT); 171 } 172 rtm->rtm_pid = curproc->p_pid; 173 info.rti_addrs = rtm->rtm_addrs; 174 rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); 175 if (dst == 0 || (dst->sa_family >= AF_MAX) 176 || (gate != 0 && (gate->sa_family >= AF_MAX))) 177 senderr(EINVAL); 178 if (genmask) { 179 struct radix_node *t; 180 t = rn_addmask((caddr_t)genmask, 0, 1); 181 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) 182 genmask = (struct sockaddr *)(t->rn_key); 183 else 184 senderr(ENOBUFS); 185 } 186 switch (rtm->rtm_type) { 187 188 case RTM_ADD: 189 if (gate == 0) 190 senderr(EINVAL); 191 error = rtrequest(RTM_ADD, dst, gate, netmask, 192 rtm->rtm_flags, &saved_nrt); 193 if (error == 0 && saved_nrt) { 194 rt_setmetrics(rtm->rtm_inits, 195 &rtm->rtm_rmx, &saved_nrt->rt_rmx); 196 saved_nrt->rt_refcnt--; 197 saved_nrt->rt_genmask = genmask; 198 } 199 break; 200 201 case RTM_DELETE: 202 error = rtrequest(RTM_DELETE, dst, gate, netmask, 203 rtm->rtm_flags, &saved_nrt); 204 if (error == 0) { 205 if ((rt = saved_nrt)) 206 rt->rt_refcnt++; 207 goto report; 208 } 209 break; 210 211 case RTM_GET: 212 case RTM_CHANGE: 213 case RTM_LOCK: 214 if ((rnh = rt_tables[dst->sa_family]) == 0) { 215 senderr(EAFNOSUPPORT); 216 } else if (rt = (struct rtentry *) 217 rnh->rnh_lookup(dst, netmask, rnh)) 218 rt->rt_refcnt++; 219 else 220 senderr(ESRCH); 221 switch(rtm->rtm_type) { 222 223 case RTM_GET: 224 report: 225 dst = rt_key(rt); 226 gate = rt->rt_gateway; 227 netmask = rt_mask(rt); 228 genmask = rt->rt_genmask; 229 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 230 ifp = rt->rt_ifp; 231 if (ifp) { 232 ifpaddr = ifp->if_addrlist->ifa_addr; 233 ifaaddr = rt->rt_ifa->ifa_addr; 234 rtm->rtm_index = ifp->if_index; 235 } else { 236 ifpaddr = 0; 237 ifaaddr = 0; 238 } 239 } 240 len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, 241 (struct walkarg *)0); 242 if (len > rtm->rtm_msglen) { 243 struct rt_msghdr *new_rtm; 244 R_Malloc(new_rtm, struct rt_msghdr *, len); 245 if (new_rtm == 0) 246 senderr(ENOBUFS); 247 Bcopy(rtm, new_rtm, rtm->rtm_msglen); 248 Free(rtm); rtm = new_rtm; 249 } 250 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, 251 (struct walkarg *)0); 252 rtm->rtm_flags = rt->rt_flags; 253 rtm->rtm_rmx = rt->rt_rmx; 254 rtm->rtm_addrs = info.rti_addrs; 255 break; 256 257 case RTM_CHANGE: 258 if (gate && rt_setgate(rt, rt_key(rt), gate)) 259 senderr(EDQUOT); 260 261 /* 262 * If they tried to change things but didn't specify 263 * the required gateway, then just use the old one. 264 * This can happen if the user tries to change the 265 * flags on the default route without changing the 266 * default gateway. Changing flags still doesn't work. 267 */ 268 if ((rt->rt_flags & RTF_GATEWAY) && !gate) 269 gate = rt->rt_gateway; 270 271 /* new gateway could require new ifaddr, ifp; 272 flags may also be different; ifp may be specified 273 by ll sockaddr when protocol address is ambiguous */ 274 if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && 275 (ifp = ifa->ifa_ifp)) 276 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, 277 ifp); 278 else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || 279 (ifa = ifa_ifwithroute(rt->rt_flags, 280 rt_key(rt), gate))) 281 ifp = ifa->ifa_ifp; 282 if (ifa) { 283 register struct ifaddr *oifa = rt->rt_ifa; 284 if (oifa != ifa) { 285 if (oifa && oifa->ifa_rtrequest) 286 oifa->ifa_rtrequest(RTM_DELETE, 287 rt, gate); 288 IFAFREE(rt->rt_ifa); 289 rt->rt_ifa = ifa; 290 ifa->ifa_refcnt++; 291 rt->rt_ifp = ifp; 292 } 293 } 294 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 295 &rt->rt_rmx); 296 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 297 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); 298 if (genmask) 299 rt->rt_genmask = genmask; 300 /* 301 * Fall into 302 */ 303 case RTM_LOCK: 304 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 305 rt->rt_rmx.rmx_locks |= 306 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 307 break; 308 } 309 break; 310 311 default: 312 senderr(EOPNOTSUPP); 313 } 314 315 flush: 316 if (rtm) { 317 if (error) 318 rtm->rtm_errno = error; 319 else 320 rtm->rtm_flags |= RTF_DONE; 321 } 322 if (rt) 323 rtfree(rt); 324 { 325 register struct rawcb *rp = 0; 326 /* 327 * Check to see if we don't want our own messages. 328 */ 329 if ((so->so_options & SO_USELOOPBACK) == 0) { 330 if (route_cb.any_count <= 1) { 331 if (rtm) 332 Free(rtm); 333 m_freem(m); 334 return (error); 335 } 336 /* There is another listener, so construct message */ 337 rp = sotorawcb(so); 338 } 339 if (rtm) { 340 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 341 Free(rtm); 342 } 343 if (rp) 344 rp->rcb_proto.sp_family = 0; /* Avoid us */ 345 if (dst) 346 route_proto.sp_protocol = dst->sa_family; 347 raw_input(m, &route_proto, &route_src, &route_dst); 348 if (rp) 349 rp->rcb_proto.sp_family = PF_ROUTE; 350 } 351 return (error); 352 } 353 354 void 355 rt_setmetrics(which, in, out) 356 u_long which; 357 register struct rt_metrics *in, *out; 358 { 359 #define metric(f, e) if (which & (f)) out->e = in->e; 360 metric(RTV_RPIPE, rmx_recvpipe); 361 metric(RTV_SPIPE, rmx_sendpipe); 362 metric(RTV_SSTHRESH, rmx_ssthresh); 363 metric(RTV_RTT, rmx_rtt); 364 metric(RTV_RTTVAR, rmx_rttvar); 365 metric(RTV_HOPCOUNT, rmx_hopcount); 366 metric(RTV_MTU, rmx_mtu); 367 metric(RTV_EXPIRE, rmx_expire); 368 #undef metric 369 } 370 371 #define ROUNDUP(a) \ 372 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 373 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 374 375 static void 376 rt_xaddrs(cp, cplim, rtinfo) 377 register caddr_t cp, cplim; 378 register struct rt_addrinfo *rtinfo; 379 { 380 register struct sockaddr *sa; 381 register int i; 382 383 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 384 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 385 if ((rtinfo->rti_addrs & (1 << i)) == 0) 386 continue; 387 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 388 ADVANCE(cp, sa); 389 } 390 } 391 392 static struct mbuf * 393 rt_msg1(type, rtinfo) 394 int type; 395 register struct rt_addrinfo *rtinfo; 396 { 397 register struct rt_msghdr *rtm; 398 register struct mbuf *m; 399 register int i; 400 register struct sockaddr *sa; 401 int len, dlen; 402 403 m = m_gethdr(M_DONTWAIT, MT_DATA); 404 if (m == 0) 405 return (m); 406 switch (type) { 407 408 case RTM_DELADDR: 409 case RTM_NEWADDR: 410 len = sizeof(struct ifa_msghdr); 411 break; 412 413 case RTM_IFINFO: 414 len = sizeof(struct if_msghdr); 415 break; 416 417 default: 418 len = sizeof(struct rt_msghdr); 419 } 420 if (len > MHLEN) 421 panic("rt_msg1"); 422 m->m_pkthdr.len = m->m_len = len; 423 m->m_pkthdr.rcvif = 0; 424 rtm = mtod(m, struct rt_msghdr *); 425 bzero((caddr_t)rtm, len); 426 for (i = 0; i < RTAX_MAX; i++) { 427 if ((sa = rtinfo->rti_info[i]) == NULL) 428 continue; 429 rtinfo->rti_addrs |= (1 << i); 430 dlen = ROUNDUP(sa->sa_len); 431 m_copyback(m, len, dlen, (caddr_t)sa); 432 len += dlen; 433 } 434 if (m->m_pkthdr.len != len) { 435 m_freem(m); 436 return (NULL); 437 } 438 rtm->rtm_msglen = len; 439 rtm->rtm_version = RTM_VERSION; 440 rtm->rtm_type = type; 441 return (m); 442 } 443 444 static int 445 rt_msg2(type, rtinfo, cp, w) 446 int type; 447 register struct rt_addrinfo *rtinfo; 448 caddr_t cp; 449 struct walkarg *w; 450 { 451 register int i; 452 int len, dlen, second_time = 0; 453 caddr_t cp0; 454 455 rtinfo->rti_addrs = 0; 456 again: 457 switch (type) { 458 459 case RTM_DELADDR: 460 case RTM_NEWADDR: 461 len = sizeof(struct ifa_msghdr); 462 break; 463 464 case RTM_IFINFO: 465 len = sizeof(struct if_msghdr); 466 break; 467 468 default: 469 len = sizeof(struct rt_msghdr); 470 } 471 cp0 = cp; 472 if (cp0) 473 cp += len; 474 for (i = 0; i < RTAX_MAX; i++) { 475 register struct sockaddr *sa; 476 477 if ((sa = rtinfo->rti_info[i]) == 0) 478 continue; 479 rtinfo->rti_addrs |= (1 << i); 480 dlen = ROUNDUP(sa->sa_len); 481 if (cp) { 482 bcopy((caddr_t)sa, cp, (unsigned)dlen); 483 cp += dlen; 484 } 485 len += dlen; 486 } 487 if (cp == 0 && w != NULL && !second_time) { 488 register struct walkarg *rw = w; 489 490 rw->w_needed += len; 491 if (rw->w_needed <= 0 && rw->w_where) { 492 if (rw->w_tmemsize < len) { 493 if (rw->w_tmem) 494 free(rw->w_tmem, M_RTABLE); 495 rw->w_tmem = (caddr_t) 496 malloc(len, M_RTABLE, M_NOWAIT); 497 if (rw->w_tmem) 498 rw->w_tmemsize = len; 499 } 500 if (rw->w_tmem) { 501 cp = rw->w_tmem; 502 second_time = 1; 503 goto again; 504 } else 505 rw->w_where = 0; 506 } 507 } 508 if (cp) { 509 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 510 511 rtm->rtm_version = RTM_VERSION; 512 rtm->rtm_type = type; 513 rtm->rtm_msglen = len; 514 } 515 return (len); 516 } 517 518 /* 519 * This routine is called to generate a message from the routing 520 * socket indicating that a redirect has occured, a routing lookup 521 * has failed, or that a protocol has detected timeouts to a particular 522 * destination. 523 */ 524 void 525 rt_missmsg(type, rtinfo, flags, error) 526 int type, flags, error; 527 register struct rt_addrinfo *rtinfo; 528 { 529 register struct rt_msghdr *rtm; 530 register struct mbuf *m; 531 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 532 533 if (route_cb.any_count == 0) 534 return; 535 m = rt_msg1(type, rtinfo); 536 if (m == 0) 537 return; 538 rtm = mtod(m, struct rt_msghdr *); 539 rtm->rtm_flags = RTF_DONE | flags; 540 rtm->rtm_errno = error; 541 rtm->rtm_addrs = rtinfo->rti_addrs; 542 route_proto.sp_protocol = sa ? sa->sa_family : 0; 543 raw_input(m, &route_proto, &route_src, &route_dst); 544 } 545 546 /* 547 * This routine is called to generate a message from the routing 548 * socket indicating that the status of a network interface has changed. 549 */ 550 void 551 rt_ifmsg(ifp) 552 register struct ifnet *ifp; 553 { 554 register struct if_msghdr *ifm; 555 struct mbuf *m; 556 struct rt_addrinfo info; 557 558 if (route_cb.any_count == 0) 559 return; 560 bzero((caddr_t)&info, sizeof(info)); 561 m = rt_msg1(RTM_IFINFO, &info); 562 if (m == 0) 563 return; 564 ifm = mtod(m, struct if_msghdr *); 565 ifm->ifm_index = ifp->if_index; 566 ifm->ifm_flags = (u_short)ifp->if_flags; 567 ifm->ifm_data = ifp->if_data; 568 ifm->ifm_addrs = 0; 569 route_proto.sp_protocol = 0; 570 raw_input(m, &route_proto, &route_src, &route_dst); 571 } 572 573 /* 574 * This is called to generate messages from the routing socket 575 * indicating a network interface has had addresses associated with it. 576 * if we ever reverse the logic and replace messages TO the routing 577 * socket indicate a request to configure interfaces, then it will 578 * be unnecessary as the routing socket will automatically generate 579 * copies of it. 580 */ 581 void 582 rt_newaddrmsg(cmd, ifa, error, rt) 583 int cmd, error; 584 register struct ifaddr *ifa; 585 register struct rtentry *rt; 586 { 587 struct rt_addrinfo info; 588 struct sockaddr *sa = 0; 589 int pass; 590 struct mbuf *m = 0; 591 struct ifnet *ifp = ifa->ifa_ifp; 592 593 if (route_cb.any_count == 0) 594 return; 595 for (pass = 1; pass < 3; pass++) { 596 bzero((caddr_t)&info, sizeof(info)); 597 if ((cmd == RTM_ADD && pass == 1) || 598 (cmd == RTM_DELETE && pass == 2)) { 599 register struct ifa_msghdr *ifam; 600 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 601 602 ifaaddr = sa = ifa->ifa_addr; 603 ifpaddr = ifp->if_addrlist->ifa_addr; 604 netmask = ifa->ifa_netmask; 605 brdaddr = ifa->ifa_dstaddr; 606 if ((m = rt_msg1(ncmd, &info)) == NULL) 607 continue; 608 ifam = mtod(m, struct ifa_msghdr *); 609 ifam->ifam_index = ifp->if_index; 610 ifam->ifam_metric = ifa->ifa_metric; 611 ifam->ifam_flags = ifa->ifa_flags; 612 ifam->ifam_addrs = info.rti_addrs; 613 } 614 if ((cmd == RTM_ADD && pass == 2) || 615 (cmd == RTM_DELETE && pass == 1)) { 616 register struct rt_msghdr *rtm; 617 618 if (rt == 0) 619 continue; 620 netmask = rt_mask(rt); 621 dst = sa = rt_key(rt); 622 gate = rt->rt_gateway; 623 if ((m = rt_msg1(cmd, &info)) == NULL) 624 continue; 625 rtm = mtod(m, struct rt_msghdr *); 626 rtm->rtm_index = ifp->if_index; 627 rtm->rtm_flags |= rt->rt_flags; 628 rtm->rtm_errno = error; 629 rtm->rtm_addrs = info.rti_addrs; 630 } 631 route_proto.sp_protocol = sa ? sa->sa_family : 0; 632 raw_input(m, &route_proto, &route_src, &route_dst); 633 } 634 } 635 636 /* 637 * This is used in dumping the kernel table via sysctl(). 638 */ 639 int 640 sysctl_dumpentry(rn, vw) 641 struct radix_node *rn; 642 void *vw; 643 { 644 register struct walkarg *w = vw; 645 register struct rtentry *rt = (struct rtentry *)rn; 646 int error = 0, size; 647 struct rt_addrinfo info; 648 649 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 650 return 0; 651 bzero((caddr_t)&info, sizeof(info)); 652 dst = rt_key(rt); 653 gate = rt->rt_gateway; 654 netmask = rt_mask(rt); 655 genmask = rt->rt_genmask; 656 size = rt_msg2(RTM_GET, &info, 0, w); 657 if (w->w_where && w->w_tmem) { 658 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 659 660 rtm->rtm_flags = rt->rt_flags; 661 rtm->rtm_use = rt->rt_use; 662 rtm->rtm_rmx = rt->rt_rmx; 663 rtm->rtm_index = rt->rt_ifp->if_index; 664 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 665 rtm->rtm_addrs = info.rti_addrs; 666 error = copyout((caddr_t)rtm, w->w_where, size); 667 if (error) 668 w->w_where = NULL; 669 else 670 w->w_where += size; 671 } 672 return (error); 673 } 674 675 int 676 sysctl_iflist(af, w) 677 int af; 678 register struct walkarg *w; 679 { 680 register struct ifnet *ifp; 681 register struct ifaddr *ifa; 682 struct rt_addrinfo info; 683 int len, error = 0; 684 685 bzero((caddr_t)&info, sizeof(info)); 686 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 687 if (w->w_arg && w->w_arg != ifp->if_index) 688 continue; 689 ifa = ifp->if_addrlist; 690 ifpaddr = ifa->ifa_addr; 691 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 692 ifpaddr = 0; 693 if (w->w_where && w->w_tmem) { 694 register struct if_msghdr *ifm; 695 696 ifm = (struct if_msghdr *)w->w_tmem; 697 ifm->ifm_index = ifp->if_index; 698 ifm->ifm_flags = (u_short)ifp->if_flags; 699 ifm->ifm_data = ifp->if_data; 700 ifm->ifm_addrs = info.rti_addrs; 701 error = copyout((caddr_t)ifm, w->w_where, len); 702 if (error) 703 return (error); 704 w->w_where += len; 705 } 706 while ((ifa = ifa->ifa_next) != 0) { 707 if (af && af != ifa->ifa_addr->sa_family) 708 continue; 709 ifaaddr = ifa->ifa_addr; 710 netmask = ifa->ifa_netmask; 711 brdaddr = ifa->ifa_dstaddr; 712 len = rt_msg2(RTM_NEWADDR, &info, 0, w); 713 if (w->w_where && w->w_tmem) { 714 register struct ifa_msghdr *ifam; 715 716 ifam = (struct ifa_msghdr *)w->w_tmem; 717 ifam->ifam_index = ifa->ifa_ifp->if_index; 718 ifam->ifam_flags = ifa->ifa_flags; 719 ifam->ifam_metric = ifa->ifa_metric; 720 ifam->ifam_addrs = info.rti_addrs; 721 error = copyout(w->w_tmem, w->w_where, len); 722 if (error) 723 return (error); 724 w->w_where += len; 725 } 726 } 727 ifaaddr = netmask = brdaddr = 0; 728 } 729 return (0); 730 } 731 732 int 733 sysctl_rtable(name, namelen, where, given, new, newlen) 734 int *name; 735 u_int namelen; 736 void *where; 737 size_t *given; 738 void *new; 739 size_t newlen; 740 { 741 register struct radix_node_head *rnh; 742 int i, s, error = EINVAL; 743 u_char af; 744 struct walkarg w; 745 746 if (new) 747 return (EPERM); 748 if (namelen != 3) 749 return (EINVAL); 750 af = name[0]; 751 Bzero(&w, sizeof(w)); 752 w.w_where = where; 753 w.w_given = *given; 754 w.w_needed = 0 - w.w_given; 755 w.w_op = name[1]; 756 w.w_arg = name[2]; 757 758 s = splnet(); 759 switch (w.w_op) { 760 761 case NET_RT_DUMP: 762 case NET_RT_FLAGS: 763 for (i = 1; i <= AF_MAX; i++) 764 if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 765 (error = rnh->rnh_walktree(rnh, 766 sysctl_dumpentry, &w))) 767 break; 768 break; 769 770 case NET_RT_IFLIST: 771 error = sysctl_iflist(af, &w); 772 } 773 splx(s); 774 if (w.w_tmem) 775 free(w.w_tmem, M_RTABLE); 776 w.w_needed += w.w_given; 777 if (where) { 778 *given = w.w_where - (caddr_t)where; 779 if (*given < w.w_needed) 780 return (ENOMEM); 781 } else { 782 *given = (11 * w.w_needed) / 10; 783 } 784 return (error); 785 } 786 787 /* 788 * Definitions of protocols supported in the ROUTE domain. 789 */ 790 791 extern struct domain routedomain; /* or at least forward */ 792 793 struct protosw routesw[] = { 794 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 795 raw_input, route_output, raw_ctlinput, 0, 796 route_usrreq, 797 raw_init, 0, 0, 0, 798 sysctl_rtable, 799 } 800 }; 801 802 struct domain routedomain = 803 { PF_ROUTE, "route", route_init, 0, 0, 804 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 805 806 DOMAIN_SET(route); 807