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