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