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.26 1997/02/22 09:41:15 peter Exp $ 35 */ 36 37 38 #include <sys/param.h> 39 #include <sys/queue.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/sysctl.h> 43 #include <sys/proc.h> 44 #include <sys/mbuf.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/domain.h> 48 #include <sys/protosw.h> 49 50 #include <net/if.h> 51 #include <net/route.h> 52 #include <net/raw_cb.h> 53 54 static struct sockaddr route_dst = { 2, PF_ROUTE, }; 55 static struct sockaddr route_src = { 2, PF_ROUTE, }; 56 static struct sockproto route_proto = { PF_ROUTE, }; 57 58 struct walkarg { 59 int w_tmemsize; 60 int w_op, w_arg; 61 caddr_t w_tmem; 62 struct sysctl_req *w_req; 63 }; 64 65 static struct mbuf * 66 rt_msg1 __P((int, struct rt_addrinfo *)); 67 static int rt_msg2 __P((int, 68 struct rt_addrinfo *, caddr_t, struct walkarg *)); 69 static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 70 static int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); 71 static int sysctl_iflist __P((int af, struct walkarg *w)); 72 static int route_output __P((struct mbuf *, struct socket *)); 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 /* 85 * It really doesn't make any sense at all for this code to share much 86 * with raw_usrreq.c, since its functionality is so restricted. XXX 87 */ 88 static int 89 rts_abort(struct socket *so) 90 { 91 int s, error; 92 s = splnet(); 93 error = raw_usrreqs.pru_abort(so); 94 splx(s); 95 return error; 96 } 97 98 /* pru_accept is EOPNOTSUPP */ 99 100 static int 101 rts_attach(struct socket *so, int proto, struct proc *p) 102 { 103 struct rawcb *rp; 104 int s, error; 105 106 if (sotorawcb(so) != 0) 107 return EISCONN; /* XXX panic? */ 108 MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */ 109 if (rp == 0) 110 return ENOBUFS; 111 bzero(rp, sizeof *rp); 112 113 /* 114 * The splnet() is necessary to block protocols from sending 115 * error notifications (like RTM_REDIRECT or RTM_LOSING) while 116 * this PCB is extant but incompletely initialized. 117 * Probably we should try to do more of this work beforehand and 118 * eliminate the spl. 119 */ 120 s = splnet(); 121 so->so_pcb = (caddr_t)rp; 122 error = raw_usrreqs.pru_attach(so, proto, p); 123 rp = sotorawcb(so); 124 if (error) { 125 splx(s); 126 free(rp, M_PCB); 127 return error; 128 } 129 switch(rp->rcb_proto.sp_protocol) { 130 case AF_INET: 131 route_cb.ip_count++; 132 break; 133 case AF_IPX: 134 route_cb.ipx_count++; 135 break; 136 case AF_NS: 137 route_cb.ns_count++; 138 break; 139 case AF_ISO: 140 route_cb.iso_count++; 141 break; 142 } 143 rp->rcb_faddr = &route_src; 144 route_cb.any_count++; 145 soisconnected(so); 146 so->so_options |= SO_USELOOPBACK; 147 splx(s); 148 return 0; 149 } 150 151 static int 152 rts_bind(struct socket *so, struct mbuf *nam, struct proc *p) 153 { 154 int s, error; 155 s = splnet(); 156 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */ 157 splx(s); 158 return error; 159 } 160 161 static int 162 rts_connect(struct socket *so, struct mbuf *nam, struct proc *p) 163 { 164 int s, error; 165 s = splnet(); 166 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */ 167 splx(s); 168 return error; 169 } 170 171 /* pru_connect2 is EOPNOTSUPP */ 172 /* pru_control is EOPNOTSUPP */ 173 174 static int 175 rts_detach(struct socket *so) 176 { 177 struct rawcb *rp = sotorawcb(so); 178 int s, error; 179 180 s = splnet(); 181 if (rp != 0) { 182 switch(rp->rcb_proto.sp_protocol) { 183 case AF_INET: 184 route_cb.ip_count--; 185 break; 186 case AF_IPX: 187 route_cb.ipx_count--; 188 break; 189 case AF_NS: 190 route_cb.ns_count--; 191 break; 192 case AF_ISO: 193 route_cb.iso_count--; 194 break; 195 } 196 route_cb.any_count--; 197 } 198 error = raw_usrreqs.pru_detach(so); 199 splx(s); 200 return error; 201 } 202 203 static int 204 rts_disconnect(struct socket *so) 205 { 206 int s, error; 207 s = splnet(); 208 error = raw_usrreqs.pru_disconnect(so); 209 splx(s); 210 return error; 211 } 212 213 /* pru_listen is EOPNOTSUPP */ 214 215 static int 216 rts_peeraddr(struct socket *so, struct mbuf *nam) 217 { 218 int s, error; 219 s = splnet(); 220 error = raw_usrreqs.pru_peeraddr(so, nam); 221 splx(s); 222 return error; 223 } 224 225 /* pru_rcvd is EOPNOTSUPP */ 226 /* pru_rcvoob is EOPNOTSUPP */ 227 228 static int 229 rts_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, 230 struct mbuf *control, struct proc *p) 231 { 232 int s, error; 233 s = splnet(); 234 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p); 235 splx(s); 236 return error; 237 } 238 239 /* pru_sense is null */ 240 241 static int 242 rts_shutdown(struct socket *so) 243 { 244 int s, error; 245 s = splnet(); 246 error = raw_usrreqs.pru_shutdown(so); 247 splx(s); 248 return error; 249 } 250 251 static int 252 rts_sockaddr(struct socket *so, struct mbuf *nam) 253 { 254 int s, error; 255 s = splnet(); 256 error = raw_usrreqs.pru_sockaddr(so, nam); 257 splx(s); 258 return error; 259 } 260 261 static struct pr_usrreqs route_usrreqs = { 262 rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect, 263 pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect, 264 pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, 265 rts_send, pru_sense_null, rts_shutdown, rts_sockaddr, 266 sosend, soreceive, soselect 267 }; 268 269 /*ARGSUSED*/ 270 static int 271 route_output(m, so) 272 register struct mbuf *m; 273 struct socket *so; 274 { 275 register struct rt_msghdr *rtm = 0; 276 register struct rtentry *rt = 0; 277 struct rtentry *saved_nrt = 0; 278 struct radix_node_head *rnh; 279 struct rt_addrinfo info; 280 int len, error = 0; 281 struct ifnet *ifp = 0; 282 struct ifaddr *ifa = 0; 283 284 #define senderr(e) { error = e; goto flush;} 285 if (m == 0 || ((m->m_len < sizeof(long)) && 286 (m = m_pullup(m, sizeof(long))) == 0)) 287 return (ENOBUFS); 288 if ((m->m_flags & M_PKTHDR) == 0) 289 panic("route_output"); 290 len = m->m_pkthdr.len; 291 if (len < sizeof(*rtm) || 292 len != mtod(m, struct rt_msghdr *)->rtm_msglen) { 293 dst = 0; 294 senderr(EINVAL); 295 } 296 R_Malloc(rtm, struct rt_msghdr *, len); 297 if (rtm == 0) { 298 dst = 0; 299 senderr(ENOBUFS); 300 } 301 m_copydata(m, 0, len, (caddr_t)rtm); 302 if (rtm->rtm_version != RTM_VERSION) { 303 dst = 0; 304 senderr(EPROTONOSUPPORT); 305 } 306 rtm->rtm_pid = curproc->p_pid; 307 info.rti_addrs = rtm->rtm_addrs; 308 rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); 309 if (dst == 0 || (dst->sa_family >= AF_MAX) 310 || (gate != 0 && (gate->sa_family >= AF_MAX))) 311 senderr(EINVAL); 312 if (genmask) { 313 struct radix_node *t; 314 t = rn_addmask((caddr_t)genmask, 0, 1); 315 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) 316 genmask = (struct sockaddr *)(t->rn_key); 317 else 318 senderr(ENOBUFS); 319 } 320 switch (rtm->rtm_type) { 321 322 case RTM_ADD: 323 if (gate == 0) 324 senderr(EINVAL); 325 error = rtrequest(RTM_ADD, dst, gate, netmask, 326 rtm->rtm_flags, &saved_nrt); 327 if (error == 0 && saved_nrt) { 328 rt_setmetrics(rtm->rtm_inits, 329 &rtm->rtm_rmx, &saved_nrt->rt_rmx); 330 saved_nrt->rt_refcnt--; 331 saved_nrt->rt_genmask = genmask; 332 } 333 break; 334 335 case RTM_DELETE: 336 error = rtrequest(RTM_DELETE, dst, gate, netmask, 337 rtm->rtm_flags, &saved_nrt); 338 if (error == 0) { 339 if ((rt = saved_nrt)) 340 rt->rt_refcnt++; 341 goto report; 342 } 343 break; 344 345 case RTM_GET: 346 case RTM_CHANGE: 347 case RTM_LOCK: 348 if ((rnh = rt_tables[dst->sa_family]) == 0) { 349 senderr(EAFNOSUPPORT); 350 } else if (rt = (struct rtentry *) 351 rnh->rnh_lookup(dst, netmask, rnh)) 352 rt->rt_refcnt++; 353 else 354 senderr(ESRCH); 355 switch(rtm->rtm_type) { 356 357 case RTM_GET: 358 report: 359 dst = rt_key(rt); 360 gate = rt->rt_gateway; 361 netmask = rt_mask(rt); 362 genmask = rt->rt_genmask; 363 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 364 ifp = rt->rt_ifp; 365 if (ifp) { 366 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; 367 ifaaddr = rt->rt_ifa->ifa_addr; 368 rtm->rtm_index = ifp->if_index; 369 } else { 370 ifpaddr = 0; 371 ifaaddr = 0; 372 } 373 } 374 len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, 375 (struct walkarg *)0); 376 if (len > rtm->rtm_msglen) { 377 struct rt_msghdr *new_rtm; 378 R_Malloc(new_rtm, struct rt_msghdr *, len); 379 if (new_rtm == 0) 380 senderr(ENOBUFS); 381 Bcopy(rtm, new_rtm, rtm->rtm_msglen); 382 Free(rtm); rtm = new_rtm; 383 } 384 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, 385 (struct walkarg *)0); 386 rtm->rtm_flags = rt->rt_flags; 387 rtm->rtm_rmx = rt->rt_rmx; 388 rtm->rtm_addrs = info.rti_addrs; 389 break; 390 391 case RTM_CHANGE: 392 if (gate && (error = rt_setgate(rt, rt_key(rt), gate))) 393 senderr(error); 394 395 /* 396 * If they tried to change things but didn't specify 397 * the required gateway, then just use the old one. 398 * This can happen if the user tries to change the 399 * flags on the default route without changing the 400 * default gateway. Changing flags still doesn't work. 401 */ 402 if ((rt->rt_flags & RTF_GATEWAY) && !gate) 403 gate = rt->rt_gateway; 404 405 /* new gateway could require new ifaddr, ifp; 406 flags may also be different; ifp may be specified 407 by ll sockaddr when protocol address is ambiguous */ 408 if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && 409 (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) 410 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, 411 ifp); 412 else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || 413 (gate && (ifa = ifa_ifwithroute(rt->rt_flags, 414 rt_key(rt), gate)))) 415 ifp = ifa->ifa_ifp; 416 if (ifa) { 417 register struct ifaddr *oifa = rt->rt_ifa; 418 if (oifa != ifa) { 419 if (oifa && oifa->ifa_rtrequest) 420 oifa->ifa_rtrequest(RTM_DELETE, 421 rt, gate); 422 IFAFREE(rt->rt_ifa); 423 rt->rt_ifa = ifa; 424 ifa->ifa_refcnt++; 425 rt->rt_ifp = ifp; 426 } 427 } 428 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 429 &rt->rt_rmx); 430 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 431 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); 432 if (genmask) 433 rt->rt_genmask = genmask; 434 /* 435 * Fall into 436 */ 437 case RTM_LOCK: 438 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 439 rt->rt_rmx.rmx_locks |= 440 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 441 break; 442 } 443 break; 444 445 default: 446 senderr(EOPNOTSUPP); 447 } 448 449 flush: 450 if (rtm) { 451 if (error) 452 rtm->rtm_errno = error; 453 else 454 rtm->rtm_flags |= RTF_DONE; 455 } 456 if (rt) 457 rtfree(rt); 458 { 459 register struct rawcb *rp = 0; 460 /* 461 * Check to see if we don't want our own messages. 462 */ 463 if ((so->so_options & SO_USELOOPBACK) == 0) { 464 if (route_cb.any_count <= 1) { 465 if (rtm) 466 Free(rtm); 467 m_freem(m); 468 return (error); 469 } 470 /* There is another listener, so construct message */ 471 rp = sotorawcb(so); 472 } 473 if (rtm) { 474 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 475 Free(rtm); 476 } 477 if (rp) 478 rp->rcb_proto.sp_family = 0; /* Avoid us */ 479 if (dst) 480 route_proto.sp_protocol = dst->sa_family; 481 raw_input(m, &route_proto, &route_src, &route_dst); 482 if (rp) 483 rp->rcb_proto.sp_family = PF_ROUTE; 484 } 485 return (error); 486 } 487 488 static void 489 rt_setmetrics(which, in, out) 490 u_long which; 491 register struct rt_metrics *in, *out; 492 { 493 #define metric(f, e) if (which & (f)) out->e = in->e; 494 metric(RTV_RPIPE, rmx_recvpipe); 495 metric(RTV_SPIPE, rmx_sendpipe); 496 metric(RTV_SSTHRESH, rmx_ssthresh); 497 metric(RTV_RTT, rmx_rtt); 498 metric(RTV_RTTVAR, rmx_rttvar); 499 metric(RTV_HOPCOUNT, rmx_hopcount); 500 metric(RTV_MTU, rmx_mtu); 501 metric(RTV_EXPIRE, rmx_expire); 502 #undef metric 503 } 504 505 #define ROUNDUP(a) \ 506 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 507 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 508 509 static void 510 rt_xaddrs(cp, cplim, rtinfo) 511 register caddr_t cp, cplim; 512 register struct rt_addrinfo *rtinfo; 513 { 514 register struct sockaddr *sa; 515 register int i; 516 517 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 518 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 519 if ((rtinfo->rti_addrs & (1 << i)) == 0) 520 continue; 521 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 522 ADVANCE(cp, sa); 523 } 524 } 525 526 static struct mbuf * 527 rt_msg1(type, rtinfo) 528 int type; 529 register struct rt_addrinfo *rtinfo; 530 { 531 register struct rt_msghdr *rtm; 532 register struct mbuf *m; 533 register int i; 534 register struct sockaddr *sa; 535 int len, dlen; 536 537 m = m_gethdr(M_DONTWAIT, MT_DATA); 538 if (m == 0) 539 return (m); 540 switch (type) { 541 542 case RTM_DELADDR: 543 case RTM_NEWADDR: 544 len = sizeof(struct ifa_msghdr); 545 break; 546 547 case RTM_DELMADDR: 548 case RTM_NEWMADDR: 549 len = sizeof(struct ifma_msghdr); 550 break; 551 552 case RTM_IFINFO: 553 len = sizeof(struct if_msghdr); 554 break; 555 556 default: 557 len = sizeof(struct rt_msghdr); 558 } 559 if (len > MHLEN) 560 panic("rt_msg1"); 561 m->m_pkthdr.len = m->m_len = len; 562 m->m_pkthdr.rcvif = 0; 563 rtm = mtod(m, struct rt_msghdr *); 564 bzero((caddr_t)rtm, len); 565 for (i = 0; i < RTAX_MAX; i++) { 566 if ((sa = rtinfo->rti_info[i]) == NULL) 567 continue; 568 rtinfo->rti_addrs |= (1 << i); 569 dlen = ROUNDUP(sa->sa_len); 570 m_copyback(m, len, dlen, (caddr_t)sa); 571 len += dlen; 572 } 573 if (m->m_pkthdr.len != len) { 574 m_freem(m); 575 return (NULL); 576 } 577 rtm->rtm_msglen = len; 578 rtm->rtm_version = RTM_VERSION; 579 rtm->rtm_type = type; 580 return (m); 581 } 582 583 static int 584 rt_msg2(type, rtinfo, cp, w) 585 int type; 586 register struct rt_addrinfo *rtinfo; 587 caddr_t cp; 588 struct walkarg *w; 589 { 590 register int i; 591 int len, dlen, second_time = 0; 592 caddr_t cp0; 593 594 rtinfo->rti_addrs = 0; 595 again: 596 switch (type) { 597 598 case RTM_DELADDR: 599 case RTM_NEWADDR: 600 len = sizeof(struct ifa_msghdr); 601 break; 602 603 case RTM_IFINFO: 604 len = sizeof(struct if_msghdr); 605 break; 606 607 default: 608 len = sizeof(struct rt_msghdr); 609 } 610 cp0 = cp; 611 if (cp0) 612 cp += len; 613 for (i = 0; i < RTAX_MAX; i++) { 614 register struct sockaddr *sa; 615 616 if ((sa = rtinfo->rti_info[i]) == 0) 617 continue; 618 rtinfo->rti_addrs |= (1 << i); 619 dlen = ROUNDUP(sa->sa_len); 620 if (cp) { 621 bcopy((caddr_t)sa, cp, (unsigned)dlen); 622 cp += dlen; 623 } 624 len += dlen; 625 } 626 if (cp == 0 && w != NULL && !second_time) { 627 register struct walkarg *rw = w; 628 629 if (rw->w_req) { 630 if (rw->w_tmemsize < len) { 631 if (rw->w_tmem) 632 free(rw->w_tmem, M_RTABLE); 633 rw->w_tmem = (caddr_t) 634 malloc(len, M_RTABLE, M_NOWAIT); 635 if (rw->w_tmem) 636 rw->w_tmemsize = len; 637 } 638 if (rw->w_tmem) { 639 cp = rw->w_tmem; 640 second_time = 1; 641 goto again; 642 } 643 } 644 } 645 if (cp) { 646 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 647 648 rtm->rtm_version = RTM_VERSION; 649 rtm->rtm_type = type; 650 rtm->rtm_msglen = len; 651 } 652 return (len); 653 } 654 655 /* 656 * This routine is called to generate a message from the routing 657 * socket indicating that a redirect has occured, a routing lookup 658 * has failed, or that a protocol has detected timeouts to a particular 659 * destination. 660 */ 661 void 662 rt_missmsg(type, rtinfo, flags, error) 663 int type, flags, error; 664 register struct rt_addrinfo *rtinfo; 665 { 666 register struct rt_msghdr *rtm; 667 register struct mbuf *m; 668 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 669 670 if (route_cb.any_count == 0) 671 return; 672 m = rt_msg1(type, rtinfo); 673 if (m == 0) 674 return; 675 rtm = mtod(m, struct rt_msghdr *); 676 rtm->rtm_flags = RTF_DONE | flags; 677 rtm->rtm_errno = error; 678 rtm->rtm_addrs = rtinfo->rti_addrs; 679 route_proto.sp_protocol = sa ? sa->sa_family : 0; 680 raw_input(m, &route_proto, &route_src, &route_dst); 681 } 682 683 /* 684 * This routine is called to generate a message from the routing 685 * socket indicating that the status of a network interface has changed. 686 */ 687 void 688 rt_ifmsg(ifp) 689 register struct ifnet *ifp; 690 { 691 register struct if_msghdr *ifm; 692 struct mbuf *m; 693 struct rt_addrinfo info; 694 695 if (route_cb.any_count == 0) 696 return; 697 bzero((caddr_t)&info, sizeof(info)); 698 m = rt_msg1(RTM_IFINFO, &info); 699 if (m == 0) 700 return; 701 ifm = mtod(m, struct if_msghdr *); 702 ifm->ifm_index = ifp->if_index; 703 ifm->ifm_flags = (u_short)ifp->if_flags; 704 ifm->ifm_data = ifp->if_data; 705 ifm->ifm_addrs = 0; 706 route_proto.sp_protocol = 0; 707 raw_input(m, &route_proto, &route_src, &route_dst); 708 } 709 710 /* 711 * This is called to generate messages from the routing socket 712 * indicating a network interface has had addresses associated with it. 713 * if we ever reverse the logic and replace messages TO the routing 714 * socket indicate a request to configure interfaces, then it will 715 * be unnecessary as the routing socket will automatically generate 716 * copies of it. 717 */ 718 void 719 rt_newaddrmsg(cmd, ifa, error, rt) 720 int cmd, error; 721 register struct ifaddr *ifa; 722 register struct rtentry *rt; 723 { 724 struct rt_addrinfo info; 725 struct sockaddr *sa = 0; 726 int pass; 727 struct mbuf *m = 0; 728 struct ifnet *ifp = ifa->ifa_ifp; 729 730 if (route_cb.any_count == 0) 731 return; 732 for (pass = 1; pass < 3; pass++) { 733 bzero((caddr_t)&info, sizeof(info)); 734 if ((cmd == RTM_ADD && pass == 1) || 735 (cmd == RTM_DELETE && pass == 2)) { 736 register struct ifa_msghdr *ifam; 737 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 738 739 ifaaddr = sa = ifa->ifa_addr; 740 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; 741 netmask = ifa->ifa_netmask; 742 brdaddr = ifa->ifa_dstaddr; 743 if ((m = rt_msg1(ncmd, &info)) == NULL) 744 continue; 745 ifam = mtod(m, struct ifa_msghdr *); 746 ifam->ifam_index = ifp->if_index; 747 ifam->ifam_metric = ifa->ifa_metric; 748 ifam->ifam_flags = ifa->ifa_flags; 749 ifam->ifam_addrs = info.rti_addrs; 750 } 751 if ((cmd == RTM_ADD && pass == 2) || 752 (cmd == RTM_DELETE && pass == 1)) { 753 register struct rt_msghdr *rtm; 754 755 if (rt == 0) 756 continue; 757 netmask = rt_mask(rt); 758 dst = sa = rt_key(rt); 759 gate = rt->rt_gateway; 760 if ((m = rt_msg1(cmd, &info)) == NULL) 761 continue; 762 rtm = mtod(m, struct rt_msghdr *); 763 rtm->rtm_index = ifp->if_index; 764 rtm->rtm_flags |= rt->rt_flags; 765 rtm->rtm_errno = error; 766 rtm->rtm_addrs = info.rti_addrs; 767 } 768 route_proto.sp_protocol = sa ? sa->sa_family : 0; 769 raw_input(m, &route_proto, &route_src, &route_dst); 770 } 771 } 772 773 /* 774 * This is the analogue to the rt_newaddrmsg which performs the same 775 * function but for multicast group memberhips. This is easier since 776 * there is no route state to worry about. 777 */ 778 void 779 rt_newmaddrmsg(cmd, ifma) 780 int cmd; 781 struct ifmultiaddr *ifma; 782 { 783 struct rt_addrinfo info; 784 struct mbuf *m = 0; 785 struct ifnet *ifp = ifma->ifma_ifp; 786 struct ifma_msghdr *ifmam; 787 788 if (route_cb.any_count == 0) 789 return; 790 791 bzero((caddr_t)&info, sizeof(info)); 792 ifaaddr = ifma->ifma_addr; 793 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; 794 /* 795 * If a link-layer address is present, present it as a ``gateway'' 796 * (similarly to how ARP entries, e.g., are presented). 797 */ 798 gate = ifma->ifma_lladdr; 799 if ((m = rt_msg1(cmd, &info)) == NULL) 800 return; 801 ifmam = mtod(m, struct ifma_msghdr *); 802 ifmam->ifmam_index = ifp->if_index; 803 ifmam->ifmam_addrs = info.rti_addrs; 804 route_proto.sp_protocol = ifma->ifma_addr->sa_family; 805 raw_input(m, &route_proto, &route_src, &route_dst); 806 } 807 808 /* 809 * This is used in dumping the kernel table via sysctl(). 810 */ 811 int 812 sysctl_dumpentry(rn, vw) 813 struct radix_node *rn; 814 void *vw; 815 { 816 register struct walkarg *w = vw; 817 register struct rtentry *rt = (struct rtentry *)rn; 818 int error = 0, size; 819 struct rt_addrinfo info; 820 821 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 822 return 0; 823 bzero((caddr_t)&info, sizeof(info)); 824 dst = rt_key(rt); 825 gate = rt->rt_gateway; 826 netmask = rt_mask(rt); 827 genmask = rt->rt_genmask; 828 size = rt_msg2(RTM_GET, &info, 0, w); 829 if (w->w_req && w->w_tmem) { 830 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 831 832 rtm->rtm_flags = rt->rt_flags; 833 rtm->rtm_use = rt->rt_use; 834 rtm->rtm_rmx = rt->rt_rmx; 835 rtm->rtm_index = rt->rt_ifp->if_index; 836 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 837 rtm->rtm_addrs = info.rti_addrs; 838 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); 839 return (error); 840 } 841 return (error); 842 } 843 844 int 845 sysctl_iflist(af, w) 846 int af; 847 register struct walkarg *w; 848 { 849 register struct ifnet *ifp; 850 register struct ifaddr *ifa; 851 struct rt_addrinfo info; 852 int len, error = 0; 853 854 bzero((caddr_t)&info, sizeof(info)); 855 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { 856 if (w->w_arg && w->w_arg != ifp->if_index) 857 continue; 858 ifa = ifp->if_addrhead.tqh_first; 859 ifpaddr = ifa->ifa_addr; 860 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 861 ifpaddr = 0; 862 if (w->w_req && w->w_tmem) { 863 register struct if_msghdr *ifm; 864 865 ifm = (struct if_msghdr *)w->w_tmem; 866 ifm->ifm_index = ifp->if_index; 867 ifm->ifm_flags = (u_short)ifp->if_flags; 868 ifm->ifm_data = ifp->if_data; 869 ifm->ifm_addrs = info.rti_addrs; 870 error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len); 871 if (error) 872 return (error); 873 } 874 while ((ifa = ifa->ifa_link.tqe_next) != 0) { 875 if (af && af != ifa->ifa_addr->sa_family) 876 continue; 877 ifaaddr = ifa->ifa_addr; 878 netmask = ifa->ifa_netmask; 879 brdaddr = ifa->ifa_dstaddr; 880 len = rt_msg2(RTM_NEWADDR, &info, 0, w); 881 if (w->w_req && w->w_tmem) { 882 register struct ifa_msghdr *ifam; 883 884 ifam = (struct ifa_msghdr *)w->w_tmem; 885 ifam->ifam_index = ifa->ifa_ifp->if_index; 886 ifam->ifam_flags = ifa->ifa_flags; 887 ifam->ifam_metric = ifa->ifa_metric; 888 ifam->ifam_addrs = info.rti_addrs; 889 error = SYSCTL_OUT(w->w_req, w->w_tmem, len); 890 if (error) 891 return (error); 892 } 893 } 894 ifaaddr = netmask = brdaddr = 0; 895 } 896 return (0); 897 } 898 899 static int 900 sysctl_rtsock SYSCTL_HANDLER_ARGS 901 { 902 int *name = (int *)arg1; 903 u_int namelen = arg2; 904 register struct radix_node_head *rnh; 905 int i, s, error = EINVAL; 906 u_char af; 907 struct walkarg w; 908 909 name ++; 910 namelen--; 911 if (req->newptr) 912 return (EPERM); 913 if (namelen != 3) 914 return (EINVAL); 915 af = name[0]; 916 Bzero(&w, sizeof(w)); 917 w.w_op = name[1]; 918 w.w_arg = name[2]; 919 w.w_req = req; 920 921 s = splnet(); 922 switch (w.w_op) { 923 924 case NET_RT_DUMP: 925 case NET_RT_FLAGS: 926 for (i = 1; i <= AF_MAX; i++) 927 if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 928 (error = rnh->rnh_walktree(rnh, 929 sysctl_dumpentry, &w))) 930 break; 931 break; 932 933 case NET_RT_IFLIST: 934 error = sysctl_iflist(af, &w); 935 } 936 splx(s); 937 if (w.w_tmem) 938 free(w.w_tmem, M_RTABLE); 939 return (error); 940 } 941 942 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, ""); 943 944 /* 945 * Definitions of protocols supported in the ROUTE domain. 946 */ 947 948 extern struct domain routedomain; /* or at least forward */ 949 950 static struct protosw routesw[] = { 951 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 952 0, route_output, raw_ctlinput, 0, 953 0, 954 raw_init, 0, 0, 0, 955 &route_usrreqs 956 } 957 }; 958 959 static struct domain routedomain = 960 { PF_ROUTE, "route", route_init, 0, 0, 961 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 962 963 DOMAIN_SET(route); 964