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