|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1988, 1991, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)rtsock.c 8.6 (Berkeley) 2/11/95
59: */
60:
61: #include <sys/param.h>
62: #include <sys/systm.h>
63: #include <sys/proc.h>
64: #include <sys/mbuf.h>
65: #include <sys/socket.h>
66: #include <sys/socketvar.h>
67: #include <sys/domain.h>
68: #include <sys/protosw.h>
69: #include <sys/malloc.h>
70:
71: #include <net/if.h>
72: #include <net/route.h>
73: #include <net/raw_cb.h>
74:
75: struct route_cb route_cb;
76: struct sockaddr route_dst = { 2, PF_ROUTE, };
77: struct sockaddr route_src = { 2, PF_ROUTE, };
78: struct sockproto route_proto = { PF_ROUTE, };
79:
80: struct walkarg {
81: int w_op, w_arg, w_given, w_needed, w_tmemsize;
82: caddr_t w_where, w_tmem;
83: };
84:
85: static struct mbuf *
86: rt_msg1 __P((int, struct rt_addrinfo *));
87: static int rt_msg2 __P((int,
88: struct rt_addrinfo *, caddr_t, struct walkarg *));
89: static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
90:
91: /* Sleazy use of local variables throughout file, warning!!!! */
92: #define dst info.rti_info[RTAX_DST]
93: #define gate info.rti_info[RTAX_GATEWAY]
94: #define netmask info.rti_info[RTAX_NETMASK]
95: #define genmask info.rti_info[RTAX_GENMASK]
96: #define ifpaddr info.rti_info[RTAX_IFP]
97: #define ifaaddr info.rti_info[RTAX_IFA]
98: #define brdaddr info.rti_info[RTAX_BRD]
99:
100: /*ARGSUSED*/
101: int
102: route_usrreq(so, req, m, nam, control)
103: register struct socket *so;
104: int req;
105: struct mbuf *m, *nam, *control;
106: {
107: register int error = 0;
108: register struct rawcb *rp = sotorawcb(so);
109: int s;
110:
111: if (req == PRU_ATTACH) {
112: MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
113: if (so->so_pcb = (caddr_t)rp)
114: bzero(so->so_pcb, sizeof(*rp));
115:
116: }
117: if (req == PRU_DETACH && rp) {
118: int af = rp->rcb_proto.sp_protocol;
119: if (af == AF_INET)
120: route_cb.ip_count--;
121: else if (af == AF_NS)
122: route_cb.ns_count--;
123: else if (af == AF_ISO)
124: route_cb.iso_count--;
125: route_cb.any_count--;
126: }
127: s = splnet();
128: error = raw_usrreq(so, req, m, nam, control);
129: rp = sotorawcb(so);
130: if (req == PRU_ATTACH && rp) {
131: int af = rp->rcb_proto.sp_protocol;
132: if (error) {
133: _FREE((caddr_t)rp, M_PCB);
134: splx(s);
135: return (error);
136: }
137: if (af == AF_INET)
138: route_cb.ip_count++;
139: else if (af == AF_NS)
140: route_cb.ns_count++;
141: else if (af == AF_ISO)
142: route_cb.iso_count++;
143: rp->rcb_faddr = &route_src;
144: route_cb.any_count++;
145: soisconnected(so);
146: so->so_options |= SO_USELOOPBACK;
147: }
148: splx(s);
149: return (error);
150: }
151:
152: void m_copyback(struct mbuf *, int, int, caddr_t);
153:
154: /*ARGSUSED*/
155: int
156: route_output(m, so)
157: register struct mbuf *m;
158: struct socket *so;
159: {
160: register struct rt_msghdr *rtm = 0;
161: register struct rtentry *rt = 0;
162: struct rtentry *saved_nrt = 0;
163: struct radix_node_head *rnh;
164: struct rt_addrinfo info;
165: int len, error = 0;
166: struct ifnet *ifp = 0;
167: struct ifaddr *ifa = 0;
168:
169: #define senderr(e) { error = e; goto flush;}
170: if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
171: (m = m_pullup(m, sizeof(int32_t))) == 0))
172: return (ENOBUFS);
173: if ((m->m_flags & M_PKTHDR) == 0)
174: panic("route_output");
175: len = m->m_pkthdr.len;
176: if (len < sizeof(*rtm) ||
177: len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
178: dst = 0;
179: senderr(EINVAL);
180: }
181: R_Malloc(rtm, struct rt_msghdr *, len);
182: if (rtm == 0) {
183: dst = 0;
184: senderr(ENOBUFS);
185: }
186: m_copydata(m, 0, len, (caddr_t)rtm);
187: if (rtm->rtm_version != RTM_VERSION) {
188: dst = 0;
189: senderr(EPROTONOSUPPORT);
190: }
191: rtm->rtm_pid = current_proc()->p_pid;
192: info.rti_addrs = rtm->rtm_addrs;
193: rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info);
194: if (dst == 0)
195: senderr(EINVAL);
196: if (genmask) {
197: struct radix_node *t;
198: t = rn_addmask((caddr_t)genmask, 0, 1);
199: if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
200: genmask = (struct sockaddr *)(t->rn_key);
201: else
202: senderr(ENOBUFS);
203: }
204: switch (rtm->rtm_type) {
205:
206: case RTM_ADD:
207: if (gate == 0)
208: senderr(EINVAL);
209: error = rtrequest(RTM_ADD, dst, gate, netmask,
210: rtm->rtm_flags, &saved_nrt);
211: if (error == 0 && saved_nrt) {
212: rt_setmetrics(rtm->rtm_inits,
213: &rtm->rtm_rmx, &saved_nrt->rt_rmx);
214: saved_nrt->rt_refcnt--;
215: saved_nrt->rt_genmask = genmask;
216: }
217: break;
218:
219: case RTM_DELETE:
220: error = rtrequest(RTM_DELETE, dst, gate, netmask,
221: rtm->rtm_flags, &saved_nrt);
222: if (error == 0) {
1.1.1.2 ! root 223: rt = saved_nrt;
! 224: RTHOLD(rt);
1.1 root 225: goto report;
226: }
227: break;
228:
229: case RTM_GET:
230: case RTM_CHANGE:
231: case RTM_LOCK:
232: if ((rnh = rt_tables[dst->sa_family]) == 0) {
233: senderr(EAFNOSUPPORT);
234: } else if (rt = (struct rtentry *)
235: rnh->rnh_lookup(dst, netmask, rnh))
1.1.1.2 ! root 236: RTHOLD(rt)
1.1 root 237: else
238: senderr(ESRCH);
239: switch(rtm->rtm_type) {
240:
241: case RTM_GET:
242: report:
243: dst = rt_key(rt);
244: gate = rt->rt_gateway;
245: netmask = rt_mask(rt);
246: genmask = rt->rt_genmask;
247: if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
248: if (ifp = rt->rt_ifp) {
249: ifpaddr = ifp->if_addrlist->ifa_addr;
250: ifaaddr = rt->rt_ifa->ifa_addr;
251: if (ifp->if_flags & IFF_POINTOPOINT)
252: brdaddr = rt->rt_ifa->ifa_dstaddr;
253: else
254: brdaddr = 0;
255: rtm->rtm_index = ifp->if_index;
256: } else {
257: ifpaddr = 0;
258: ifaaddr = 0;
259: }
260: }
261: len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
262: (struct walkarg *)0);
263: if (len > rtm->rtm_msglen) {
264: struct rt_msghdr *new_rtm;
265: R_Malloc(new_rtm, struct rt_msghdr *, len);
266: if (new_rtm == 0)
267: senderr(ENOBUFS);
268: Bcopy(rtm, new_rtm, rtm->rtm_msglen);
269: Free(rtm); rtm = new_rtm;
270: }
271: (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
272: (struct walkarg *)0);
273: rtm->rtm_flags = rt->rt_flags;
274: rtm->rtm_rmx = rt->rt_rmx;
275: rtm->rtm_addrs = info.rti_addrs;
276: break;
277:
278: case RTM_CHANGE:
279: if (gate && rt_setgate(rt, rt_key(rt), gate))
280: senderr(EDQUOT);
281: /* new gateway could require new ifaddr, ifp;
282: flags may also be different; ifp may be specified
283: by ll sockaddr when protocol address is ambiguous */
284: if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
285: (ifp = ifa->ifa_ifp))
286: ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
287: ifp);
288: else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
289: (ifa = ifa_ifwithroute(rt->rt_flags,
290: rt_key(rt), gate)))
291: ifp = ifa->ifa_ifp;
292: if (ifa) {
293: register struct ifaddr *oifa = rt->rt_ifa;
294: if (oifa != ifa) {
295: if (oifa && oifa->ifa_rtrequest)
296: oifa->ifa_rtrequest(RTM_DELETE,
297: rt, gate);
298: IFAFREE(rt->rt_ifa);
299: rt->rt_ifa = ifa;
1.1.1.2 ! root 300: if (++ifa->ifa_refcnt <= 0)
! 301: panic("route_output ifa_refcnt");
1.1 root 302: rt->rt_ifp = ifp;
303: }
304: }
305: rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
306: &rt->rt_rmx);
307: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
308: rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
309: if (genmask)
310: rt->rt_genmask = genmask;
311: /*
312: * Fall into
313: */
314: case RTM_LOCK:
315: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
316: rt->rt_rmx.rmx_locks |=
317: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
318: break;
319: }
320: break;
321:
322: default:
323: senderr(EOPNOTSUPP);
324: }
325:
326: flush:
327: if (rtm) {
328: if (error)
329: rtm->rtm_errno = error;
330: else
331: rtm->rtm_flags |= RTF_DONE;
332: }
333: if (rt)
334: rtfree(rt);
335: {
336: register struct rawcb *rp = 0;
337: /*
338: * Check to see if we don't want our own messages.
339: */
340: if ((so->so_options & SO_USELOOPBACK) == 0) {
341: if (route_cb.any_count <= 1) {
342: if (rtm)
343: Free(rtm);
344: m_freem(m);
345: return (error);
346: }
347: /* There is another listener, so construct message */
348: rp = sotorawcb(so);
349: }
350: if (rtm) {
351: m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
352: Free(rtm);
353: }
354: if (rp)
355: rp->rcb_proto.sp_family = 0; /* Avoid us */
356: if (dst)
357: route_proto.sp_protocol = dst->sa_family;
358: raw_input(m, &route_proto, &route_src, &route_dst);
359: if (rp)
360: rp->rcb_proto.sp_family = PF_ROUTE;
361: }
362: return (error);
363: }
364:
365: void
366: rt_setmetrics(which, in, out)
367: u_long which;
368: register struct rt_metrics *in, *out;
369: {
370: #define metric(f, e) if (which & (f)) out->e = in->e;
371: metric(RTV_RPIPE, rmx_recvpipe);
372: metric(RTV_SPIPE, rmx_sendpipe);
373: metric(RTV_SSTHRESH, rmx_ssthresh);
374: metric(RTV_RTT, rmx_rtt);
375: metric(RTV_RTTVAR, rmx_rttvar);
376: metric(RTV_HOPCOUNT, rmx_hopcount);
377: metric(RTV_MTU, rmx_mtu);
378: metric(RTV_EXPIRE, rmx_expire);
379: #undef metric
380: }
381:
382: #define ROUNDUP(a) \
383: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
384: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
385:
386: static void
387: rt_xaddrs(cp, cplim, rtinfo)
388: register caddr_t cp, cplim;
389: register struct rt_addrinfo *rtinfo;
390: {
391: register struct sockaddr *sa;
392: register int i;
393:
394: bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
395: for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
396: if ((rtinfo->rti_addrs & (1 << i)) == 0)
397: continue;
398: rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
399: ADVANCE(cp, sa);
400: }
401: }
402:
403: /*
404: * Copy data from a buffer back into the indicated mbuf chain,
405: * starting "off" bytes from the beginning, extending the mbuf
406: * chain if necessary.
407: */
408: void
409: m_copyback(m0, off, len, cp)
410: struct mbuf *m0;
411: register int off;
412: register int len;
413: caddr_t cp;
414: {
415: register int mlen;
416: register struct mbuf *m = m0, *n;
417: int totlen = 0;
418:
419: if (m0 == 0)
420: return;
421: while (off > (mlen = m->m_len)) {
422: off -= mlen;
423: totlen += mlen;
424: if (m->m_next == 0) {
425: n = m_getclr(M_DONTWAIT, m->m_type);
426: if (n == 0)
427: goto out;
428: n->m_len = min(MLEN, len + off);
429: m->m_next = n;
430: }
431: m = m->m_next;
432: }
433: while (len > 0) {
434: mlen = min (m->m_len - off, len);
435: bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
436: cp += mlen;
437: len -= mlen;
438: mlen += off;
439: off = 0;
440: totlen += mlen;
441: if (len == 0)
442: break;
443: if (m->m_next == 0) {
444: n = m_get(M_DONTWAIT, m->m_type);
445: if (n == 0)
446: break;
447: n->m_len = min(MLEN, len);
448: m->m_next = n;
449: }
450: m = m->m_next;
451: }
452: out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
453: m->m_pkthdr.len = totlen;
454: }
455:
456: static struct mbuf *
457: rt_msg1(type, rtinfo)
458: int type;
459: register struct rt_addrinfo *rtinfo;
460: {
461: register struct rt_msghdr *rtm;
462: register struct mbuf *m;
463: register int i;
464: register struct sockaddr *sa;
465: int len, dlen;
466:
467: m = m_gethdr(M_DONTWAIT, MT_DATA);
468: if (m == 0)
469: return (m);
470: switch (type) {
471:
472: case RTM_DELADDR:
473: case RTM_NEWADDR:
474: len = sizeof(struct ifa_msghdr);
475: break;
476:
477: case RTM_IFINFO:
478: len = sizeof(struct if_msghdr);
479: break;
480:
481: default:
482: len = sizeof(struct rt_msghdr);
483: }
484: if (len > MHLEN)
485: panic("rt_msg1");
486: m->m_pkthdr.len = m->m_len = len;
487: m->m_pkthdr.rcvif = 0;
488: rtm = mtod(m, struct rt_msghdr *);
489: bzero((caddr_t)rtm, len);
490: for (i = 0; i < RTAX_MAX; i++) {
491: if ((sa = rtinfo->rti_info[i]) == NULL)
492: continue;
493: rtinfo->rti_addrs |= (1 << i);
494: dlen = ROUNDUP(sa->sa_len);
495: m_copyback(m, len, dlen, (caddr_t)sa);
496: len += dlen;
497: }
498: if (m->m_pkthdr.len != len) {
499: m_freem(m);
500: return (NULL);
501: }
502: rtm->rtm_msglen = len;
503: rtm->rtm_version = RTM_VERSION;
504: rtm->rtm_type = type;
505: return (m);
506: }
507:
508: static int
509: rt_msg2(type, rtinfo, cp, w)
510: int type;
511: register struct rt_addrinfo *rtinfo;
512: caddr_t cp;
513: struct walkarg *w;
514: {
515: register int i;
516: int len, dlen, second_time = 0;
517: caddr_t cp0;
518:
519: rtinfo->rti_addrs = 0;
520: again:
521: switch (type) {
522:
523: case RTM_DELADDR:
524: case RTM_NEWADDR:
525: len = sizeof(struct ifa_msghdr);
526: break;
527:
528: case RTM_IFINFO:
529: len = sizeof(struct if_msghdr);
530: break;
531:
532: default:
533: len = sizeof(struct rt_msghdr);
534: }
535: if (cp0 = cp)
536: cp += len;
537: for (i = 0; i < RTAX_MAX; i++) {
538: register struct sockaddr *sa;
539:
540: if ((sa = rtinfo->rti_info[i]) == 0)
541: continue;
542: rtinfo->rti_addrs |= (1 << i);
543: dlen = ROUNDUP(sa->sa_len);
544: if (cp) {
545: bcopy((caddr_t)sa, cp, (unsigned)dlen);
546: cp += dlen;
547: }
548: len += dlen;
549: }
550: if (cp == 0 && w != NULL && !second_time) {
551: register struct walkarg *rw = w;
552:
553: rw->w_needed += len;
554: if (rw->w_needed <= 0 && rw->w_where) {
555: if (rw->w_tmemsize < len) {
556: if (rw->w_tmem)
557: _FREE(rw->w_tmem, M_RTABLE);
558: if (rw->w_tmem = (caddr_t)
559: _MALLOC(len, M_RTABLE, M_NOWAIT))
560: rw->w_tmemsize = len;
561: }
562: if (rw->w_tmem) {
563: cp = rw->w_tmem;
564: second_time = 1;
565: goto again;
566: } else
567: rw->w_where = 0;
568: }
569: }
570: if (cp) {
571: register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
572:
573: rtm->rtm_version = RTM_VERSION;
574: rtm->rtm_type = type;
575: rtm->rtm_msglen = len;
576: }
577: return (len);
578: }
579:
580: /*
581: * This routine is called to generate a message from the routing
582: * socket indicating that a redirect has occured, a routing lookup
583: * has failed, or that a protocol has detected timeouts to a particular
584: * destination.
585: */
586: void
587: rt_missmsg(type, rtinfo, flags, error)
588: int type, flags, error;
589: register struct rt_addrinfo *rtinfo;
590: {
591: register struct rt_msghdr *rtm;
592: register struct mbuf *m;
593: struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
594:
595: if (route_cb.any_count == 0)
596: return;
597: m = rt_msg1(type, rtinfo);
598: if (m == 0)
599: return;
600: rtm = mtod(m, struct rt_msghdr *);
601: rtm->rtm_flags = RTF_DONE | flags;
602: rtm->rtm_errno = error;
603: rtm->rtm_addrs = rtinfo->rti_addrs;
604: route_proto.sp_protocol = sa ? sa->sa_family : 0;
605: raw_input(m, &route_proto, &route_src, &route_dst);
606: }
607:
608: /*
609: * This routine is called to generate a message from the routing
610: * socket indicating that the status of a network interface has changed.
611: */
612: void
613: rt_ifmsg(ifp)
614: register struct ifnet *ifp;
615: {
616: register struct if_msghdr *ifm;
617: struct mbuf *m;
618: struct rt_addrinfo info;
619:
620: if (route_cb.any_count == 0)
621: return;
622: bzero((caddr_t)&info, sizeof(info));
623: m = rt_msg1(RTM_IFINFO, &info);
624: if (m == 0)
625: return;
626: ifm = mtod(m, struct if_msghdr *);
627: ifm->ifm_index = ifp->if_index;
628: ifm->ifm_flags = ifp->if_flags;
629: ifm->ifm_data = ifp->if_data;
630: ifm->ifm_addrs = 0;
631: route_proto.sp_protocol = 0;
632: raw_input(m, &route_proto, &route_src, &route_dst);
633: }
634:
635: /*
636: * This is called to generate messages from the routing socket
637: * indicating a network interface has had addresses associated with it.
638: * if we ever reverse the logic and replace messages TO the routing
639: * socket indicate a request to configure interfaces, then it will
640: * be unnecessary as the routing socket will automatically generate
641: * copies of it.
642: */
643: void
644: rt_newaddrmsg(cmd, ifa, error, rt)
645: int cmd, error;
646: register struct ifaddr *ifa;
647: register struct rtentry *rt;
648: {
649: struct rt_addrinfo info;
650: struct sockaddr *sa;
651: int pass;
652: struct mbuf *m;
653: struct ifnet *ifp = ifa->ifa_ifp;
654:
655: if (route_cb.any_count == 0)
656: return;
657: for (pass = 1; pass < 3; pass++) {
658: bzero((caddr_t)&info, sizeof(info));
659: if ((cmd == RTM_ADD && pass == 1) ||
660: (cmd == RTM_DELETE && pass == 2)) {
661: register struct ifa_msghdr *ifam;
662: int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
663:
664: ifaaddr = sa = ifa->ifa_addr;
665: ifpaddr = ifp->if_addrlist->ifa_addr;
666: netmask = ifa->ifa_netmask;
667: brdaddr = ifa->ifa_dstaddr;
668: if ((m = rt_msg1(ncmd, &info)) == NULL)
669: continue;
670: ifam = mtod(m, struct ifa_msghdr *);
671: ifam->ifam_index = ifp->if_index;
672: ifam->ifam_metric = ifa->ifa_metric;
673: ifam->ifam_flags = ifa->ifa_flags;
674: ifam->ifam_addrs = info.rti_addrs;
675: }
676: if ((cmd == RTM_ADD && pass == 2) ||
677: (cmd == RTM_DELETE && pass == 1)) {
678: register struct rt_msghdr *rtm;
679:
680: if (rt == 0)
681: continue;
682: netmask = rt_mask(rt);
683: dst = sa = rt_key(rt);
684: gate = rt->rt_gateway;
685: if ((m = rt_msg1(cmd, &info)) == NULL)
686: continue;
687: rtm = mtod(m, struct rt_msghdr *);
688: rtm->rtm_index = ifp->if_index;
689: rtm->rtm_flags |= rt->rt_flags;
690: rtm->rtm_errno = error;
691: rtm->rtm_addrs = info.rti_addrs;
692: }
693: route_proto.sp_protocol = sa ? sa->sa_family : 0;
694: raw_input(m, &route_proto, &route_src, &route_dst);
695: }
696: }
697:
698: /*
699: * This is used in dumping the kernel table via sysctl().
700: */
701: int
702: sysctl_dumpentry(rn, w)
703: struct radix_node *rn;
704: register struct walkarg *w;
705: {
706: register struct rtentry *rt = (struct rtentry *)rn;
707: int error = 0, size;
708: struct rt_addrinfo info;
709:
710: if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
711: return 0;
712: bzero((caddr_t)&info, sizeof(info));
713: dst = rt_key(rt);
714: gate = rt->rt_gateway;
715: netmask = rt_mask(rt);
716: genmask = rt->rt_genmask;
717: if (rt->rt_ifp) {
718: ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr;
719: ifaaddr = rt->rt_ifa->ifa_addr;
720: if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
721: brdaddr = rt->rt_ifa->ifa_dstaddr;
722: }
723: size = rt_msg2(RTM_GET, &info, 0, w);
724: if (w->w_where && w->w_tmem) {
725: register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
726:
727: rtm->rtm_flags = rt->rt_flags;
728: rtm->rtm_use = rt->rt_use;
729: rtm->rtm_rmx = rt->rt_rmx;
730: rtm->rtm_index = rt->rt_ifp->if_index;
731: rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
732: rtm->rtm_addrs = info.rti_addrs;
733: if (error = copyout((caddr_t)rtm, w->w_where, size))
734: w->w_where = NULL;
735: else
736: w->w_where += size;
737: }
738: return (error);
739: }
740:
741: int
742: sysctl_iflist(af, w)
743: int af;
744: register struct walkarg *w;
745: {
746: register struct ifnet *ifp;
747: register struct ifaddr *ifa;
748: struct rt_addrinfo info;
749: int len, error = 0;
750:
751: bzero((caddr_t)&info, sizeof(info));
752: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
753: if (w->w_arg && w->w_arg != ifp->if_index)
754: continue;
755: ifa = ifp->if_addrlist;
756: ifpaddr = ifa->ifa_addr;
757: len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
758: ifpaddr = 0;
759: if (w->w_where && w->w_tmem) {
760: register struct if_msghdr *ifm;
761:
762: ifm = (struct if_msghdr *)w->w_tmem;
763: ifm->ifm_index = ifp->if_index;
764: ifm->ifm_flags = ifp->if_flags;
765: ifm->ifm_data = ifp->if_data;
766: ifm->ifm_addrs = info.rti_addrs;
767: if (error = copyout((caddr_t)ifm, w->w_where, len))
768: return (error);
769: w->w_where += len;
770: }
771: while (ifa = ifa->ifa_next) {
772: if (af && af != ifa->ifa_addr->sa_family)
773: continue;
774: ifaaddr = ifa->ifa_addr;
775: netmask = ifa->ifa_netmask;
776: brdaddr = ifa->ifa_dstaddr;
777: len = rt_msg2(RTM_NEWADDR, &info, 0, w);
778: if (w->w_where && w->w_tmem) {
779: register struct ifa_msghdr *ifam;
780:
781: ifam = (struct ifa_msghdr *)w->w_tmem;
782: ifam->ifam_index = ifa->ifa_ifp->if_index;
783: ifam->ifam_flags = ifa->ifa_flags;
784: ifam->ifam_metric = ifa->ifa_metric;
785: ifam->ifam_addrs = info.rti_addrs;
786: if (error = copyout(w->w_tmem, w->w_where, len))
787: return (error);
788: w->w_where += len;
789: }
790: }
791: ifaaddr = netmask = brdaddr = 0;
792: }
793: return (0);
794: }
795:
796: int
797: sysctl_rtable(name, namelen, where, given, new, newlen)
798: int *name;
799: int namelen;
800: caddr_t where;
801: size_t *given;
802: caddr_t *new;
803: size_t newlen;
804: {
805: register struct radix_node_head *rnh;
806: int i, s, error = EINVAL;
807: u_char af;
808: struct walkarg w;
809:
810: if (new)
811: return (EPERM);
812: if (namelen != 3)
813: return (EINVAL);
814: af = name[0];
815: Bzero(&w, sizeof(w));
816: w.w_where = where;
817: w.w_given = *given;
818: w.w_needed = 0 - w.w_given;
819: w.w_op = name[1];
820: w.w_arg = name[2];
821:
822: s = splnet();
823: switch (w.w_op) {
824:
825: case NET_RT_DUMP:
826: case NET_RT_FLAGS:
827: for (i = 1; i <= AF_MAX; i++)
828: if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
829: (error = rnh->rnh_walktree(rnh,
830: sysctl_dumpentry, &w)))
831: break;
832: break;
833:
834: case NET_RT_IFLIST:
835: error = sysctl_iflist(af, &w);
836: }
837: splx(s);
838: if (w.w_tmem)
839: _FREE(w.w_tmem, M_RTABLE);
840: w.w_needed += w.w_given;
841: if (where) {
842: *given = w.w_where - where;
843: if (*given < w.w_needed)
844: return (ENOMEM);
845: } else {
846: *given = (11 * w.w_needed) / 10;
847: }
848: return (error);
849: }
850:
851: /*
852: * Definitions of protocols supported in the ROUTE domain.
853: */
854:
855: extern struct domain routedomain; /* or at least forward */
856:
857: struct protosw routesw[] = {
858: { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
859: raw_input, route_output, raw_ctlinput, 0,
860: route_usrreq,
861: raw_init, 0, 0, 0,
862: sysctl_rtable,
863: }
864: };
865:
866: struct domain routedomain =
867: { PF_ROUTE, "route", route_init, 0, 0,
868: 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.