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