|
|
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_input.c 7.8 (Berkeley) 6/27/91
34: */
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "malloc.h"
39: #include "mbuf.h"
40: #include "domain.h"
41: #include "protosw.h"
42: #include "socket.h"
43: #include "socketvar.h"
44: #include "errno.h"
45: #include "time.h"
46: #include "kernel.h"
47:
48: #include "../net/if.h"
49: #include "../net/route.h"
50: #include "../net/raw_cb.h"
51:
52: #include "ns.h"
53: #include "ns_if.h"
54: #include "ns_pcb.h"
55: #include "idp.h"
56: #include "idp_var.h"
57: #include "ns_error.h"
58:
59: /*
60: * NS initialization.
61: */
62: union ns_host ns_thishost;
63: union ns_host ns_zerohost;
64: union ns_host ns_broadhost;
65: union ns_net ns_zeronet;
66: union ns_net ns_broadnet;
67: struct sockaddr_ns ns_netmask, ns_hostmask;
68:
69: static u_short allones[] = {-1, -1, -1};
70:
71: struct nspcb nspcb;
72: struct nspcb nsrawpcb;
73:
74: struct ifqueue nsintrq;
75: int nsqmaxlen = IFQ_MAXLEN;
76:
77: int idpcksum = 1;
78: long ns_pexseq;
79:
80: ns_init()
81: {
82: extern struct timeval time;
83:
84: ns_broadhost = * (union ns_host *) allones;
85: ns_broadnet = * (union ns_net *) allones;
86: nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
87: nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
88: nsintrq.ifq_maxlen = nsqmaxlen;
89: ns_pexseq = time.tv_usec;
90: ns_netmask.sns_len = 6;
91: ns_netmask.sns_addr.x_net = ns_broadnet;
92: ns_hostmask.sns_len = 12;
93: ns_hostmask.sns_addr.x_net = ns_broadnet;
94: ns_hostmask.sns_addr.x_host = ns_broadhost;
95: }
96:
97: /*
98: * Idp input routine. Pass to next level.
99: */
100: int nsintr_getpck = 0;
101: int nsintr_swtch = 0;
102: nsintr()
103: {
104: register struct idp *idp;
105: register struct mbuf *m;
106: register struct nspcb *nsp;
107: register int i;
108: int len, s, error;
109: char oddpacketp;
110:
111: next:
112: /*
113: * Get next datagram off input queue and get IDP header
114: * in first mbuf.
115: */
116: s = splimp();
117: IF_DEQUEUE(&nsintrq, m);
118: splx(s);
119: nsintr_getpck++;
120: if (m == 0)
121: return;
122: if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) &&
123: (m = m_pullup(m, sizeof (struct idp))) == 0) {
124: idpstat.idps_toosmall++;
125: goto next;
126: }
127:
128: /*
129: * Give any raw listeners a crack at the packet
130: */
131: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
132: struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
133: if (m1) idp_input(m1, nsp);
134: }
135:
136: idp = mtod(m, struct idp *);
137: len = ntohs(idp->idp_len);
138: if (oddpacketp = len & 1) {
139: len++; /* If this packet is of odd length,
140: preserve garbage byte for checksum */
141: }
142:
143: /*
144: * Check that the amount of data in the buffers
145: * is as at least much as the IDP header would have us expect.
146: * Trim mbufs if longer than we expect.
147: * Drop packet if shorter than we expect.
148: */
149: if (m->m_pkthdr.len < len) {
150: idpstat.idps_tooshort++;
151: goto bad;
152: }
153: if (m->m_pkthdr.len > len) {
154: if (m->m_len == m->m_pkthdr.len) {
155: m->m_len = len;
156: m->m_pkthdr.len = len;
157: } else
158: m_adj(m, len - m->m_pkthdr.len);
159: }
160: if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
161: idp->idp_sum = 0;
162: if (i != (idp->idp_sum = ns_cksum(m, len))) {
163: idpstat.idps_badsum++;
164: idp->idp_sum = i;
165: if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
166: error = NS_ERR_BADSUM;
167: else
168: error = NS_ERR_BADSUM_T;
169: ns_error(m, error, 0);
170: goto next;
171: }
172: }
173: /*
174: * Is this a directed broadcast?
175: */
176: if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
177: if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
178: (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
179: (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
180: (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
181: /*
182: * Look to see if I need to eat this packet.
183: * Algorithm is to forward all young packets
184: * and prematurely age any packets which will
185: * by physically broadcasted.
186: * Any very old packets eaten without forwarding
187: * would die anyway.
188: *
189: * Suggestion of Bill Nesheim, Cornell U.
190: */
191: if (idp->idp_tc < NS_MAXHOPS) {
192: idp_forward(m);
193: goto next;
194: }
195: }
196: /*
197: * Is this our packet? If not, forward.
198: */
199: } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
200: idp_forward(m);
201: goto next;
202: }
203: /*
204: * Locate pcb for datagram.
205: */
206: nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
207: /*
208: * Switch out to protocol's input routine.
209: */
210: nsintr_swtch++;
211: if (nsp) {
212: if (oddpacketp) {
213: m_adj(m, -1);
214: }
215: if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
216: switch (idp->idp_pt) {
217:
218: case NSPROTO_SPP:
219: spp_input(m, nsp);
220: goto next;
221:
222: case NSPROTO_ERROR:
223: ns_err_input(m);
224: goto next;
225: }
226: idp_input(m, nsp);
227: } else {
228: ns_error(m, NS_ERR_NOSOCK, 0);
229: }
230: goto next;
231:
232: bad:
233: m_freem(m);
234: goto next;
235: }
236:
237: u_char nsctlerrmap[PRC_NCMDS] = {
238: ECONNABORTED, ECONNABORTED, 0, 0,
239: 0, 0, EHOSTDOWN, EHOSTUNREACH,
240: ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
241: EMSGSIZE, 0, 0, 0,
242: 0, 0, 0, 0
243: };
244:
245: int idp_donosocks = 1;
246:
247: idp_ctlinput(cmd, arg)
248: int cmd;
249: caddr_t arg;
250: {
251: struct ns_addr *ns;
252: struct nspcb *nsp;
253: struct ns_errp *errp;
254: int idp_abort();
255: extern struct nspcb *idp_drop();
256: int type;
257:
258: if (cmd < 0 || cmd > PRC_NCMDS)
259: return;
260: if (nsctlerrmap[cmd] == 0)
261: return; /* XXX */
262: type = NS_ERR_UNREACH_HOST;
263: switch (cmd) {
264: struct sockaddr_ns *sns;
265:
266: case PRC_IFDOWN:
267: case PRC_HOSTDEAD:
268: case PRC_HOSTUNREACH:
269: sns = (struct sockaddr_ns *)arg;
270: if (sns->sns_family != AF_NS)
271: return;
272: ns = &sns->sns_addr;
273: break;
274:
275: default:
276: errp = (struct ns_errp *)arg;
277: ns = &errp->ns_err_idp.idp_dna;
278: type = errp->ns_err_num;
279: type = ntohs((u_short)type);
280: }
281: switch (type) {
282:
283: case NS_ERR_UNREACH_HOST:
284: ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
285: break;
286:
287: case NS_ERR_NOSOCK:
288: nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
289: NS_WILDCARD);
290: if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
291: (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
292: }
293: }
294:
295: int idpprintfs = 0;
296: int idpforwarding = 1;
297: /*
298: * Forward a packet. If some error occurs return the sender
299: * an error packet. Note we can't always generate a meaningful
300: * error message because the NS errors don't have a large enough repetoire
301: * of codes and types.
302: */
303: struct route idp_droute;
304: struct route idp_sroute;
305:
306: idp_forward(m)
307: struct mbuf *m;
308: {
309: register struct idp *idp = mtod(m, struct idp *);
310: register int error, type, code;
311: struct mbuf *mcopy = NULL;
312: int agedelta = 1;
313: int flags = NS_FORWARDING;
314: int ok_there = 0;
315: int ok_back = 0;
316:
317: if (idpprintfs) {
318: printf("forward: src ");
319: ns_printhost(&idp->idp_sna);
320: printf(", dst ");
321: ns_printhost(&idp->idp_dna);
322: printf("hop count %d\n", idp->idp_tc);
323: }
324: if (idpforwarding == 0) {
325: /* can't tell difference between net and host */
326: type = NS_ERR_UNREACH_HOST, code = 0;
327: goto senderror;
328: }
329: idp->idp_tc++;
330: if (idp->idp_tc > NS_MAXHOPS) {
331: type = NS_ERR_TOO_OLD, code = 0;
332: goto senderror;
333: }
334: /*
335: * Save at most 42 bytes of the packet in case
336: * we need to generate an NS error message to the src.
337: */
338: mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42));
339:
340: if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
341: type = NS_ERR_UNREACH_HOST, code = 0;
342: goto senderror;
343: }
344: /*
345: * Here we think about forwarding broadcast packets,
346: * so we try to insure that it doesn't go back out
347: * on the interface it came in on. Also, if we
348: * are going to physically broadcast this, let us
349: * age the packet so we can eat it safely the second time around.
350: */
351: if (idp->idp_dna.x_host.c_host[0] & 0x1) {
352: struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
353: struct ifnet *ifp;
354: if (ia) {
355: /* I'm gonna hafta eat this packet */
356: agedelta += NS_MAXHOPS - idp->idp_tc;
357: idp->idp_tc = NS_MAXHOPS;
358: }
359: if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
360: /* error = ENETUNREACH; He'll never get it! */
361: m_freem(m);
362: goto cleanup;
363: }
364: if (idp_droute.ro_rt &&
365: (ifp=idp_droute.ro_rt->rt_ifp) &&
366: idp_sroute.ro_rt &&
367: (ifp!=idp_sroute.ro_rt->rt_ifp)) {
368: flags |= NS_ALLOWBROADCAST;
369: } else {
370: type = NS_ERR_UNREACH_HOST, code = 0;
371: goto senderror;
372: }
373: }
374: /* need to adjust checksum */
375: if (idp->idp_sum!=0xffff) {
376: union bytes {
377: u_char c[4];
378: u_short s[2];
379: long l;
380: } x;
381: register int shift;
382: x.l = 0; x.c[0] = agedelta;
383: shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
384: x.l = idp->idp_sum + (x.s[0] << shift);
385: x.l = x.s[0] + x.s[1];
386: x.l = x.s[0] + x.s[1];
387: if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
388: }
389: if ((error = ns_output(m, &idp_droute, flags)) &&
390: (mcopy!=NULL)) {
391: idp = mtod(mcopy, struct idp *);
392: type = NS_ERR_UNSPEC_T, code = 0;
393: switch (error) {
394:
395: case ENETUNREACH:
396: case EHOSTDOWN:
397: case EHOSTUNREACH:
398: case ENETDOWN:
399: case EPERM:
400: type = NS_ERR_UNREACH_HOST;
401: break;
402:
403: case EMSGSIZE:
404: type = NS_ERR_TOO_BIG;
405: code = 576; /* too hard to figure out mtu here */
406: break;
407:
408: case ENOBUFS:
409: type = NS_ERR_UNSPEC_T;
410: break;
411: }
412: mcopy = NULL;
413: senderror:
414: ns_error(m, type, code);
415: }
416: cleanup:
417: if (ok_there)
418: idp_undo_route(&idp_droute);
419: if (ok_back)
420: idp_undo_route(&idp_sroute);
421: if (mcopy != NULL)
422: m_freem(mcopy);
423: }
424:
425: idp_do_route(src, ro)
426: struct ns_addr *src;
427: struct route *ro;
428: {
429:
430: struct sockaddr_ns *dst;
431:
432: bzero((caddr_t)ro, sizeof (*ro));
433: dst = (struct sockaddr_ns *)&ro->ro_dst;
434:
435: dst->sns_len = sizeof(*dst);
436: dst->sns_family = AF_NS;
437: dst->sns_addr = *src;
438: dst->sns_addr.x_port = 0;
439: rtalloc(ro);
440: if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
441: return (0);
442: }
443: ro->ro_rt->rt_use++;
444: return (1);
445: }
446:
447: idp_undo_route(ro)
448: register struct route *ro;
449: {
450: if (ro->ro_rt) {RTFREE(ro->ro_rt);}
451: }
452:
453: ns_watch_output(m, ifp)
454: struct mbuf *m;
455: struct ifnet *ifp;
456: {
457: register struct nspcb *nsp;
458: register struct ifaddr *ifa;
459: /*
460: * Give any raw listeners a crack at the packet
461: */
462: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
463: struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
464: if (m0) {
465: register struct idp *idp;
466:
467: M_PREPEND(m0, sizeof (*idp), M_DONTWAIT);
468: if (m0 == NULL)
469: continue;
470: idp = mtod(m0, struct idp *);
471: idp->idp_sna.x_net = ns_zeronet;
472: idp->idp_sna.x_host = ns_thishost;
473: if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
474: for(ifa = ifp->if_addrlist; ifa;
475: ifa = ifa->ifa_next) {
476: if (ifa->ifa_addr->sa_family==AF_NS) {
477: idp->idp_sna = IA_SNS(ifa)->sns_addr;
478: break;
479: }
480: }
481: idp->idp_len = ntohl(m0->m_pkthdr.len);
482: idp_input(m0, nsp);
483: }
484: }
485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.