|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)rtsock.c 7.13 (Berkeley) 7/24/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "mbuf.h" ! 25: #include "user.h" ! 26: #include "proc.h" ! 27: #include "socket.h" ! 28: #include "socketvar.h" ! 29: #include "domain.h" ! 30: #include "protosw.h" ! 31: #include "errno.h" ! 32: ! 33: #include "af.h" ! 34: #include "if.h" ! 35: #include "route.h" ! 36: #include "raw_cb.h" ! 37: ! 38: #include "machine/mtpr.h" ! 39: ! 40: struct sockaddr route_dst = { 2, PF_ROUTE, }; ! 41: struct sockaddr route_src = { 2, PF_ROUTE, }; ! 42: struct sockproto route_proto = { PF_ROUTE, }; ! 43: ! 44: /*ARGSUSED*/ ! 45: route_usrreq(so, req, m, nam, control) ! 46: register struct socket *so; ! 47: int req; ! 48: struct mbuf *m, *nam, *control; ! 49: { ! 50: register int error = 0; ! 51: register struct rawcb *rp = sotorawcb(so); ! 52: int s; ! 53: if (req == PRU_ATTACH) { ! 54: MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); ! 55: if (so->so_pcb = (caddr_t)rp) ! 56: bzero(so->so_pcb, sizeof(*rp)); ! 57: ! 58: } ! 59: if (req == PRU_DETACH && rp) { ! 60: int af = rp->rcb_proto.sp_protocol; ! 61: if (af == AF_INET) ! 62: route_cb.ip_count--; ! 63: else if (af == AF_NS) ! 64: route_cb.ns_count--; ! 65: else if (af == AF_ISO) ! 66: route_cb.iso_count--; ! 67: route_cb.any_count--; ! 68: } ! 69: s = splnet(); ! 70: error = raw_usrreq(so, req, m, nam, control); ! 71: rp = sotorawcb(so); ! 72: if (req == PRU_ATTACH && rp) { ! 73: int af = rp->rcb_proto.sp_protocol; ! 74: if (error) { ! 75: free((caddr_t)rp, M_PCB); ! 76: splx(s); ! 77: return (error); ! 78: } ! 79: if (af == AF_INET) ! 80: route_cb.ip_count++; ! 81: else if (af == AF_NS) ! 82: route_cb.ns_count++; ! 83: else if (af == AF_ISO) ! 84: route_cb.iso_count++; ! 85: rp->rcb_faddr = &route_src; ! 86: route_cb.any_count++; ! 87: soisconnected(so); ! 88: so->so_options |= SO_USELOOPBACK; ! 89: } ! 90: splx(s); ! 91: return (error); ! 92: } ! 93: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) ! 94: ! 95: /*ARGSUSED*/ ! 96: route_output(m, so) ! 97: register struct mbuf *m; ! 98: struct socket *so; ! 99: { ! 100: register struct rt_msghdr *rtm = 0; ! 101: register struct rtentry *rt = 0; ! 102: struct rtentry *saved_nrt = 0; ! 103: struct sockaddr *dst = 0, *gate = 0, *netmask = 0, *genmask = 0; ! 104: struct sockaddr *ifpaddr = 0; ! 105: caddr_t cp, lim; ! 106: int len, error = 0; ! 107: struct ifnet *ifp = 0; ! 108: struct ifaddr *ifa; ! 109: extern 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: senderr(EINVAL); ! 122: R_Malloc(rtm, struct rt_msghdr *, len); ! 123: if (rtm == 0) ! 124: senderr(ENOBUFS); ! 125: m_copydata(m, 0, len, (caddr_t)rtm); ! 126: if (rtm->rtm_version != RTM_VERSION) ! 127: senderr(EPROTONOSUPPORT); ! 128: rtm->rtm_pid = u.u_procp->p_pid; ! 129: lim = len + (caddr_t) rtm; ! 130: cp = (caddr_t) (rtm + 1); ! 131: if (rtm->rtm_addrs & RTA_DST) { ! 132: dst = (struct sockaddr *)cp; ! 133: cp += ROUNDUP(dst->sa_len); ! 134: } else ! 135: senderr(EINVAL); ! 136: if ((rtm->rtm_addrs & RTA_GATEWAY) && cp < lim) { ! 137: gate = (struct sockaddr *)cp; ! 138: cp += ROUNDUP(gate->sa_len); ! 139: } ! 140: if ((rtm->rtm_addrs & RTA_NETMASK) && cp < lim) { ! 141: netmask = (struct sockaddr *)cp; ! 142: if (*cp) ! 143: cp += ROUNDUP(netmask->sa_len); ! 144: else ! 145: cp += sizeof(long); ! 146: ! 147: } ! 148: if ((rtm->rtm_addrs & RTA_GENMASK) && cp < lim) { ! 149: struct radix_node *t, *rn_addmask(); ! 150: genmask = (struct sockaddr *)cp; ! 151: if (*cp) ! 152: cp += ROUNDUP(netmask->sa_len); ! 153: else ! 154: cp += sizeof(long); ! 155: t = rn_addmask(genmask, 1, 2); ! 156: if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) ! 157: genmask = (struct sockaddr *)(t->rn_key); ! 158: else ! 159: senderr(ENOBUFS); ! 160: } ! 161: if ((rtm->rtm_addrs & RTA_IFP) && cp < lim) { ! 162: ifpaddr = (struct sockaddr *)cp; ! 163: } ! 164: switch (rtm->rtm_type) { ! 165: case RTM_ADD: ! 166: if (gate == 0) ! 167: senderr(EINVAL); ! 168: error = rtrequest(RTM_ADD, dst, gate, netmask, ! 169: rtm->rtm_flags, &saved_nrt); ! 170: if (error == 0 && saved_nrt) { ! 171: rt_setmetrics(rtm->rtm_inits, ! 172: &rtm->rtm_rmx, &saved_nrt->rt_rmx); ! 173: saved_nrt->rt_refcnt--; ! 174: saved_nrt->rt_genmask = genmask; ! 175: } ! 176: break; ! 177: ! 178: case RTM_DELETE: ! 179: error = rtrequest(RTM_DELETE, dst, gate, netmask, ! 180: rtm->rtm_flags, (struct rtentry **)0); ! 181: break; ! 182: ! 183: case RTM_GET: ! 184: case RTM_CHANGE: ! 185: case RTM_LOCK: ! 186: rt = rtalloc1(dst, 0); ! 187: if (rt == 0) ! 188: senderr(ESRCH); ! 189: switch(rtm->rtm_type) { ! 190: struct sockaddr *outmask; ! 191: ! 192: case RTM_GET: ! 193: netmask = rt_mask(rt); ! 194: len = sizeof(*rtm) + ROUNDUP(rt_key(rt)->sa_len); ! 195: rtm->rtm_addrs = RTA_DST; ! 196: if (rt->rt_gateway) { ! 197: len += ROUNDUP(rt->rt_gateway->sa_len); ! 198: rtm->rtm_addrs |= RTA_GATEWAY; ! 199: } ! 200: if (netmask) { ! 201: len += netmask->sa_len; ! 202: rtm->rtm_addrs |= RTA_NETMASK; ! 203: } ! 204: if (len > rtm->rtm_msglen) { ! 205: struct rt_msghdr *new_rtm; ! 206: R_Malloc(new_rtm, struct rt_msghdr *, len); ! 207: if (new_rtm == 0) ! 208: senderr(ENOBUFS); ! 209: Bcopy(rtm, new_rtm, rtm->rtm_msglen); ! 210: Free(rtm); rtm = new_rtm; ! 211: gate = (struct sockaddr *) ! 212: (ROUNDUP(rt->rt_gateway->sa_len) ! 213: + (char *)dst); ! 214: Bcopy(&rt->rt_gateway, gate, ! 215: rt->rt_gateway->sa_len); ! 216: rtm->rtm_flags = rt->rt_flags; ! 217: if (netmask) { ! 218: outmask = (struct sockaddr *) ! 219: (ROUNDUP(netmask->sa_len)+(char *)gate); ! 220: Bcopy(netmask, outmask, netmask->sa_len); ! 221: } ! 222: } ! 223: break; ! 224: ! 225: case RTM_CHANGE: ! 226: if (gate == 0 || netmask != 0) ! 227: senderr(EINVAL); ! 228: if (gate->sa_len > (len = rt->rt_gateway->sa_len)) ! 229: senderr(EDQUOT); ! 230: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) ! 231: rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, gate); ! 232: /* new gateway could require new ifaddr, ifp; ! 233: flags may also be different; ifp may be specified ! 234: by ll sockaddr when protocol address is ambiguous */ ! 235: if (ifpaddr && ! 236: (ifa = ifa_ifwithnet(ifpaddr)) && ! 237: (ifp = ifa->ifa_ifp) && ! 238: (ifa = ifaof_ifpforaddr(gate, ifp))) { ! 239: /* We got it */ ! 240: } else { ! 241: ifa = 0; ifp = 0; ! 242: } ! 243: Bcopy(gate, rt->rt_gateway, len); ! 244: rt->rt_gateway->sa_len = len; ! 245: rt_setmetrics(rtm->rtm_inits, ! 246: &rtm->rtm_rmx, &rt->rt_rmx); ! 247: if (ifa == 0) ! 248: ifa = ifa_ifwithroute(rt->rt_flags, rt_key(rt), ! 249: gate); ! 250: if (ifa) { ! 251: if (rt->rt_ifa != ifa) { ! 252: rt->rt_ifa = ifa; ! 253: rt->rt_ifp = ifa->ifa_ifp; ! 254: } ! 255: } ! 256: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) ! 257: rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); ! 258: if (genmask) ! 259: rt->rt_genmask = genmask; ! 260: /* ! 261: * Fall into ! 262: */ ! 263: case RTM_LOCK: ! 264: rt->rt_rmx.rmx_locks |= ! 265: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); ! 266: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); ! 267: break; ! 268: } ! 269: goto cleanup; ! 270: ! 271: default: ! 272: senderr(EOPNOTSUPP); ! 273: } ! 274: ! 275: flush: ! 276: if (rtm) { ! 277: if (error) ! 278: rtm->rtm_errno = error; ! 279: else ! 280: rtm->rtm_flags |= RTF_DONE; ! 281: } ! 282: cleanup: ! 283: if (rt) ! 284: rtfree(rt); ! 285: { ! 286: register struct rawcb *rp = 0; ! 287: /* ! 288: * Check to see if we don't want our own messages. ! 289: */ ! 290: if ((so->so_options & SO_USELOOPBACK) == 0) { ! 291: if (route_cb.any_count <= 1) { ! 292: if (rtm) ! 293: Free(rtm); ! 294: m_freem(m); ! 295: return (error); ! 296: } ! 297: /* There is another listener, so construct message */ ! 298: rp = sotorawcb(so); ! 299: } ! 300: if (cp = (caddr_t)rtm) { ! 301: m_copyback(m, 0, len, cp); ! 302: Free(rtm); ! 303: } ! 304: if (rp) ! 305: rp->rcb_proto.sp_family = 0; /* Avoid us */ ! 306: route_proto.sp_protocol = dst->sa_family; ! 307: raw_input(m, &route_proto, &route_src, &route_dst); ! 308: if (rp) ! 309: rp->rcb_proto.sp_family = PF_ROUTE; ! 310: } ! 311: return (error); ! 312: } ! 313: ! 314: rt_setmetrics(which, in, out) ! 315: u_long which; ! 316: register struct rt_metrics *in, *out; ! 317: { ! 318: #define metric(f, e) if (which & (f)) out->e = in->e; ! 319: metric(RTV_RPIPE, rmx_recvpipe); ! 320: metric(RTV_SPIPE, rmx_sendpipe); ! 321: metric(RTV_SSTHRESH, rmx_ssthresh); ! 322: metric(RTV_RTT, rmx_rtt); ! 323: metric(RTV_RTTVAR, rmx_rttvar); ! 324: metric(RTV_HOPCOUNT, rmx_hopcount); ! 325: metric(RTV_MTU, rmx_mtu); ! 326: #undef metric ! 327: } ! 328: ! 329: /* ! 330: * Copy data from a buffer back into the indicated mbuf chain, ! 331: * starting "off" bytes from the beginning, extending the mbuf ! 332: * chain if necessary. ! 333: */ ! 334: m_copyback(m0, off, len, cp) ! 335: struct mbuf *m0; ! 336: register int off; ! 337: register int len; ! 338: caddr_t cp; ! 339: ! 340: { ! 341: register int mlen; ! 342: register struct mbuf *m = m0, *n; ! 343: int totlen = 0; ! 344: ! 345: if (m0 == 0) ! 346: return; ! 347: while (off >= (mlen = m->m_len)) { ! 348: off -= mlen; ! 349: totlen += mlen; ! 350: if (m->m_next == 0) { ! 351: n = m_getclr(M_DONTWAIT, m->m_type); ! 352: if (n == 0) ! 353: goto out; ! 354: n->m_len = min(MLEN, len + off); ! 355: m->m_next = n; ! 356: } ! 357: m = m->m_next; ! 358: } ! 359: while (len > 0) { ! 360: mlen = min (m->m_len - off, len); ! 361: bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); ! 362: cp += mlen; ! 363: len -= mlen; ! 364: mlen += off; ! 365: off = 0; ! 366: totlen += mlen; ! 367: if (len == 0) ! 368: break; ! 369: if (m->m_next == 0) { ! 370: n = m_get(M_DONTWAIT, m->m_type); ! 371: if (n == 0) ! 372: break; ! 373: n->m_len = min(MLEN, len); ! 374: m->m_next = n; ! 375: } ! 376: m = m->m_next; ! 377: } ! 378: out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) ! 379: m->m_pkthdr.len = totlen; ! 380: } ! 381: ! 382: /* ! 383: * The miss message and losing message are very similar. ! 384: */ ! 385: ! 386: rt_missmsg(type, dst, gate, mask, src, flags, error) ! 387: register struct sockaddr *dst; ! 388: struct sockaddr *gate, *mask, *src; ! 389: { ! 390: register struct rt_msghdr *rtm; ! 391: register struct mbuf *m; ! 392: int dlen = ROUNDUP(dst->sa_len); ! 393: int len = dlen + sizeof(*rtm); ! 394: ! 395: if (route_cb.any_count == 0) ! 396: return; ! 397: m = m_gethdr(M_DONTWAIT, MT_DATA); ! 398: if (m == 0) ! 399: return; ! 400: m->m_pkthdr.len = m->m_len = min(len, MHLEN); ! 401: m->m_pkthdr.rcvif = 0; ! 402: rtm = mtod(m, struct rt_msghdr *); ! 403: bzero((caddr_t)rtm, sizeof(*rtm)); /*XXX assumes sizeof(*rtm) < MHLEN*/ ! 404: rtm->rtm_flags = RTF_DONE | flags; ! 405: rtm->rtm_msglen = len; ! 406: rtm->rtm_version = RTM_VERSION; ! 407: rtm->rtm_type = type; ! 408: rtm->rtm_addrs = RTA_DST; ! 409: if (type == RTM_OLDADD || type == RTM_OLDDEL) { ! 410: rtm->rtm_pid = u.u_procp->p_pid; ! 411: } ! 412: m_copyback(m, sizeof (*rtm), dlen, (caddr_t)dst); ! 413: if (gate) { ! 414: dlen = ROUNDUP(gate->sa_len); ! 415: m_copyback(m, len , dlen, (caddr_t)gate); ! 416: len += dlen; ! 417: rtm->rtm_addrs |= RTA_GATEWAY; ! 418: } ! 419: if (mask) { ! 420: if (mask->sa_len) ! 421: dlen = ROUNDUP(mask->sa_len); ! 422: else ! 423: dlen = sizeof(long); ! 424: m_copyback(m, len , dlen, (caddr_t)mask); ! 425: len += dlen; ! 426: rtm->rtm_addrs |= RTA_NETMASK; ! 427: } ! 428: if (src) { ! 429: dlen = ROUNDUP(src->sa_len); ! 430: m_copyback(m, len , dlen, (caddr_t)src); ! 431: len += dlen; ! 432: rtm->rtm_addrs |= RTA_AUTHOR; ! 433: } ! 434: if (m->m_pkthdr.len != len) { ! 435: m_freem(m); ! 436: return; ! 437: } ! 438: rtm->rtm_errno = error; ! 439: rtm->rtm_msglen = len; ! 440: route_proto.sp_protocol = dst->sa_family; ! 441: raw_input(m, &route_proto, &route_src, &route_dst); ! 442: } ! 443: ! 444: #include "kinfo.h" ! 445: struct walkarg { ! 446: int w_op, w_arg; ! 447: int w_given, w_needed; ! 448: caddr_t w_where; ! 449: struct { ! 450: struct rt_msghdr m_rtm; ! 451: char m_sabuf[128]; ! 452: } w_m; ! 453: #define w_rtm w_m.m_rtm ! 454: }; ! 455: /* ! 456: * This is used in dumping the kernel table via getkinfo(). ! 457: */ ! 458: rt_dumpentry(rn, w) ! 459: struct radix_node *rn; ! 460: register struct walkarg *w; ! 461: { ! 462: register struct sockaddr *sa; ! 463: int n, error; ! 464: ! 465: for (; rn; rn = rn->rn_dupedkey) { ! 466: int count = 0, size = sizeof(w->w_rtm); ! 467: register struct rtentry *rt = (struct rtentry *)rn; ! 468: ! 469: if (rn->rn_flags & RNF_ROOT) ! 470: continue; ! 471: if (w->w_op == KINFO_RT_FLAGS && !(rt->rt_flags & w->w_arg)) ! 472: continue; ! 473: #define next(a, l) {size += (l); w->w_rtm.rtm_addrs |= (a); } ! 474: w->w_rtm.rtm_addrs = 0; ! 475: if (sa = rt_key(rt)) ! 476: next(RTA_DST, ROUNDUP(sa->sa_len)); ! 477: if (sa = rt->rt_gateway) ! 478: next(RTA_GATEWAY, ROUNDUP(sa->sa_len)); ! 479: if (sa = rt_mask(rt)) ! 480: next(RTA_NETMASK, ! 481: sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); ! 482: if (sa = rt->rt_genmask) ! 483: next(RTA_GENMASK, ROUNDUP(sa->sa_len)); ! 484: w->w_needed += size; ! 485: if (w->w_where == NULL || w->w_needed > 0) ! 486: continue; ! 487: w->w_rtm.rtm_msglen = size; ! 488: w->w_rtm.rtm_flags = rt->rt_flags; ! 489: w->w_rtm.rtm_use = rt->rt_use; ! 490: w->w_rtm.rtm_rmx = rt->rt_rmx; ! 491: w->w_rtm.rtm_index = rt->rt_ifp->if_index; ! 492: #undef next ! 493: #define next(l) {n = (l); Bcopy(sa, cp, n); cp += n;} ! 494: if (size <= sizeof(w->w_m)) { ! 495: register caddr_t cp = (caddr_t)(w->w_m.m_sabuf); ! 496: if (sa = rt_key(rt)) ! 497: next(ROUNDUP(sa->sa_len)); ! 498: if (sa = rt->rt_gateway) ! 499: next(ROUNDUP(sa->sa_len)); ! 500: if (sa = rt_mask(rt)) ! 501: next(sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); ! 502: if (sa = rt->rt_genmask) ! 503: next(ROUNDUP(sa->sa_len)); ! 504: #undef next ! 505: #define next(s, l) {n = (l); \ ! 506: if (error = copyout((caddr_t)(s), w->w_where, n)) return (error); \ ! 507: w->w_where += n;} ! 508: ! 509: next(&w->w_m, size); /* Copy rtmsg and sockaddrs back */ ! 510: continue; ! 511: } ! 512: next(&w->w_rtm, sizeof(w->w_rtm)); ! 513: if (sa = rt_key(rt)) ! 514: next(sa, ROUNDUP(sa->sa_len)); ! 515: if (sa = rt->rt_gateway) ! 516: next(sa, ROUNDUP(sa->sa_len)); ! 517: if (sa = rt_mask(rt)) ! 518: next(sa, sa->sa_len ? ROUNDUP(sa->sa_len) : sizeof(long)); ! 519: if (sa = rt->rt_genmask) ! 520: next(sa, ROUNDUP(sa->sa_len)); ! 521: } ! 522: return (0); ! 523: #undef next ! 524: } ! 525: ! 526: kinfo_rtable(op, where, given, arg, needed) ! 527: int op, arg; ! 528: caddr_t where; ! 529: int *given, *needed; ! 530: { ! 531: register struct radix_node_head *rnh; ! 532: int s, error = 0; ! 533: u_char af = ki_af(op); ! 534: struct walkarg w; ! 535: ! 536: op &= 0xffff; ! 537: if (op != KINFO_RT_DUMP && op != KINFO_RT_FLAGS) ! 538: return (EINVAL); ! 539: ! 540: Bzero(&w, sizeof(w)); ! 541: if ((w.w_where = where) && given) ! 542: w.w_given = *given; ! 543: w.w_needed = 0 - w.w_given; ! 544: w.w_arg = arg; ! 545: w.w_op = op; ! 546: w.w_rtm.rtm_version = RTM_VERSION; ! 547: w.w_rtm.rtm_type = RTM_GET; ! 548: ! 549: s = splnet(); ! 550: for (rnh = radix_node_head; rnh; rnh = rnh->rnh_next) { ! 551: if (rnh->rnh_af == 0) ! 552: continue; ! 553: if (af && af != rnh->rnh_af) ! 554: continue; ! 555: error = rt_walk(rnh->rnh_treetop, rt_dumpentry, &w); ! 556: if (error) ! 557: break; ! 558: } ! 559: w.w_needed += w.w_given; ! 560: if (where && given) ! 561: *given = w.w_where - where; ! 562: else ! 563: w.w_needed = (11 * w.w_needed) / 10; ! 564: *needed = w.w_needed; ! 565: splx(s); ! 566: return (error); ! 567: } ! 568: ! 569: rt_walk(rn, f, w) ! 570: register struct radix_node *rn; ! 571: register int (*f)(); ! 572: struct walkarg *w; ! 573: { ! 574: int error; ! 575: for (;;) { ! 576: while (rn->rn_b >= 0) ! 577: rn = rn->rn_l; /* First time through node, go left */ ! 578: if (error = (*f)(rn, w)) ! 579: return (error); /* Process Leaf */ ! 580: while (rn->rn_p->rn_r == rn) { /* if coming back from right */ ! 581: rn = rn->rn_p; /* go back up */ ! 582: if (rn->rn_flags & RNF_ROOT) ! 583: return 0; ! 584: } ! 585: rn = rn->rn_p->rn_r; /* otherwise, go right*/ ! 586: } ! 587: } ! 588: ! 589: /* ! 590: * Definitions of protocols supported in the ROUTE domain. ! 591: */ ! 592: ! 593: int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput(); ! 594: extern struct domain routedomain; /* or at least forward */ ! 595: ! 596: struct protosw routesw[] = { ! 597: { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, ! 598: raw_input, route_output, raw_ctlinput, 0, ! 599: route_usrreq, ! 600: raw_init, 0, 0, 0, ! 601: } ! 602: }; ! 603: ! 604: int unp_externalize(), unp_dispose(); ! 605: ! 606: struct domain routedomain = ! 607: { PF_ROUTE, "route", 0, 0, 0, ! 608: routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.