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