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