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