|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1988, 1991, 1993
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)rtsock.c 8.5 (Berkeley) 11/2/94
55: */
56:
57:
58: #include <sys/param.h>
59: #include <sys/systm.h>
60: #include <sys/kernel.h>
61: #include <sys/sysctl.h>
62: #include <sys/proc.h>
63: #include <sys/malloc.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:
70: #include <net/if.h>
71: #include <net/route.h>
72: #include <net/raw_cb.h>
73:
74: MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
75:
76: static struct sockaddr route_dst = { 2, PF_ROUTE, };
77: static struct sockaddr route_src = { 2, PF_ROUTE, };
78: static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
79: static struct sockproto route_proto = { PF_ROUTE, };
80:
81:
82:
83: struct walkarg {
84: int w_tmemsize;
85: int w_op, w_arg;
86: caddr_t w_tmem;
87: struct sysctl_req *w_req;
88: };
89:
90: static struct mbuf *
91: rt_msg1 __P((int, struct rt_addrinfo *));
92: static int rt_msg2 __P((int,
93: struct rt_addrinfo *, caddr_t, struct walkarg *));
94: static int rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
95: static int sysctl_dumpentry __P((struct radix_node *rn, void *vw));
96: static int sysctl_iflist __P((int af, struct walkarg *w));
97: static int route_output __P((struct mbuf *, struct socket *));
98: static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
99:
100: /* Sleazy use of local variables throughout file, warning!!!! */
101: #define dst info.rti_info[RTAX_DST]
102: #define gate info.rti_info[RTAX_GATEWAY]
103: #define netmask info.rti_info[RTAX_NETMASK]
104: #define genmask info.rti_info[RTAX_GENMASK]
105: #define ifpaddr info.rti_info[RTAX_IFP]
106: #define ifaaddr info.rti_info[RTAX_IFA]
107: #define brdaddr info.rti_info[RTAX_BRD]
108:
109: /*
110: * It really doesn't make any sense at all for this code to share much
111: * with raw_usrreq.c, since its functionality is so restricted. XXX
112: */
113: static int
114: rts_abort(struct socket *so)
115: {
116: int s, error;
117: s = splnet();
118: error = raw_usrreqs.pru_abort(so);
119: splx(s);
120: return error;
121: }
122:
123: /* pru_accept is EOPNOTSUPP */
124:
125: static int
126: rts_attach(struct socket *so, int proto, struct proc *p)
127: {
128: struct rawcb *rp;
129: int s, error;
130:
131: if (sotorawcb(so) != 0)
132: return EISCONN; /* XXX panic? */
133: MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */
134: if (rp == 0)
135: return ENOBUFS;
136: bzero(rp, sizeof *rp);
137:
138: /*
139: * The splnet() is necessary to block protocols from sending
140: * error notifications (like RTM_REDIRECT or RTM_LOSING) while
141: * this PCB is extant but incompletely initialized.
142: * Probably we should try to do more of this work beforehand and
143: * eliminate the spl.
144: */
145: s = splnet();
146: so->so_pcb = (caddr_t)rp;
147: error = raw_usrreqs.pru_attach(so, proto, p);
148: rp = sotorawcb(so);
149: if (error) {
150: splx(s);
151: FREE(rp, M_PCB);
152: return error;
153: }
154: switch(rp->rcb_proto.sp_protocol) {
155: case AF_INET:
156: route_cb.ip_count++;
157: break;
158: case AF_IPX:
159: route_cb.ipx_count++;
160: break;
161: case AF_NS:
162: route_cb.ns_count++;
163: break;
164: case AF_ISO:
165: route_cb.iso_count++;
166: break;
167: }
168: rp->rcb_faddr = &route_src;
169: route_cb.any_count++;
170: soisconnected(so);
171: so->so_options |= SO_USELOOPBACK;
172: splx(s);
173: return 0;
174: }
175:
176: static int
177: rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
178: {
179: int s, error;
180: s = splnet();
181: error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
182: splx(s);
183: return error;
184: }
185:
186: static int
187: rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
188: {
189: int s, error;
190: s = splnet();
191: error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
192: splx(s);
193: return error;
194: }
195:
196: /* pru_connect2 is EOPNOTSUPP */
197: /* pru_control is EOPNOTSUPP */
198:
199: static int
200: rts_detach(struct socket *so)
201: {
202: struct rawcb *rp = sotorawcb(so);
203: int s, error;
204:
205: s = splnet();
206: if (rp != 0) {
207: switch(rp->rcb_proto.sp_protocol) {
208: case AF_INET:
209: route_cb.ip_count--;
210: break;
211: case AF_IPX:
212: route_cb.ipx_count--;
213: break;
214: case AF_NS:
215: route_cb.ns_count--;
216: break;
217: case AF_ISO:
218: route_cb.iso_count--;
219: break;
220: }
221: route_cb.any_count--;
222: }
223: error = raw_usrreqs.pru_detach(so);
224: splx(s);
225: return error;
226: }
227:
228: static int
229: rts_disconnect(struct socket *so)
230: {
231: int s, error;
232: s = splnet();
233: error = raw_usrreqs.pru_disconnect(so);
234: splx(s);
235: return error;
236: }
237:
238: /* pru_listen is EOPNOTSUPP */
239:
240: static int
241: rts_peeraddr(struct socket *so, struct sockaddr **nam)
242: {
243: int s, error;
244: s = splnet();
245: error = raw_usrreqs.pru_peeraddr(so, nam);
246: splx(s);
247: return error;
248: }
249:
250: /* pru_rcvd is EOPNOTSUPP */
251: /* pru_rcvoob is EOPNOTSUPP */
252:
253: static int
254: rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
255: struct mbuf *control, struct proc *p)
256: {
257: int s, error;
258: s = splnet();
259: error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
260: splx(s);
261: return error;
262: }
263:
264: /* pru_sense is null */
265:
266: static int
267: rts_shutdown(struct socket *so)
268: {
269: int s, error;
270: s = splnet();
271: error = raw_usrreqs.pru_shutdown(so);
272: splx(s);
273: return error;
274: }
275:
276: static int
277: rts_sockaddr(struct socket *so, struct sockaddr **nam)
278: {
279: int s, error;
280: s = splnet();
281: error = raw_usrreqs.pru_sockaddr(so, nam);
282: splx(s);
283: return error;
284: }
285:
286: static struct pr_usrreqs route_usrreqs = {
287: rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
288: pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
289: pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
290: rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
291: sosend, soreceive, sopoll
292: };
293:
294: /*ARGSUSED*/
295: static int
296: route_output(m, so)
297: register struct mbuf *m;
298: struct socket *so;
299: {
300: register struct rt_msghdr *rtm = 0;
301: register struct rtentry *rt = 0;
302: struct rtentry *saved_nrt = 0;
303: struct radix_node_head *rnh;
304: struct rt_addrinfo info;
305: int len, error = 0;
306: struct ifnet *ifp = 0;
307: struct ifaddr *ifa = 0;
308: struct proc *curproc = current_proc();
309:
310: #define senderr(e) { error = e; goto flush;}
311: if (m == 0 || ((m->m_len < sizeof(long)) &&
312: (m = m_pullup(m, sizeof(long))) == 0))
313: return (ENOBUFS);
314: if ((m->m_flags & M_PKTHDR) == 0)
315: panic("route_output");
316: len = m->m_pkthdr.len;
317: if (len < sizeof(*rtm) ||
318: len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
319: dst = 0;
320: senderr(EINVAL);
321: }
322: R_Malloc(rtm, struct rt_msghdr *, len);
323: if (rtm == 0) {
324: dst = 0;
325: senderr(ENOBUFS);
326: }
327: m_copydata(m, 0, len, (caddr_t)rtm);
328: if (rtm->rtm_version != RTM_VERSION) {
329: dst = 0;
330: senderr(EPROTONOSUPPORT);
331: }
332: rtm->rtm_pid = curproc->p_pid;
333: info.rti_addrs = rtm->rtm_addrs;
334: if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
335: dst = 0;
336: senderr(EINVAL);
337: }
338: if (dst == 0 || (dst->sa_family >= AF_MAX)
339: || (gate != 0 && (gate->sa_family >= AF_MAX)))
340: senderr(EINVAL);
341: if (genmask) {
342: struct radix_node *t;
343: t = rn_addmask((caddr_t)genmask, 0, 1);
344: if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
345: genmask = (struct sockaddr *)(t->rn_key);
346: else
347: senderr(ENOBUFS);
348: }
349: switch (rtm->rtm_type) {
350:
351: case RTM_ADD:
352: if (gate == 0)
353: senderr(EINVAL);
354: error = rtrequest(RTM_ADD, dst, gate, netmask,
355: rtm->rtm_flags, &saved_nrt);
356: if (error == 0 && saved_nrt) {
357: rt_setmetrics(rtm->rtm_inits,
358: &rtm->rtm_rmx, &saved_nrt->rt_rmx);
359: saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
360: saved_nrt->rt_rmx.rmx_locks |=
361: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
362: saved_nrt->rt_refcnt--;
363: saved_nrt->rt_genmask = genmask;
364: }
365: break;
366:
367: case RTM_DELETE:
368: error = rtrequest(RTM_DELETE, dst, gate, netmask,
369: rtm->rtm_flags, &saved_nrt);
370: if (error == 0) {
371: if ((rt = saved_nrt))
372: rt->rt_refcnt++;
373: goto report;
374: }
375: break;
376:
377: case RTM_GET:
378: case RTM_CHANGE:
379: case RTM_LOCK:
380: if ((rnh = rt_tables[dst->sa_family]) == 0) {
381: senderr(EAFNOSUPPORT);
382: } else if (rt = (struct rtentry *)
383: rnh->rnh_lookup(dst, netmask, rnh))
384: rt->rt_refcnt++;
385: else
386: senderr(ESRCH);
387: switch(rtm->rtm_type) {
388:
389: case RTM_GET:
390: report:
391: dst = rt_key(rt);
392: gate = rt->rt_gateway;
393: netmask = rt_mask(rt);
394: genmask = rt->rt_genmask;
395: if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
396: ifp = rt->rt_ifp;
397: if (ifp) {
398: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
399: ifaaddr = rt->rt_ifa->ifa_addr;
400: rtm->rtm_index = ifp->if_index;
401: } else {
402: ifpaddr = 0;
403: ifaaddr = 0;
404: }
405: }
406: len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
407: (struct walkarg *)0);
408: if (len > rtm->rtm_msglen) {
409: struct rt_msghdr *new_rtm;
410: R_Malloc(new_rtm, struct rt_msghdr *, len);
411: if (new_rtm == 0)
412: senderr(ENOBUFS);
413: Bcopy(rtm, new_rtm, rtm->rtm_msglen);
414: Free(rtm); rtm = new_rtm;
415: }
416: (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
417: (struct walkarg *)0);
418: rtm->rtm_flags = rt->rt_flags;
419: rtm->rtm_rmx = rt->rt_rmx;
420: rtm->rtm_addrs = info.rti_addrs;
421: break;
422:
423: case RTM_CHANGE:
424: if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
425: senderr(error);
426:
427: /*
428: * If they tried to change things but didn't specify
429: * the required gateway, then just use the old one.
430: * This can happen if the user tries to change the
431: * flags on the default route without changing the
432: * default gateway. Changing flags still doesn't work.
433: */
434: if ((rt->rt_flags & RTF_GATEWAY) && !gate)
435: gate = rt->rt_gateway;
436:
437: /* new gateway could require new ifaddr, ifp;
438: flags may also be different; ifp may be specified
439: by ll sockaddr when protocol address is ambiguous */
440: if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
441: (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
442: ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
443: ifp);
444: else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
445: (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
446: rt_key(rt), gate))))
447: ifp = ifa->ifa_ifp;
448: if (ifa) {
449: register struct ifaddr *oifa = rt->rt_ifa;
450: if (oifa != ifa) {
451: if (oifa && oifa->ifa_rtrequest)
452: oifa->ifa_rtrequest(RTM_DELETE,
453: rt, gate);
454: IFAFREE(rt->rt_ifa);
455: rt->rt_ifa = ifa;
456: ifa->ifa_refcnt++;
457: rt->rt_ifp = ifp;
458: rt->rt_dlt = ifa->ifa_dlt;
459: }
460: }
461: rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
462: &rt->rt_rmx);
463: if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
464: rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
465: if (genmask)
466: rt->rt_genmask = genmask;
467: /*
468: * Fall into
469: */
470: case RTM_LOCK:
471: rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
472: rt->rt_rmx.rmx_locks |=
473: (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
474: break;
475: }
476: break;
477:
478: default:
479: senderr(EOPNOTSUPP);
480: }
481:
482: flush:
483: if (rtm) {
484: if (error)
485: rtm->rtm_errno = error;
486: else
487: rtm->rtm_flags |= RTF_DONE;
488: }
489: if (rt)
490: rtfree(rt);
491: {
492: register struct rawcb *rp = 0;
493: /*
494: * Check to see if we don't want our own messages.
495: */
496: if ((so->so_options & SO_USELOOPBACK) == 0) {
497: if (route_cb.any_count <= 1) {
498: if (rtm)
499: Free(rtm);
500: m_freem(m);
501: return (error);
502: }
503: /* There is another listener, so construct message */
504: rp = sotorawcb(so);
505: }
506: if (rtm) {
507: m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
508: Free(rtm);
509: }
510: if (rp)
511: rp->rcb_proto.sp_family = 0; /* Avoid us */
512: if (dst)
513: route_proto.sp_protocol = dst->sa_family;
514: raw_input(m, &route_proto, &route_src, &route_dst);
515: if (rp)
516: rp->rcb_proto.sp_family = PF_ROUTE;
517: }
518: return (error);
519: }
520:
521: static void
522: rt_setmetrics(which, in, out)
523: u_long which;
524: register struct rt_metrics *in, *out;
525: {
526: #define metric(f, e) if (which & (f)) out->e = in->e;
527: metric(RTV_RPIPE, rmx_recvpipe);
528: metric(RTV_SPIPE, rmx_sendpipe);
529: metric(RTV_SSTHRESH, rmx_ssthresh);
530: metric(RTV_RTT, rmx_rtt);
531: metric(RTV_RTTVAR, rmx_rttvar);
532: metric(RTV_HOPCOUNT, rmx_hopcount);
533: metric(RTV_MTU, rmx_mtu);
534: metric(RTV_EXPIRE, rmx_expire);
535: #undef metric
536: }
537:
538: #define ROUNDUP(a) \
539: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
540: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
541:
542:
543: /*
544: * Extract the addresses of the passed sockaddrs.
545: * Do a little sanity checking so as to avoid bad memory references.
546: * This data is derived straight from userland.
547: */
548: static int
549: rt_xaddrs(cp, cplim, rtinfo)
550: register caddr_t cp, cplim;
551: register struct rt_addrinfo *rtinfo;
552: {
553: register struct sockaddr *sa;
554: register int i;
555:
556: bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
557: for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
558: if ((rtinfo->rti_addrs & (1 << i)) == 0)
559: continue;
560: sa = (struct sockaddr *)cp;
561: /*
562: * It won't fit.
563: */
564: if ( (cp + sa->sa_len) > cplim ) {
565: return (EINVAL);
566: }
567:
568: /*
569: * there are no more.. quit now
570: * If there are more bits, they are in error.
571: * I've seen this. route(1) can evidently generate these.
572: * This causes kernel to core dump.
573: * for compatibility, If we see this, point to a safe address.
574: */
575: if (sa->sa_len == 0) {
576: rtinfo->rti_info[i] = &sa_zero;
577: return (0); /* should be EINVAL but for compat */
578: }
579:
580: /* accept it */
581: rtinfo->rti_info[i] = sa;
582: ADVANCE(cp, sa);
583: }
584: return (0);
585: }
586:
587: static struct mbuf *
588: rt_msg1(type, rtinfo)
589: int type;
590: register struct rt_addrinfo *rtinfo;
591: {
592: register struct rt_msghdr *rtm;
593: register struct mbuf *m;
594: register int i;
595: register struct sockaddr *sa;
596: int len, dlen;
597:
598: m = m_gethdr(M_DONTWAIT, MT_DATA);
599: if (m == 0)
600: return (m);
601: switch (type) {
602:
603: case RTM_DELADDR:
604: case RTM_NEWADDR:
605: len = sizeof(struct ifa_msghdr);
606: break;
607:
608: case RTM_DELMADDR:
609: case RTM_NEWMADDR:
610: len = sizeof(struct ifma_msghdr);
611: break;
612:
613: case RTM_IFINFO:
614: len = sizeof(struct if_msghdr);
615: break;
616:
617: default:
618: len = sizeof(struct rt_msghdr);
619: }
620: if (len > MHLEN)
621: panic("rt_msg1");
622: m->m_pkthdr.len = m->m_len = len;
623: m->m_pkthdr.rcvif = 0;
624: rtm = mtod(m, struct rt_msghdr *);
625: bzero((caddr_t)rtm, len);
626: for (i = 0; i < RTAX_MAX; i++) {
627: if ((sa = rtinfo->rti_info[i]) == NULL)
628: continue;
629: rtinfo->rti_addrs |= (1 << i);
630: dlen = ROUNDUP(sa->sa_len);
631: m_copyback(m, len, dlen, (caddr_t)sa);
632: len += dlen;
633: }
634: if (m->m_pkthdr.len != len) {
635: m_freem(m);
636: return (NULL);
637: }
638: rtm->rtm_msglen = len;
639: rtm->rtm_version = RTM_VERSION;
640: rtm->rtm_type = type;
641: return (m);
642: }
643:
644: static int
645: rt_msg2(type, rtinfo, cp, w)
646: int type;
647: register struct rt_addrinfo *rtinfo;
648: caddr_t cp;
649: struct walkarg *w;
650: {
651: register int i;
652: int len, dlen, second_time = 0;
653: caddr_t cp0;
654:
655: rtinfo->rti_addrs = 0;
656: again:
657: switch (type) {
658:
659: case RTM_DELADDR:
660: case RTM_NEWADDR:
661: len = sizeof(struct ifa_msghdr);
662: break;
663:
664: case RTM_IFINFO:
665: len = sizeof(struct if_msghdr);
666: break;
667:
668: default:
669: len = sizeof(struct rt_msghdr);
670: }
671: cp0 = cp;
672: if (cp0)
673: cp += len;
674: for (i = 0; i < RTAX_MAX; i++) {
675: register struct sockaddr *sa;
676:
677: if ((sa = rtinfo->rti_info[i]) == 0)
678: continue;
679: rtinfo->rti_addrs |= (1 << i);
680: dlen = ROUNDUP(sa->sa_len);
681: if (cp) {
682: bcopy((caddr_t)sa, cp, (unsigned)dlen);
683: cp += dlen;
684: }
685: len += dlen;
686: }
687: if (cp == 0 && w != NULL && !second_time) {
688: register struct walkarg *rw = w;
689:
690: if (rw->w_req) {
691: if (rw->w_tmemsize < len) {
692: if (rw->w_tmem)
693: FREE(rw->w_tmem, M_RTABLE);
694: rw->w_tmem = (caddr_t)
695: _MALLOC(len, M_RTABLE, M_NOWAIT);
696: if (rw->w_tmem)
697: rw->w_tmemsize = len;
698: }
699: if (rw->w_tmem) {
700: cp = rw->w_tmem;
701: second_time = 1;
702: goto again;
703: }
704: }
705: }
706: if (cp) {
707: register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
708:
709: rtm->rtm_version = RTM_VERSION;
710: rtm->rtm_type = type;
711: rtm->rtm_msglen = len;
712: }
713: return (len);
714: }
715:
716: /*
717: * This routine is called to generate a message from the routing
718: * socket indicating that a redirect has occured, a routing lookup
719: * has failed, or that a protocol has detected timeouts to a particular
720: * destination.
721: */
722: void
723: rt_missmsg(type, rtinfo, flags, error)
724: int type, flags, error;
725: register struct rt_addrinfo *rtinfo;
726: {
727: register struct rt_msghdr *rtm;
728: register struct mbuf *m;
729: struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
730:
731: if (route_cb.any_count == 0)
732: return;
733: m = rt_msg1(type, rtinfo);
734: if (m == 0)
735: return;
736: rtm = mtod(m, struct rt_msghdr *);
737: rtm->rtm_flags = RTF_DONE | flags;
738: rtm->rtm_errno = error;
739: rtm->rtm_addrs = rtinfo->rti_addrs;
740: route_proto.sp_protocol = sa ? sa->sa_family : 0;
741: raw_input(m, &route_proto, &route_src, &route_dst);
742: }
743:
744: /*
745: * This routine is called to generate a message from the routing
746: * socket indicating that the status of a network interface has changed.
747: */
748: void
749: rt_ifmsg(ifp)
750: register struct ifnet *ifp;
751: {
752: register struct if_msghdr *ifm;
753: struct mbuf *m;
754: struct rt_addrinfo info;
755:
756: if (route_cb.any_count == 0)
757: return;
758: bzero((caddr_t)&info, sizeof(info));
759: m = rt_msg1(RTM_IFINFO, &info);
760: if (m == 0)
761: return;
762: ifm = mtod(m, struct if_msghdr *);
763: ifm->ifm_index = ifp->if_index;
764: ifm->ifm_flags = (u_short)ifp->if_flags;
765: ifm->ifm_data = ifp->if_data;
766: ifm->ifm_addrs = 0;
767: route_proto.sp_protocol = 0;
768: raw_input(m, &route_proto, &route_src, &route_dst);
769: }
770:
771: /*
772: * This is called to generate messages from the routing socket
773: * indicating a network interface has had addresses associated with it.
774: * if we ever reverse the logic and replace messages TO the routing
775: * socket indicate a request to configure interfaces, then it will
776: * be unnecessary as the routing socket will automatically generate
777: * copies of it.
778: */
779: void
780: rt_newaddrmsg(cmd, ifa, error, rt)
781: int cmd, error;
782: register struct ifaddr *ifa;
783: register struct rtentry *rt;
784: {
785: struct rt_addrinfo info;
786: struct sockaddr *sa = 0;
787: int pass;
788: struct mbuf *m = 0;
789: struct ifnet *ifp = ifa->ifa_ifp;
790:
791: if (route_cb.any_count == 0)
792: return;
793: for (pass = 1; pass < 3; pass++) {
794: bzero((caddr_t)&info, sizeof(info));
795: if ((cmd == RTM_ADD && pass == 1) ||
796: (cmd == RTM_DELETE && pass == 2)) {
797: register struct ifa_msghdr *ifam;
798: int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
799:
800: ifaaddr = sa = ifa->ifa_addr;
801: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
802: netmask = ifa->ifa_netmask;
803: brdaddr = ifa->ifa_dstaddr;
804: if ((m = rt_msg1(ncmd, &info)) == NULL)
805: continue;
806: ifam = mtod(m, struct ifa_msghdr *);
807: ifam->ifam_index = ifp->if_index;
808: ifam->ifam_metric = ifa->ifa_metric;
809: ifam->ifam_flags = ifa->ifa_flags;
810: ifam->ifam_addrs = info.rti_addrs;
811: }
812: if ((cmd == RTM_ADD && pass == 2) ||
813: (cmd == RTM_DELETE && pass == 1)) {
814: register struct rt_msghdr *rtm;
815:
816: if (rt == 0)
817: continue;
818: netmask = rt_mask(rt);
819: dst = sa = rt_key(rt);
820: gate = rt->rt_gateway;
821: if ((m = rt_msg1(cmd, &info)) == NULL)
822: continue;
823: rtm = mtod(m, struct rt_msghdr *);
824: rtm->rtm_index = ifp->if_index;
825: rtm->rtm_flags |= rt->rt_flags;
826: rtm->rtm_errno = error;
827: rtm->rtm_addrs = info.rti_addrs;
828: }
829: route_proto.sp_protocol = sa ? sa->sa_family : 0;
830: raw_input(m, &route_proto, &route_src, &route_dst);
831: }
832: }
833:
834: /*
835: * This is the analogue to the rt_newaddrmsg which performs the same
836: * function but for multicast group memberhips. This is easier since
837: * there is no route state to worry about.
838: */
839: void
840: rt_newmaddrmsg(cmd, ifma)
841: int cmd;
842: struct ifmultiaddr *ifma;
843: {
844: struct rt_addrinfo info;
845: struct mbuf *m = 0;
846: struct ifnet *ifp = ifma->ifma_ifp;
847: struct ifma_msghdr *ifmam;
848:
849: if (route_cb.any_count == 0)
850: return;
851:
852: bzero((caddr_t)&info, sizeof(info));
853: ifaaddr = ifma->ifma_addr;
854: ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
855: /*
856: * If a link-layer address is present, present it as a ``gateway''
857: * (similarly to how ARP entries, e.g., are presented).
858: */
859: gate = ifma->ifma_lladdr;
860: if ((m = rt_msg1(cmd, &info)) == NULL)
861: return;
862: ifmam = mtod(m, struct ifma_msghdr *);
863: ifmam->ifmam_index = ifp->if_index;
864: ifmam->ifmam_addrs = info.rti_addrs;
865: route_proto.sp_protocol = ifma->ifma_addr->sa_family;
866: raw_input(m, &route_proto, &route_src, &route_dst);
867: }
868:
869: /*
870: * This is used in dumping the kernel table via sysctl().
871: */
872: int
873: sysctl_dumpentry(rn, vw)
874: struct radix_node *rn;
875: void *vw;
876: {
877: register struct walkarg *w = vw;
878: register struct rtentry *rt = (struct rtentry *)rn;
879: int error = 0, size;
880: struct rt_addrinfo info;
881:
882: if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
883: return 0;
884: bzero((caddr_t)&info, sizeof(info));
885: dst = rt_key(rt);
886: gate = rt->rt_gateway;
887: netmask = rt_mask(rt);
888: genmask = rt->rt_genmask;
889: size = rt_msg2(RTM_GET, &info, 0, w);
890: if (w->w_req && w->w_tmem) {
891: register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
892:
893: rtm->rtm_flags = rt->rt_flags;
894: rtm->rtm_use = rt->rt_use;
895: rtm->rtm_rmx = rt->rt_rmx;
896: rtm->rtm_index = rt->rt_ifp->if_index;
897: rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
898: rtm->rtm_addrs = info.rti_addrs;
899: error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
900: return (error);
901: }
902: return (error);
903: }
904:
905: int
906: sysctl_iflist(af, w)
907: int af;
908: register struct walkarg *w;
909: {
910: register struct ifnet *ifp;
911: register struct ifaddr *ifa;
912: struct rt_addrinfo info;
913: int len, error = 0;
914:
915: bzero((caddr_t)&info, sizeof(info));
916: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
917: if (w->w_arg && w->w_arg != ifp->if_index)
918: continue;
919: ifa = ifp->if_addrhead.tqh_first;
920: ifpaddr = ifa->ifa_addr;
921: len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
922: ifpaddr = 0;
923: if (w->w_req && w->w_tmem) {
924: register struct if_msghdr *ifm;
925:
926: ifm = (struct if_msghdr *)w->w_tmem;
927: ifm->ifm_index = ifp->if_index;
928: ifm->ifm_flags = (u_short)ifp->if_flags;
929: ifm->ifm_data = ifp->if_data;
930: ifm->ifm_addrs = info.rti_addrs;
931: error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
932: if (error)
933: return (error);
934: }
935: while ((ifa = ifa->ifa_link.tqe_next) != 0) {
936: if (af && af != ifa->ifa_addr->sa_family)
937: continue;
938: ifaaddr = ifa->ifa_addr;
939: netmask = ifa->ifa_netmask;
940: brdaddr = ifa->ifa_dstaddr;
941: len = rt_msg2(RTM_NEWADDR, &info, 0, w);
942: if (w->w_req && w->w_tmem) {
943: register struct ifa_msghdr *ifam;
944:
945: ifam = (struct ifa_msghdr *)w->w_tmem;
946: ifam->ifam_index = ifa->ifa_ifp->if_index;
947: ifam->ifam_flags = ifa->ifa_flags;
948: ifam->ifam_metric = ifa->ifa_metric;
949: ifam->ifam_addrs = info.rti_addrs;
950: error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
951: if (error)
952: return (error);
953: }
954: }
955: ifaaddr = netmask = brdaddr = 0;
956: }
957: return (0);
958: }
959:
960:
961: static int
962: sysctl_rtsock SYSCTL_HANDLER_ARGS
963: {
964: int *name = (int *)arg1;
965: u_int namelen = arg2;
966: register struct radix_node_head *rnh;
967: int i, s, error = EINVAL;
968: u_char af;
969: struct walkarg w;
970:
971: name ++;
972: namelen--;
973: if (req->newptr)
974: return (EPERM);
975: if (namelen != 3)
976: return (EINVAL);
977: af = name[0];
978: Bzero(&w, sizeof(w));
979: w.w_op = name[1];
980: w.w_arg = name[2];
981: w.w_req = req;
982:
983: s = splnet();
984: switch (w.w_op) {
985:
986: case NET_RT_DUMP:
987: case NET_RT_FLAGS:
988: for (i = 1; i <= AF_MAX; i++)
989: if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
990: (error = rnh->rnh_walktree(rnh,
991: sysctl_dumpentry, &w)))
992: break;
993: break;
994:
995: case NET_RT_IFLIST:
996: error = sysctl_iflist(af, &w);
997: }
998: splx(s);
999: if (w.w_tmem)
1000: FREE(w.w_tmem, M_RTABLE);
1001: return (error);
1002: }
1003:
1004: SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1005:
1006:
1007:
1008: /*
1009: * Definitions of protocols supported in the ROUTE domain.
1010: */
1011:
1012: struct domain routedomain; /* or at least forward */
1013:
1014:
1015: static struct protosw routesw[] = {
1016: { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
1017: 0, route_output, raw_ctlinput, 0,
1018: 0,
1019: raw_init, 0, 0, 0,
1020: 0, &route_usrreqs, 0, 0
1021: }
1022: };
1023:
1024: struct domain routedomain =
1025: { PF_ROUTE, "route", route_init, 0, 0,
1026: routesw};
1027:
1028: DOMAIN_SET(route);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.