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