|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1984, 1985, 1986, 1987, 1993
27: * The Regents of the University of California. All rights reserved.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Berkeley and its contributors.
41: * 4. Neither the name of the University nor the names of its contributors
42: * may be used to endorse or promote products derived from this software
43: * without specific prior written permission.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: *
57: * @(#)ns_input.c 8.1 (Berkeley) 6/10/93
58: */
59:
60: #include <sys/param.h>
61: #include <sys/systm.h>
62: #include <sys/malloc.h>
63: #include <sys/mbuf.h>
64: #include <sys/domain.h>
65: #include <sys/protosw.h>
66: #include <sys/socket.h>
67: #include <sys/socketvar.h>
68: #include <sys/errno.h>
69: #include <sys/time.h>
70: #include <sys/kernel.h>
71:
72: #include <net/if.h>
73: #include <net/route.h>
74: #include <net/raw_cb.h>
75:
76: #include <netns/ns.h>
77: #include <netns/ns_if.h>
78: #include <netns/ns_pcb.h>
79: #include <netns/idp.h>
80: #include <netns/idp_var.h>
81: #include <netns/ns_error.h>
82:
83: /*
84: * NS initialization.
85: */
86: union ns_host ns_thishost;
87: union ns_host ns_zerohost;
88: union ns_host ns_broadhost;
89: union ns_net ns_zeronet;
90: union ns_net ns_broadnet;
91: struct sockaddr_ns ns_netmask, ns_hostmask;
92:
93: static u_short allones[] = {-1, -1, -1};
94:
95: struct nspcb nspcb;
96: struct nspcb nsrawpcb;
97:
98: struct ifqueue nsintrq;
99: int nsqmaxlen = IFQ_MAXLEN;
100:
101: int idpcksum = 1;
102: long ns_pexseq;
103:
104: ns_init()
105: {
106: extern struct timeval time;
107:
108: ns_broadhost = * (union ns_host *) allones;
109: ns_broadnet = * (union ns_net *) allones;
110: nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
111: nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
112: nsintrq.ifq_maxlen = nsqmaxlen;
113: ns_pexseq = time.tv_usec;
114: ns_netmask.sns_len = 6;
115: ns_netmask.sns_addr.x_net = ns_broadnet;
116: ns_hostmask.sns_len = 12;
117: ns_hostmask.sns_addr.x_net = ns_broadnet;
118: ns_hostmask.sns_addr.x_host = ns_broadhost;
119: }
120:
121: /*
122: * Idp input routine. Pass to next level.
123: */
124: int nsintr_getpck = 0;
125: int nsintr_swtch = 0;
126: nsintr()
127: {
128: register struct idp *idp;
129: register struct mbuf *m;
130: register struct nspcb *nsp;
131: register int i;
132: int len, s, error;
133: char oddpacketp;
134:
135: next:
136: /*
137: * Get next datagram off input queue and get IDP header
138: * in first mbuf.
139: */
140: s = splimp();
141: IF_DEQUEUE(&nsintrq, m);
142: splx(s);
143: nsintr_getpck++;
144: if (m == 0)
145: return;
146: if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) &&
147: (m = m_pullup(m, sizeof (struct idp))) == 0) {
148: idpstat.idps_toosmall++;
149: goto next;
150: }
151:
152: /*
153: * Give any raw listeners a crack at the packet
154: */
155: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
156: struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
157: if (m1) idp_input(m1, nsp);
158: }
159:
160: idp = mtod(m, struct idp *);
161: len = ntohs(idp->idp_len);
162: if (oddpacketp = len & 1) {
163: len++; /* If this packet is of odd length,
164: preserve garbage byte for checksum */
165: }
166:
167: /*
168: * Check that the amount of data in the buffers
169: * is as at least much as the IDP header would have us expect.
170: * Trim mbufs if longer than we expect.
171: * Drop packet if shorter than we expect.
172: */
173: if (m->m_pkthdr.len < len) {
174: idpstat.idps_tooshort++;
175: goto bad;
176: }
177: if (m->m_pkthdr.len > len) {
178: if (m->m_len == m->m_pkthdr.len) {
179: m->m_len = len;
180: m->m_pkthdr.len = len;
181: } else
182: m_adj(m, len - m->m_pkthdr.len);
183: }
184: if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
185: idp->idp_sum = 0;
186: if (i != (idp->idp_sum = ns_cksum(m, len))) {
187: idpstat.idps_badsum++;
188: idp->idp_sum = i;
189: if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
190: error = NS_ERR_BADSUM;
191: else
192: error = NS_ERR_BADSUM_T;
193: ns_error(m, error, 0);
194: goto next;
195: }
196: }
197: /*
198: * Is this a directed broadcast?
199: */
200: if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
201: if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
202: (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
203: (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
204: (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
205: /*
206: * Look to see if I need to eat this packet.
207: * Algorithm is to forward all young packets
208: * and prematurely age any packets which will
209: * by physically broadcasted.
210: * Any very old packets eaten without forwarding
211: * would die anyway.
212: *
213: * Suggestion of Bill Nesheim, Cornell U.
214: */
215: if (idp->idp_tc < NS_MAXHOPS) {
216: idp_forward(m);
217: goto next;
218: }
219: }
220: /*
221: * Is this our packet? If not, forward.
222: */
223: } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
224: idp_forward(m);
225: goto next;
226: }
227: /*
228: * Locate pcb for datagram.
229: */
230: nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
231: /*
232: * Switch out to protocol's input routine.
233: */
234: nsintr_swtch++;
235: if (nsp) {
236: if (oddpacketp) {
237: m_adj(m, -1);
238: }
239: if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
240: switch (idp->idp_pt) {
241:
242: case NSPROTO_SPP:
243: spp_input(m, nsp);
244: goto next;
245:
246: case NSPROTO_ERROR:
247: ns_err_input(m);
248: goto next;
249: }
250: idp_input(m, nsp);
251: } else {
252: ns_error(m, NS_ERR_NOSOCK, 0);
253: }
254: goto next;
255:
256: bad:
257: m_freem(m);
258: goto next;
259: }
260:
261: u_char nsctlerrmap[PRC_NCMDS] = {
262: ECONNABORTED, ECONNABORTED, 0, 0,
263: 0, 0, EHOSTDOWN, EHOSTUNREACH,
264: ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
265: EMSGSIZE, 0, 0, 0,
266: 0, 0, 0, 0
267: };
268:
269: int idp_donosocks = 1;
270:
271: idp_ctlinput(cmd, arg)
272: int cmd;
273: caddr_t arg;
274: {
275: struct ns_addr *ns;
276: struct nspcb *nsp;
277: struct ns_errp *errp;
278: int idp_abort();
279: extern struct nspcb *idp_drop();
280: int type;
281:
282: if (cmd < 0 || cmd > PRC_NCMDS)
283: return;
284: if (nsctlerrmap[cmd] == 0)
285: return; /* XXX */
286: type = NS_ERR_UNREACH_HOST;
287: switch (cmd) {
288: struct sockaddr_ns *sns;
289:
290: case PRC_IFDOWN:
291: case PRC_HOSTDEAD:
292: case PRC_HOSTUNREACH:
293: sns = (struct sockaddr_ns *)arg;
294: if (sns->sns_family != AF_NS)
295: return;
296: ns = &sns->sns_addr;
297: break;
298:
299: default:
300: errp = (struct ns_errp *)arg;
301: ns = &errp->ns_err_idp.idp_dna;
302: type = errp->ns_err_num;
303: type = ntohs((u_short)type);
304: }
305: switch (type) {
306:
307: case NS_ERR_UNREACH_HOST:
308: ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
309: break;
310:
311: case NS_ERR_NOSOCK:
312: nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
313: NS_WILDCARD);
314: if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
315: (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
316: }
317: }
318:
319: int idpprintfs = 0;
320: int idpforwarding = 1;
321: /*
322: * Forward a packet. If some error occurs return the sender
323: * an error packet. Note we can't always generate a meaningful
324: * error message because the NS errors don't have a large enough repetoire
325: * of codes and types.
326: */
327: struct route idp_droute;
328: struct route idp_sroute;
329:
330: idp_forward(m)
331: struct mbuf *m;
332: {
333: register struct idp *idp = mtod(m, struct idp *);
334: register int error, type, code;
335: struct mbuf *mcopy = NULL;
336: int agedelta = 1;
337: int flags = NS_FORWARDING;
338: int ok_there = 0;
339: int ok_back = 0;
340:
341: if (idpprintfs) {
342: printf("forward: src ");
343: ns_printhost(&idp->idp_sna);
344: printf(", dst ");
345: ns_printhost(&idp->idp_dna);
346: printf("hop count %d\n", idp->idp_tc);
347: }
348: if (idpforwarding == 0) {
349: /* can't tell difference between net and host */
350: type = NS_ERR_UNREACH_HOST, code = 0;
351: goto senderror;
352: }
353: idp->idp_tc++;
354: if (idp->idp_tc > NS_MAXHOPS) {
355: type = NS_ERR_TOO_OLD, code = 0;
356: goto senderror;
357: }
358: /*
359: * Save at most 42 bytes of the packet in case
360: * we need to generate an NS error message to the src.
361: */
362: mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42));
363:
364: if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
365: type = NS_ERR_UNREACH_HOST, code = 0;
366: goto senderror;
367: }
368: /*
369: * Here we think about forwarding broadcast packets,
370: * so we try to insure that it doesn't go back out
371: * on the interface it came in on. Also, if we
372: * are going to physically broadcast this, let us
373: * age the packet so we can eat it safely the second time around.
374: */
375: if (idp->idp_dna.x_host.c_host[0] & 0x1) {
376: struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
377: struct ifnet *ifp;
378: if (ia) {
379: /* I'm gonna hafta eat this packet */
380: agedelta += NS_MAXHOPS - idp->idp_tc;
381: idp->idp_tc = NS_MAXHOPS;
382: }
383: if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
384: /* error = ENETUNREACH; He'll never get it! */
385: m_freem(m);
386: goto cleanup;
387: }
388: if (idp_droute.ro_rt &&
389: (ifp=idp_droute.ro_rt->rt_ifp) &&
390: idp_sroute.ro_rt &&
391: (ifp!=idp_sroute.ro_rt->rt_ifp)) {
392: flags |= NS_ALLOWBROADCAST;
393: } else {
394: type = NS_ERR_UNREACH_HOST, code = 0;
395: goto senderror;
396: }
397: }
398: /* need to adjust checksum */
399: if (idp->idp_sum!=0xffff) {
400: union bytes {
401: u_char c[4];
402: u_short s[2];
403: long l;
404: } x;
405: register int shift;
406: x.l = 0; x.c[0] = agedelta;
407: shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
408: x.l = idp->idp_sum + (x.s[0] << shift);
409: x.l = x.s[0] + x.s[1];
410: x.l = x.s[0] + x.s[1];
411: if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
412: }
413: if ((error = ns_output(m, &idp_droute, flags)) &&
414: (mcopy!=NULL)) {
415: idp = mtod(mcopy, struct idp *);
416: type = NS_ERR_UNSPEC_T, code = 0;
417: switch (error) {
418:
419: case ENETUNREACH:
420: case EHOSTDOWN:
421: case EHOSTUNREACH:
422: case ENETDOWN:
423: case EPERM:
424: type = NS_ERR_UNREACH_HOST;
425: break;
426:
427: case EMSGSIZE:
428: type = NS_ERR_TOO_BIG;
429: code = 576; /* too hard to figure out mtu here */
430: break;
431:
432: case ENOBUFS:
433: type = NS_ERR_UNSPEC_T;
434: break;
435: }
436: mcopy = NULL;
437: senderror:
438: ns_error(m, type, code);
439: }
440: cleanup:
441: if (ok_there)
442: idp_undo_route(&idp_droute);
443: if (ok_back)
444: idp_undo_route(&idp_sroute);
445: if (mcopy != NULL)
446: m_freem(mcopy);
447: }
448:
449: idp_do_route(src, ro)
450: struct ns_addr *src;
451: struct route *ro;
452: {
453:
454: struct sockaddr_ns *dst;
455:
456: bzero((caddr_t)ro, sizeof (*ro));
457: dst = (struct sockaddr_ns *)&ro->ro_dst;
458:
459: dst->sns_len = sizeof(*dst);
460: dst->sns_family = AF_NS;
461: dst->sns_addr = *src;
462: dst->sns_addr.x_port = 0;
463: rtalloc(ro);
464: if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
465: return (0);
466: }
467: ro->ro_rt->rt_use++;
468: return (1);
469: }
470:
471: idp_undo_route(ro)
472: register struct route *ro;
473: {
474: if (ro->ro_rt) {RTFREE(ro->ro_rt);}
475: }
476:
477: ns_watch_output(m, ifp)
478: struct mbuf *m;
479: struct ifnet *ifp;
480: {
481: register struct nspcb *nsp;
482: register struct ifaddr *ifa;
483: /*
484: * Give any raw listeners a crack at the packet
485: */
486: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
487: struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
488: if (m0) {
489: register struct idp *idp;
490:
491: M_PREPEND(m0, sizeof (*idp), M_DONTWAIT);
492: if (m0 == NULL)
493: continue;
494: idp = mtod(m0, struct idp *);
495: idp->idp_sna.x_net = ns_zeronet;
496: idp->idp_sna.x_host = ns_thishost;
497: if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
498: for(ifa = ifp->if_addrlist; ifa;
499: ifa = ifa->ifa_next) {
500: if (ifa->ifa_addr->sa_family==AF_NS) {
501: idp->idp_sna = IA_SNS(ifa)->sns_addr;
502: break;
503: }
504: }
505: idp->idp_len = ntohl(m0->m_pkthdr.len);
506: idp_input(m0, nsp);
507: }
508: }
509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.