|
|
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) 1984, 1985, 1986, 1987, 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: * @(#)ns_ip.c 8.1 (Berkeley) 6/10/93
55: */
56:
57: /*
58: * Software interface driver for encapsulating ns in ip.
59: */
60:
61: #ifdef NSIP
62: #include <sys/param.h>
63: #include <sys/systm.h>
64: #include <sys/malloc.h>
65: #include <sys/mbuf.h>
66: #include <sys/socket.h>
67: #include <sys/socketvar.h>
68: #include <sys/errno.h>
69: #include <sys/ioctl.h>
70: #include <sys/protosw.h>
71:
72: #include <net/if.h>
73: #include <net/netisr.h>
74: #include <net/route.h>
75:
76: #include <netinet/in.h>
77: #include <netinet/in_systm.h>
78: #include <netinet/in_var.h>
79: #include <netinet/ip.h>
80: #include <netinet/ip_var.h>
81:
82: #include <machine/mtpr.h>
83:
84: #include <netns/ns.h>
85: #include <netns/ns_if.h>
86: #include <netns/idp.h>
87:
88: struct ifnet_en {
89: struct ifnet ifen_ifnet;
90: struct route ifen_route;
91: struct in_addr ifen_src;
92: struct in_addr ifen_dst;
93: struct ifnet_en *ifen_next;
94: };
95:
96: int nsipoutput(), nsipioctl(), nsipstart();
97: #define LOMTU (1024+512);
98:
99: struct ifnet nsipif;
100: struct ifnet_en *nsip_list; /* list of all hosts and gateways or
101: broadcast addrs */
102:
103: struct ifnet_en *
104: nsipattach()
105: {
106: register struct ifnet_en *m;
107: register struct ifnet *ifp;
108:
109: if (nsipif.if_mtu == 0) {
110: ifp = &nsipif;
111: ifp->if_name = "nsip";
112: ifp->if_mtu = LOMTU;
113: ifp->if_ioctl = nsipioctl;
114: ifp->if_output = nsipoutput;
115: ifp->if_start = nsipstart;
116: ifp->if_flags = IFF_POINTOPOINT;
117: }
118:
119: MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);
120: if (m == NULL) return (NULL);
121: m->ifen_next = nsip_list;
122: nsip_list = m;
123: ifp = &m->ifen_ifnet;
124:
125: ifp->if_name = "nsip";
126: ifp->if_mtu = LOMTU;
127: ifp->if_ioctl = nsipioctl;
128: ifp->if_output = nsipoutput;
129: ifp->if_start = nsipstart;
130: ifp->if_flags = IFF_POINTOPOINT;
131: ifp->if_unit = nsipif.if_unit++;
132: if_attach(ifp);
133:
134: return (m);
135: }
136:
137:
138: /*
139: * Process an ioctl request.
140: */
141: /* ARGSUSED */
142: nsipioctl(ifp, cmd, data)
143: register struct ifnet *ifp;
144: int cmd;
145: caddr_t data;
146: {
147: int error = 0;
148: struct ifreq *ifr;
149:
150: switch (cmd) {
151:
152: case SIOCSIFADDR:
153: ifp->if_flags |= IFF_UP;
154: /* fall into: */
155:
156: case SIOCSIFDSTADDR:
157: /*
158: * Everything else is done at a higher level.
159: */
160: break;
161:
162: case SIOCSIFFLAGS:
163: ifr = (struct ifreq *)data;
164: if ((ifr->ifr_flags & IFF_UP) == 0)
165: error = nsip_free(ifp);
166:
167:
168: default:
169: error = EINVAL;
170: }
171: return (error);
172: }
173:
174: struct mbuf *nsip_badlen;
175: struct mbuf *nsip_lastin;
176: int nsip_hold_input;
177:
178: idpip_input(m, ifp)
179: register struct mbuf *m;
180: struct ifnet *ifp;
181: {
182: register struct ip *ip;
183: register struct idp *idp;
184: register struct ifqueue *ifq = &nsintrq;
185: int len, s;
186:
187: if (nsip_hold_input) {
188: if (nsip_lastin) {
189: m_freem(nsip_lastin);
190: }
191: nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
192: }
193: /*
194: * Get IP and IDP header together in first mbuf.
195: */
196: nsipif.if_ipackets++;
197: s = sizeof (struct ip) + sizeof (struct idp);
198: if (((m->m_flags & M_EXT) || m->m_len < s) &&
199: (m = m_pullup(m, s)) == 0) {
200: nsipif.if_ierrors++;
201: return;
202: }
203: ip = mtod(m, struct ip *);
204: if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
205: ip_stripoptions(m, (struct mbuf *)0);
206: if (m->m_len < s) {
207: if ((m = m_pullup(m, s)) == 0) {
208: nsipif.if_ierrors++;
209: return;
210: }
211: ip = mtod(m, struct ip *);
212: }
213: }
214:
215: /*
216: * Make mbuf data length reflect IDP length.
217: * If not enough data to reflect IDP length, drop.
218: */
219: m->m_data += sizeof (struct ip);
220: m->m_len -= sizeof (struct ip);
221: m->m_pkthdr.len -= sizeof (struct ip);
222: idp = mtod(m, struct idp *);
223: len = ntohs(idp->idp_len);
224: if (len & 1) len++; /* Preserve Garbage Byte */
225: if (ip->ip_len != len) {
226: if (len > ip->ip_len) {
227: nsipif.if_ierrors++;
228: if (nsip_badlen) m_freem(nsip_badlen);
229: nsip_badlen = m;
230: return;
231: }
232: /* Any extra will be trimmed off by the NS routines */
233: }
234:
235: /*
236: * Place interface pointer before the data
237: * for the receiving protocol.
238: */
239: m->m_pkthdr.rcvif = ifp;
240: /*
241: * Deliver to NS
242: */
243: s = splimp();
244: if (IF_QFULL(ifq)) {
245: IF_DROP(ifq);
246: bad:
247: m_freem(m);
248: splx(s);
249: return;
250: }
251: IF_ENQUEUE(ifq, m);
252: schednetisr(NETISR_NS);
253: splx(s);
254: return;
255: }
256:
257: /* ARGSUSED */
258: nsipoutput(ifn, m, dst)
259: struct ifnet_en *ifn;
260: register struct mbuf *m;
261: struct sockaddr *dst;
262: {
263:
264: register struct ip *ip;
265: register struct route *ro = &(ifn->ifen_route);
266: register int len = 0;
267: register struct idp *idp = mtod(m, struct idp *);
268: int error;
269:
270: ifn->ifen_ifnet.if_opackets++;
271: nsipif.if_opackets++;
272:
273:
274: /*
275: * Calculate data length and make space
276: * for IP header.
277: */
278: len = ntohs(idp->idp_len);
279: if (len & 1) len++; /* Preserve Garbage Byte */
280: /* following clause not necessary on vax */
281: if (3 & (int)m->m_data) {
282: /* force longword alignment of ip hdr */
283: struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
284: if (m0 == 0) {
285: m_freem(m);
286: return (ENOBUFS);
287: }
288: MH_ALIGN(m0, sizeof (struct ip));
289: m0->m_flags = m->m_flags & M_COPYFLAGS;
290: m0->m_next = m;
291: m0->m_len = sizeof (struct ip);
292: m0->m_pkthdr.len = m0->m_len + m->m_len;
293: m->m_flags &= ~M_PKTHDR;
294: } else {
295: M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
296: if (m == 0)
297: return (ENOBUFS);
298: }
299: /*
300: * Fill in IP header.
301: */
302: ip = mtod(m, struct ip *);
303: *(long *)ip = 0;
304: ip->ip_p = IPPROTO_IDP;
305: ip->ip_src = ifn->ifen_src;
306: ip->ip_dst = ifn->ifen_dst;
307: ip->ip_len = (u_short)len + sizeof (struct ip);
308: ip->ip_ttl = MAXTTL;
309:
310: /*
311: * Output final datagram.
312: */
313: error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));
314: if (error) {
315: ifn->ifen_ifnet.if_oerrors++;
316: ifn->ifen_ifnet.if_ierrors = error;
317: }
318: return (error);
319: bad:
320: m_freem(m);
321: return (ENETUNREACH);
322: }
323:
324: nsipstart(ifp)
325: struct ifnet *ifp;
326: {
327: panic("nsip_start called\n");
328: }
329:
330: struct ifreq ifr = {"nsip0"};
331:
332: nsip_route(m)
333: register struct mbuf *m;
334: {
335: register struct nsip_req *rq = mtod(m, struct nsip_req *);
336: struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
337: struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
338: struct route ro;
339: struct ifnet_en *ifn;
340: struct sockaddr_in *src;
341:
342: /*
343: * First, make sure we already have an ns address:
344: */
345: if (ns_hosteqnh(ns_thishost, ns_zerohost))
346: return (EADDRNOTAVAIL);
347: /*
348: * Now, determine if we can get to the destination
349: */
350: bzero((caddr_t)&ro, sizeof (ro));
351: ro.ro_dst = *(struct sockaddr *)ip_dst;
352: rtalloc(&ro);
353: if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
354: return (ENETUNREACH);
355: }
356:
357: /*
358: * And see how he's going to get back to us:
359: * i.e., what return ip address do we use?
360: */
361: {
362: register struct in_ifaddr *ia;
363: struct ifnet *ifp = ro.ro_rt->rt_ifp;
364:
365: for (ia = in_ifaddr; ia; ia = ia->ia_next)
366: if (ia->ia_ifp == ifp)
367: break;
368: if (ia == 0)
369: ia = in_ifaddr;
370: if (ia == 0) {
371: RTFREE(ro.ro_rt);
372: return (EADDRNOTAVAIL);
373: }
374: src = (struct sockaddr_in *)&ia->ia_addr;
375: }
376:
377: /*
378: * Is there a free (pseudo-)interface or space?
379: */
380: for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
381: if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)
382: break;
383: }
384: if (ifn == NULL)
385: ifn = nsipattach();
386: if (ifn == NULL) {
387: RTFREE(ro.ro_rt);
388: return (ENOBUFS);
389: }
390: ifn->ifen_route = ro;
391: ifn->ifen_dst = ip_dst->sin_addr;
392: ifn->ifen_src = src->sin_addr;
393:
394: /*
395: * now configure this as a point to point link
396: */
397: ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
398: ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
399: (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr,
400: (struct ifnet *)ifn);
401: satons_addr(ifr.ifr_addr).x_host = ns_thishost;
402: return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
403: (struct ifnet *)ifn));
404: }
405:
406: nsip_free(ifp)
407: struct ifnet *ifp;
408: {
409: register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
410: struct route *ro = & ifn->ifen_route;
411:
412: if (ro->ro_rt) {
413: RTFREE(ro->ro_rt);
414: ro->ro_rt = 0;
415: }
416: ifp->if_flags &= ~IFF_UP;
417: return (0);
418: }
419:
420: nsip_ctlinput(cmd, sa)
421: int cmd;
422: struct sockaddr *sa;
423: {
424: extern u_char inetctlerrmap[];
425: struct sockaddr_in *sin;
426: int in_rtchange();
427:
428: if ((unsigned)cmd >= PRC_NCMDS)
429: return;
430: if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
431: return;
432: sin = (struct sockaddr_in *)sa;
433: if (sin->sin_addr.s_addr == INADDR_ANY)
434: return;
435:
436: switch (cmd) {
437:
438: case PRC_ROUTEDEAD:
439: case PRC_REDIRECT_NET:
440: case PRC_REDIRECT_HOST:
441: case PRC_REDIRECT_TOSNET:
442: case PRC_REDIRECT_TOSHOST:
443: nsip_rtchange(&sin->sin_addr);
444: break;
445: }
446: }
447:
448: nsip_rtchange(dst)
449: register struct in_addr *dst;
450: {
451: register struct ifnet_en *ifn;
452:
453: for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
454: if (ifn->ifen_dst.s_addr == dst->s_addr &&
455: ifn->ifen_route.ro_rt) {
456: RTFREE(ifn->ifen_route.ro_rt);
457: ifn->ifen_route.ro_rt = 0;
458: }
459: }
460: }
461: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.