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