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