date and time created 85/07/26 13:37:37 by sam
[unix-history] / usr / src / sys / netns / ns_ip.c
CommitLineData
8ae0e4b4
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
f2c50bef 6 * @(#)ns_ip.c 6.3 (Berkeley) %G%
8ae0e4b4 7 */
c5d24c39
KS
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 "errno.h"
19#include "ioctl.h"
20
21#include "../net/if.h"
22#include "../net/netisr.h"
23#include "../net/route.h"
24
25#include "../netinet/in.h"
26#include "../netinet/in_systm.h"
27#include "../netinet/in_var.h"
28#include "../netinet/ip.h"
29#include "../netinet/ip_var.h"
30
31#ifdef vax
32#include "../vax/mtpr.h"
33#endif
34
35#include "../netns/ns.h"
36#include "../netns/ns_if.h"
37#include "../netns/idp.h"
38
39struct ifnet_en {
40 struct ifnet ifen_ifnet;
41 struct route ifen_route;
42 struct in_addr ifen_src;
43 struct in_addr ifen_dst;
44};
45
46int nsipoutput(), nsipioctl();
47#define LOMTU (1024+512);
48
49struct ifnet nsipif;
50union ns_net nsip_net;
51struct mbuf *nsip_list; /* list of all hosts and gateways or
52 broadcast addrs */
53
54struct mbuf *
55nsipattach()
56{
57 register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
58 register struct ifnet *ifp;
59 register struct sockaddr_in *sin;
60
61 if (m==0) return (0);
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 */
83nsipioctl(ifp, cmd, data)
84 register struct ifnet *ifp;
85 int cmd;
86 caddr_t data;
87{
88 int error = 0;
89
90 switch (cmd) {
91
92 case SIOCSIFADDR:
93 ifp->if_flags |= IFF_UP;
94 /*
95 * Everything else is done at a higher level.
96 */
97 break;
98
99 default:
100 error = EINVAL;
101 }
102 return (error);
103}
104
105struct mbuf *nsip_badlen;
106struct mbuf *nsip_lastin;
107int nsip_hold_input;
108
109idpip_input(m0)
110 struct mbuf *m0;
111{
112 register struct ip *ip;
113 register struct idp *idp;
114 register struct mbuf *m;
115 register struct ifqueue *ifq = &nsintrq;
116 int len, s;
117
118 if(nsip_hold_input) {
119 if(nsip_lastin) {
120 m_free(nsip_lastin);
121 }
122 nsip_lastin = m_copy(m0, 0, M_COPYALL);
123 }
124 /*
125 * Get IP and IDP header together in first mbuf.
126 */
127 nsipif.if_ipackets++;
128 m = m0;
129 s = sizeof (struct ip) + sizeof (struct idp);
130 if ((m->m_off > MMAXOFF || m->m_len < s) &&
131 (m = m_pullup(m, s))==0) {
132 nsipif.if_ierrors++;
133 return;
134 }
135 ip = mtod(m, struct ip *);
136 if (ip->ip_hl > (sizeof (struct ip) >> 2))
137 ip_stripoptions(ip, (struct mbuf *)0);
138
139 /*
140 * Make mbuf data length reflect IDP length.
141 * If not enough data to reflect IDP length, drop.
142 */
143 m->m_off += sizeof (struct ip);
144 m->m_len -= sizeof (struct ip);
145 idp = mtod(m, struct idp *);
146 len = ntohs(idp->idp_len);
f2c50bef 147 if (len & 1) len++; /* Preserve Garbage Byte */
c5d24c39
KS
148 if (ip->ip_len != len) {
149 if (len > ip->ip_len) {
150 nsipif.if_ierrors++;
151 if(nsip_badlen) m_freem(nsip_badlen);
152 nsip_badlen = m;
153 return;
154 }
155 m_adj(m, len - ip->ip_len);
156 /* ip->ip_len = len; */
157 }
158 /*
159 * Deliver to NS
160 */
161 s = splimp();
162 if (IF_QFULL(ifq)) {
163 IF_DROP(ifq);
164 m_freem(m0);
165 splx(s);
166 return (ENOBUFS);
167 }
168 IF_ENQUEUE(ifq, m0);
169 schednetisr(NETISR_NS);
170 splx(s);
171 return (0);
172bad:
173 m_freem(m);
174 return (0);
175}
176
177nsipoutput(ifn, m0, dst)
178 struct ifnet_en *ifn;
179 struct mbuf *m0;
180 struct sockaddr *dst;
181{
182
183 register struct mbuf *m = dtom(ifn);
184 register struct ip *ip;
185 register struct route *ro = &(ifn->ifen_route);
186 register int len = 0;
187 struct in_addr in_src, in_dst;
188 register struct idp *idp = mtod(m0, struct idp *);
189 int error;
190
191 if (m->m_len != sizeof(struct ifnet_en)) {
192 printf("nsipoutput: bad dst ifp %x\n", ifn);
193 goto bad;
194 }
195 ifn->ifen_ifnet.if_opackets++;
196 nsipif.if_opackets++;
197
198
199 /*
200 * Calculate data length and make space
201 * for IP header.
202 */
203 len = ntohs(idp->idp_len);
f2c50bef 204 if (len & 1) len++; /* Preserve Garbage Byte */
c5d24c39
KS
205 m = m0;
206 if(m->m_off < MMINOFF + sizeof (struct ip)) {
207 m = m_get(M_DONTWAIT, MT_HEADER);
208 if (m == 0) {
209 m_freem(m0);
210 return (ENOBUFS);
211 }
212 m->m_off = MMAXOFF - sizeof (struct ip);
213 m->m_len = sizeof (struct ip);
214 m->m_next = m0;
215 } else {
216 m->m_off -= sizeof (struct ip);
217 m->m_len += sizeof (struct ip);
218 }
219 /*
220 * Fill in IP header.
221 */
222 ip = mtod(m, struct ip *);
223 *(long *)ip = 0;
224 ip->ip_p = IPPROTO_PUP;
225 ip->ip_src = ifn->ifen_src;
226 ip->ip_dst = ifn->ifen_dst;
227 ip->ip_len = (u_short)len + sizeof (struct ip);
228 ip->ip_ttl = MAXTTL;
229
230 /*
231 * Output final datagram.
232 */
233 error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST));
234 if (error) {
235 ifn->ifen_ifnet.if_oerrors++;
236 ifn->ifen_ifnet.if_ierrors = error;
237 }
238 return (error);
239bad:
240 m_freem(m0);
241 return(ENETUNREACH);
242}
243
244struct ifreq ifr = {"nsip0"};
245
246nsip_route(m)
247 register struct mbuf *m;
248{
249 register struct nsip_req *rq = mtod(m, struct nsip_req *);
250 struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
251 struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
252 int flags = rq->rq_flags;
253 struct ifnet *ifp;
254 struct route ro;
255 struct ifnet_en *ifn;
256 int error;
257 struct sockaddr_in *dst;
258 struct sockaddr_in *src;
259 /*
260 * First, determine if we can get to the destination
261 */
262 bzero((caddr_t)&ro, sizeof (ro));
263 ro.ro_dst = *(struct sockaddr *)ip_dst;
264 dst = (struct sockaddr_in *)& ro.ro_dst;
265 rtalloc(&ro);
266 if (ro.ro_rt == 0 || (ifp = ro.ro_rt->rt_ifp) == 0) {
267 return (ENETUNREACH);
268 }
269 /*
270 * And see how he's going to get back to us:
271 */
272 {
273 register struct in_ifaddr *ia;
274 struct ifnet *ifp = ro.ro_rt->rt_ifp;
275
276 for (ia = in_ifaddr; ia; ia = ia->ia_next)
277 if (ia->ia_ifp == ifp)
278 break;
279 if (ia == 0)
280 ia = in_ifaddr;
281 if (ia == 0) {
282 return (EADDRNOTAVAIL);
283 }
284 src = (struct sockaddr_in *)&ia->ia_addr;
285 }
286 /*
287 * Is there space?
288 */
289 m = nsipattach();
290 if (m==NULL) {return (ENOBUFS);}
291 ifn = mtod(m, struct ifnet_en *);
292
293 ro.ro_rt->rt_use++;
294 ifn->ifen_route = ro;
295 ifn->ifen_dst = ip_dst->sin_addr;
296 ifn->ifen_src = src->sin_addr;
297
298 /*
299 * now configure this as a point to point link
300 */
301 ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
302 ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
303 return(ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr,
304 (struct ifnet *)ifn));
305}
306#endif