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