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