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