1 /* $OpenBSD: rtsock.c,v 1.30 2003/07/05 00:00:32 itojun 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 && 240 suser(curproc->p_ucred, &curproc->p_acflag) != 0) 241 senderr(EACCES); 242 switch (rtm->rtm_type) { 243 244 case RTM_DELETE: 245 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 246 if (error == 0) { 247 (rt = saved_nrt)->rt_refcnt++; 248 goto report; 249 } 250 break; 251 252 case RTM_ADD: 253 if (gate == 0) 254 senderr(EINVAL); 255 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 256 if (error == 0 && saved_nrt) { 257 rt_setmetrics(rtm->rtm_inits, 258 &rtm->rtm_rmx, &saved_nrt->rt_rmx); 259 saved_nrt->rt_refcnt--; 260 saved_nrt->rt_genmask = genmask; 261 } 262 /* FALLTHROUGH */ 263 case RTM_GET: 264 case RTM_CHANGE: 265 case RTM_LOCK: 266 if ((rnh = rt_tables[dst->sa_family]) == 0) { 267 senderr(EAFNOSUPPORT); 268 } 269 rn = rnh->rnh_lookup(dst, netmask, rnh); 270 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) { 271 senderr(ESRCH); 272 } 273 rt = (struct rtentry *)rn; 274 rt->rt_refcnt++; 275 276 switch (rtm->rtm_type) { 277 278 case RTM_GET: 279 report: 280 dst = rt_key(rt); 281 gate = rt->rt_gateway; 282 netmask = rt_mask(rt); 283 genmask = rt->rt_genmask; 284 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 285 if ((ifp = rt->rt_ifp) != NULL) { 286 ifpaddr = 287 TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr; 288 ifaaddr = rt->rt_ifa->ifa_addr; 289 if (ifp->if_flags & IFF_POINTOPOINT) 290 brdaddr = rt->rt_ifa->ifa_dstaddr; 291 else 292 brdaddr = 0; 293 rtm->rtm_index = ifp->if_index; 294 } else { 295 ifpaddr = 0; 296 ifaaddr = 0; 297 } 298 } 299 len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, 300 (struct walkarg *)0); 301 if (len > rtm->rtm_msglen) { 302 struct rt_msghdr *new_rtm; 303 R_Malloc(new_rtm, struct rt_msghdr *, len); 304 if (new_rtm == 0) 305 senderr(ENOBUFS); 306 Bcopy(rtm, new_rtm, rtm->rtm_msglen); 307 Free(rtm); rtm = new_rtm; 308 } 309 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, 310 (struct walkarg *)0); 311 rtm->rtm_flags = rt->rt_flags; 312 rtm->rtm_rmx = rt->rt_rmx; 313 rtm->rtm_addrs = info.rti_addrs; 314 break; 315 316 case RTM_CHANGE: 317 /* 318 * new gateway could require new ifaddr, ifp; 319 * flags may also be different; ifp may be specified 320 * by ll sockaddr when protocol address is ambiguous 321 */ 322 if ((error = rt_getifa(&info)) != 0) 323 senderr(error); 324 if (gate && rt_setgate(rt, rt_key(rt), gate)) 325 senderr(EDQUOT); 326 if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && 327 (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) 328 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, 329 ifp); 330 else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || 331 (gate && (ifa = ifa_ifwithroute(rt->rt_flags, 332 rt_key(rt), gate)))) 333 ifp = ifa->ifa_ifp; 334 if (ifa) { 335 register struct ifaddr *oifa = rt->rt_ifa; 336 if (oifa != ifa) { 337 if (oifa && oifa->ifa_rtrequest) 338 oifa->ifa_rtrequest(RTM_DELETE, rt, 339 &info); 340 IFAFREE(rt->rt_ifa); 341 rt->rt_ifa = ifa; 342 ifa->ifa_refcnt++; 343 rt->rt_ifp = ifp; 344 } 345 } 346 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 347 &rt->rt_rmx); 348 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 349 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 350 if (genmask) 351 rt->rt_genmask = genmask; 352 /* 353 * Fall into 354 */ 355 case RTM_ADD: 356 case RTM_LOCK: 357 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 358 rt->rt_rmx.rmx_locks |= 359 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 360 break; 361 } 362 break; 363 364 default: 365 senderr(EOPNOTSUPP); 366 } 367 368 flush: 369 if (rtm) { 370 if (error) 371 rtm->rtm_errno = error; 372 else 373 rtm->rtm_flags |= RTF_DONE; 374 } 375 if (rt) 376 rtfree(rt); 377 { 378 register struct rawcb *rp = 0; 379 /* 380 * Check to see if we don't want our own messages. 381 */ 382 if ((so->so_options & SO_USELOOPBACK) == 0) { 383 if (route_cb.any_count <= 1) { 384 if (rtm) 385 Free(rtm); 386 m_freem(m); 387 return (error); 388 } 389 /* There is another listener, so construct message */ 390 rp = sotorawcb(so); 391 } 392 if (rp) 393 rp->rcb_proto.sp_family = 0; /* Avoid us */ 394 if (dst) 395 route_proto.sp_protocol = dst->sa_family; 396 if (rtm) { 397 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); 398 if (m->m_pkthdr.len < rtm->rtm_msglen) { 399 m_freem(m); 400 m = NULL; 401 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 402 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 403 Free(rtm); 404 } 405 if (m) 406 raw_input(m, &route_proto, &route_src, &route_dst); 407 if (rp) 408 rp->rcb_proto.sp_family = PF_ROUTE; 409 } 410 return (error); 411 } 412 413 void 414 rt_setmetrics(which, in, out) 415 u_long which; 416 register struct rt_metrics *in, *out; 417 { 418 #define metric(f, e) if (which & (f)) out->e = in->e; 419 metric(RTV_RPIPE, rmx_recvpipe); 420 metric(RTV_SPIPE, rmx_sendpipe); 421 metric(RTV_SSTHRESH, rmx_ssthresh); 422 metric(RTV_RTT, rmx_rtt); 423 metric(RTV_RTTVAR, rmx_rttvar); 424 metric(RTV_HOPCOUNT, rmx_hopcount); 425 metric(RTV_MTU, rmx_mtu); 426 metric(RTV_EXPIRE, rmx_expire); 427 #undef metric 428 } 429 430 #define ROUNDUP(a) \ 431 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 432 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 433 434 static void 435 rt_xaddrs(cp, cplim, rtinfo) 436 register caddr_t cp, cplim; 437 register struct rt_addrinfo *rtinfo; 438 { 439 register struct sockaddr *sa; 440 register int i; 441 442 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); 443 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 444 if ((rtinfo->rti_addrs & (1 << i)) == 0) 445 continue; 446 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 447 ADVANCE(cp, sa); 448 } 449 } 450 451 static struct mbuf * 452 rt_msg1(type, rtinfo) 453 int type; 454 register struct rt_addrinfo *rtinfo; 455 { 456 register struct rt_msghdr *rtm; 457 register struct mbuf *m; 458 register int i; 459 register struct sockaddr *sa; 460 int len, dlen; 461 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 if (len > MCLBYTES) 477 panic("rt_msg1"); 478 m = m_gethdr(M_DONTWAIT, MT_DATA); 479 if (m && len > MHLEN) { 480 MCLGET(m, M_DONTWAIT); 481 if ((m->m_flags & M_EXT) == 0) { 482 m_free(m); 483 m = NULL; 484 } 485 } 486 if (m == 0) 487 return (m); 488 m->m_pkthdr.len = m->m_len = len; 489 m->m_pkthdr.rcvif = 0; 490 rtm = mtod(m, struct rt_msghdr *); 491 bzero((caddr_t)rtm, len); 492 for (i = 0; i < RTAX_MAX; i++) { 493 if ((sa = rtinfo->rti_info[i]) == NULL) 494 continue; 495 rtinfo->rti_addrs |= (1 << i); 496 dlen = ROUNDUP(sa->sa_len); 497 m_copyback(m, len, dlen, (caddr_t)sa); 498 len += dlen; 499 } 500 if (m->m_pkthdr.len != len) { 501 m_freem(m); 502 return (NULL); 503 } 504 rtm->rtm_msglen = len; 505 rtm->rtm_version = RTM_VERSION; 506 rtm->rtm_type = type; 507 return (m); 508 } 509 510 static int 511 rt_msg2(type, rtinfo, cp, w) 512 int type; 513 register struct rt_addrinfo *rtinfo; 514 caddr_t cp; 515 struct walkarg *w; 516 { 517 register int i; 518 int len, dlen, second_time = 0; 519 caddr_t cp0; 520 521 rtinfo->rti_addrs = 0; 522 again: 523 switch (type) { 524 525 case RTM_DELADDR: 526 case RTM_NEWADDR: 527 len = sizeof(struct ifa_msghdr); 528 break; 529 530 case RTM_IFINFO: 531 len = sizeof(struct if_msghdr); 532 break; 533 534 default: 535 len = sizeof(struct rt_msghdr); 536 } 537 if ((cp0 = cp) != NULL) 538 cp += len; 539 for (i = 0; i < RTAX_MAX; i++) { 540 register struct sockaddr *sa; 541 542 if ((sa = rtinfo->rti_info[i]) == 0) 543 continue; 544 rtinfo->rti_addrs |= (1 << i); 545 dlen = ROUNDUP(sa->sa_len); 546 if (cp) { 547 bcopy((caddr_t)sa, cp, (unsigned)dlen); 548 cp += dlen; 549 } 550 len += dlen; 551 } 552 if (cp == 0 && w != NULL && !second_time) { 553 register struct walkarg *rw = w; 554 555 rw->w_needed += len; 556 if (rw->w_needed <= 0 && rw->w_where) { 557 if (rw->w_tmemsize < len) { 558 if (rw->w_tmem) 559 free(rw->w_tmem, M_RTABLE); 560 rw->w_tmem = (caddr_t) malloc(len, M_RTABLE, 561 M_NOWAIT); 562 if (rw->w_tmem) 563 rw->w_tmemsize = len; 564 } 565 if (rw->w_tmem) { 566 cp = rw->w_tmem; 567 second_time = 1; 568 goto again; 569 } else 570 rw->w_where = 0; 571 } 572 } 573 if (cp) { 574 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 575 576 rtm->rtm_version = RTM_VERSION; 577 rtm->rtm_type = type; 578 rtm->rtm_msglen = len; 579 } 580 return (len); 581 } 582 583 /* 584 * This routine is called to generate a message from the routing 585 * socket indicating that a redirect has occurred, a routing lookup 586 * has failed, or that a protocol has detected timeouts to a particular 587 * destination. 588 */ 589 void 590 rt_missmsg(type, rtinfo, flags, error) 591 int type, flags, error; 592 register struct rt_addrinfo *rtinfo; 593 { 594 register struct rt_msghdr *rtm; 595 register struct mbuf *m; 596 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 597 598 if (route_cb.any_count == 0) 599 return; 600 m = rt_msg1(type, rtinfo); 601 if (m == 0) 602 return; 603 rtm = mtod(m, struct rt_msghdr *); 604 rtm->rtm_flags = RTF_DONE | flags; 605 rtm->rtm_errno = error; 606 rtm->rtm_addrs = rtinfo->rti_addrs; 607 route_proto.sp_protocol = sa ? sa->sa_family : 0; 608 raw_input(m, &route_proto, &route_src, &route_dst); 609 } 610 611 /* 612 * This routine is called to generate a message from the routing 613 * socket indicating that the status of a network interface has changed. 614 */ 615 void 616 rt_ifmsg(ifp) 617 register struct ifnet *ifp; 618 { 619 register struct if_msghdr *ifm; 620 struct mbuf *m; 621 struct rt_addrinfo info; 622 623 if (route_cb.any_count == 0) 624 return; 625 bzero((caddr_t)&info, sizeof(info)); 626 m = rt_msg1(RTM_IFINFO, &info); 627 if (m == 0) 628 return; 629 ifm = mtod(m, struct if_msghdr *); 630 ifm->ifm_index = ifp->if_index; 631 ifm->ifm_flags = ifp->if_flags; 632 ifm->ifm_data = ifp->if_data; 633 ifm->ifm_addrs = 0; 634 route_proto.sp_protocol = 0; 635 raw_input(m, &route_proto, &route_src, &route_dst); 636 } 637 638 /* 639 * This is called to generate messages from the routing socket 640 * indicating a network interface has had addresses associated with it. 641 * if we ever reverse the logic and replace messages TO the routing 642 * socket indicate a request to configure interfaces, then it will 643 * be unnecessary as the routing socket will automatically generate 644 * copies of it. 645 */ 646 void 647 rt_newaddrmsg(cmd, ifa, error, rt) 648 int cmd, error; 649 register struct ifaddr *ifa; 650 register struct rtentry *rt; 651 { 652 struct rt_addrinfo info; 653 struct sockaddr *sa = NULL; 654 int pass; 655 struct mbuf *m = NULL; 656 struct ifnet *ifp = ifa->ifa_ifp; 657 658 if (route_cb.any_count == 0) 659 return; 660 for (pass = 1; pass < 3; pass++) { 661 bzero((caddr_t)&info, sizeof(info)); 662 if ((cmd == RTM_ADD && pass == 1) || 663 (cmd == RTM_DELETE && pass == 2)) { 664 register struct ifa_msghdr *ifam; 665 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; 666 667 ifaaddr = sa = ifa->ifa_addr; 668 ifpaddr = TAILQ_FIRST(&ifp->if_addrlist)->ifa_addr; 669 netmask = ifa->ifa_netmask; 670 brdaddr = ifa->ifa_dstaddr; 671 if ((m = rt_msg1(ncmd, &info)) == NULL) 672 continue; 673 ifam = mtod(m, struct ifa_msghdr *); 674 ifam->ifam_index = ifp->if_index; 675 ifam->ifam_metric = ifa->ifa_metric; 676 ifam->ifam_flags = ifa->ifa_flags; 677 ifam->ifam_addrs = info.rti_addrs; 678 } 679 if ((cmd == RTM_ADD && pass == 2) || 680 (cmd == RTM_DELETE && pass == 1)) { 681 register struct rt_msghdr *rtm; 682 683 if (rt == 0) 684 continue; 685 netmask = rt_mask(rt); 686 dst = sa = rt_key(rt); 687 gate = rt->rt_gateway; 688 if ((m = rt_msg1(cmd, &info)) == NULL) 689 continue; 690 rtm = mtod(m, struct rt_msghdr *); 691 rtm->rtm_index = ifp->if_index; 692 rtm->rtm_flags |= rt->rt_flags; 693 rtm->rtm_errno = error; 694 rtm->rtm_addrs = info.rti_addrs; 695 } 696 route_proto.sp_protocol = sa ? sa->sa_family : 0; 697 raw_input(m, &route_proto, &route_src, &route_dst); 698 } 699 } 700 701 /* 702 * This is used in dumping the kernel table via sysctl(). 703 */ 704 int 705 sysctl_dumpentry(rn, v) 706 struct radix_node *rn; 707 register void *v; 708 { 709 register struct walkarg *w = v; 710 register struct rtentry *rt = (struct rtentry *)rn; 711 int error = 0, size; 712 struct rt_addrinfo info; 713 714 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 715 return 0; 716 bzero((caddr_t)&info, sizeof(info)); 717 dst = rt_key(rt); 718 gate = rt->rt_gateway; 719 netmask = rt_mask(rt); 720 genmask = rt->rt_genmask; 721 if (rt->rt_ifp) { 722 ifpaddr = TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr; 723 ifaaddr = rt->rt_ifa->ifa_addr; 724 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 725 brdaddr = rt->rt_ifa->ifa_dstaddr; 726 } 727 size = rt_msg2(RTM_GET, &info, 0, w); 728 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 729 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 730 731 rtm->rtm_flags = rt->rt_flags; 732 rtm->rtm_use = rt->rt_use; 733 rtm->rtm_rmx = rt->rt_rmx; 734 rtm->rtm_index = rt->rt_ifp->if_index; 735 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 736 rtm->rtm_addrs = info.rti_addrs; 737 if ((error = copyout((caddr_t)rtm, w->w_where, size)) != 0) 738 w->w_where = NULL; 739 else 740 w->w_where += size; 741 } 742 return (error); 743 } 744 745 int 746 sysctl_iflist(af, w) 747 int af; 748 register struct walkarg *w; 749 { 750 register struct ifnet *ifp; 751 register struct ifaddr *ifa; 752 struct rt_addrinfo info; 753 int len, error = 0; 754 755 bzero((caddr_t)&info, sizeof(info)); 756 TAILQ_FOREACH(ifp, &ifnet, if_list) { 757 if (w->w_arg && w->w_arg != ifp->if_index) 758 continue; 759 ifa = TAILQ_FIRST(&ifp->if_addrlist); 760 if (!ifa) 761 continue; 762 ifpaddr = ifa->ifa_addr; 763 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); 764 ifpaddr = 0; 765 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 766 register struct if_msghdr *ifm; 767 768 ifm = (struct if_msghdr *)w->w_tmem; 769 ifm->ifm_index = ifp->if_index; 770 ifm->ifm_flags = ifp->if_flags; 771 ifm->ifm_data = ifp->if_data; 772 ifm->ifm_addrs = info.rti_addrs; 773 error = copyout((caddr_t)ifm, w->w_where, len); 774 if (error) 775 return (error); 776 w->w_where += len; 777 } 778 while ((ifa = TAILQ_NEXT(ifa, ifa_list)) != 779 TAILQ_END(&ifp->if_addrlist)) { 780 if (af && af != ifa->ifa_addr->sa_family) 781 continue; 782 ifaaddr = ifa->ifa_addr; 783 netmask = ifa->ifa_netmask; 784 brdaddr = ifa->ifa_dstaddr; 785 len = rt_msg2(RTM_NEWADDR, &info, 0, w); 786 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 787 register struct ifa_msghdr *ifam; 788 789 ifam = (struct ifa_msghdr *)w->w_tmem; 790 ifam->ifam_index = ifa->ifa_ifp->if_index; 791 ifam->ifam_flags = ifa->ifa_flags; 792 ifam->ifam_metric = ifa->ifa_metric; 793 ifam->ifam_addrs = info.rti_addrs; 794 error = copyout(w->w_tmem, w->w_where, len); 795 if (error) 796 return (error); 797 w->w_where += len; 798 } 799 } 800 ifaaddr = netmask = brdaddr = 0; 801 } 802 return (0); 803 } 804 805 int 806 sysctl_rtable(name, namelen, where, given, new, newlen) 807 int *name; 808 u_int namelen; 809 void *where; 810 size_t *given; 811 void *new; 812 size_t newlen; 813 { 814 register struct radix_node_head *rnh; 815 int i, s, error = EINVAL; 816 u_char af; 817 struct walkarg w; 818 819 if (new) 820 return (EPERM); 821 if (namelen != 3) 822 return (EINVAL); 823 af = name[0]; 824 Bzero(&w, sizeof(w)); 825 w.w_where = where; 826 w.w_given = *given; 827 w.w_needed = 0 - w.w_given; 828 w.w_op = name[1]; 829 w.w_arg = name[2]; 830 831 s = splsoftnet(); 832 switch (w.w_op) { 833 834 case NET_RT_DUMP: 835 case NET_RT_FLAGS: 836 for (i = 1; i <= AF_MAX; i++) 837 if ((rnh = rt_tables[i]) && (af == 0 || af == i) && 838 (error = (*rnh->rnh_walktree)(rnh, 839 sysctl_dumpentry, 840 &w))) 841 break; 842 break; 843 844 case NET_RT_IFLIST: 845 error = sysctl_iflist(af, &w); 846 } 847 splx(s); 848 if (w.w_tmem) 849 free(w.w_tmem, M_RTABLE); 850 w.w_needed += w.w_given; 851 if (where) { 852 *given = w.w_where - (caddr_t) where; 853 if (*given < w.w_needed) 854 return (ENOMEM); 855 } else { 856 *given = (11 * w.w_needed) / 10; 857 } 858 return (error); 859 } 860 861 /* 862 * Definitions of protocols supported in the ROUTE domain. 863 */ 864 865 extern struct domain routedomain; /* or at least forward */ 866 867 struct protosw routesw[] = { 868 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 869 raw_input, route_output, raw_ctlinput, 0, 870 route_usrreq, 871 raw_init, 0, 0, 0, 872 sysctl_rtable, 873 } 874 }; 875 876 struct domain routedomain = 877 { PF_ROUTE, "route", route_init, 0, 0, 878 routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; 879