Annotation of src/sys/net/if_ethersubr.c, Revision 1.47
1.47 ! itojun 1: /* $NetBSD: if_ethersubr.c,v 1.46 1999/08/05 02:07:39 thorpej Exp $ */
1.44 itojun 2:
3: /*
4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. Neither the name of the project nor the names of its contributors
16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
1.9 cgd 31:
1.1 cgd 32: /*
1.8 mycroft 33: * Copyright (c) 1982, 1989, 1993
34: * The Regents of the University of California. All rights reserved.
1.1 cgd 35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the University of
47: * California, Berkeley and its contributors.
48: * 4. Neither the name of the University nor the names of its contributors
49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: *
1.27 fvdl 64: * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96
1.1 cgd 65: */
66:
1.33 jonathan 67: #include "opt_inet.h"
68: #include "opt_atalk.h"
1.34 jonathan 69: #include "opt_ccitt.h"
1.35 jonathan 70: #include "opt_llc.h"
1.36 jonathan 71: #include "opt_iso.h"
1.37 jonathan 72: #include "opt_ns.h"
1.30 matt 73: #include "opt_gateway.h"
74:
1.4 mycroft 75: #include <sys/param.h>
76: #include <sys/systm.h>
77: #include <sys/kernel.h>
78: #include <sys/malloc.h>
79: #include <sys/mbuf.h>
80: #include <sys/protosw.h>
81: #include <sys/socket.h>
82: #include <sys/ioctl.h>
83: #include <sys/errno.h>
84: #include <sys/syslog.h>
85:
1.8 mycroft 86: #include <machine/cpu.h>
87:
1.4 mycroft 88: #include <net/if.h>
89: #include <net/netisr.h>
90: #include <net/route.h>
91: #include <net/if_llc.h>
92: #include <net/if_dl.h>
1.8 mycroft 93: #include <net/if_types.h>
1.1 cgd 94:
1.22 is 95: #include <net/if_ether.h>
96:
1.15 phil 97: #include <netinet/in.h>
1.1 cgd 98: #ifdef INET
1.4 mycroft 99: #include <netinet/in_var.h>
1.1 cgd 100: #endif
1.22 is 101: #include <netinet/if_inarp.h>
1.1 cgd 102:
1.44 itojun 103: #ifdef INET6
104: #ifndef INET
105: #include <netinet/in.h>
106: #endif
107: #include <netinet6/in6_var.h>
108: #include <netinet6/nd6.h>
1.47 ! itojun 109: #include <netinet6/in6_ifattach.h>
1.44 itojun 110: #endif
111:
1.1 cgd 112: #ifdef NS
1.4 mycroft 113: #include <netns/ns.h>
114: #include <netns/ns_if.h>
1.1 cgd 115: #endif
116:
1.32 christos 117: #ifdef IPX
118: #include <netipx/ipx.h>
119: #include <netipx/ipx_if.h>
120: #endif
121:
1.1 cgd 122: #ifdef ISO
1.4 mycroft 123: #include <netiso/argo_debug.h>
124: #include <netiso/iso.h>
125: #include <netiso/iso_var.h>
126: #include <netiso/iso_snpac.h>
1.1 cgd 127: #endif
1.4 mycroft 128:
1.8 mycroft 129: #ifdef LLC
130: #include <netccitt/dll.h>
131: #include <netccitt/llc_var.h>
132: #endif
133:
134: #if defined(LLC) && defined(CCITT)
135: extern struct ifqueue pkintrq;
136: #endif
1.1 cgd 137:
1.23 christos 138: #ifdef NETATALK
139: #include <netatalk/at.h>
140: #include <netatalk/at_var.h>
141: #include <netatalk/at_extern.h>
142:
143: #define llc_snap_org_code llc_un.type_snap.org_code
144: #define llc_snap_ether_type llc_un.type_snap.ether_type
145:
146: extern u_char at_org_code[3];
147: extern u_char aarp_org_code[3];
148: #endif /* NETATALK */
149:
1.1 cgd 150: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1.8 mycroft 151: #define senderr(e) { error = (e); goto bad;}
1.1 cgd 152:
1.22 is 153: #define SIN(x) ((struct sockaddr_in *)x)
154:
1.42 thorpej 155: static int ether_output __P((struct ifnet *, struct mbuf *,
156: struct sockaddr *, struct rtentry *));
157: static void ether_input __P((struct ifnet *, struct mbuf *));
158:
1.1 cgd 159: /*
160: * Ethernet output routine.
161: * Encapsulate a packet of type family for the local net.
1.22 is 162: * Assumes that ifp is actually pointer to ethercom structure.
1.1 cgd 163: */
1.42 thorpej 164: static int
1.8 mycroft 165: ether_output(ifp, m0, dst, rt0)
1.29 mrg 166: struct ifnet *ifp;
1.1 cgd 167: struct mbuf *m0;
168: struct sockaddr *dst;
1.8 mycroft 169: struct rtentry *rt0;
1.1 cgd 170: {
1.10 cgd 171: u_int16_t etype;
1.31 thorpej 172: int s, error = 0, hdrcmplt = 0;
173: u_char esrc[6], edst[6];
1.29 mrg 174: struct mbuf *m = m0;
175: struct rtentry *rt;
1.1 cgd 176: struct mbuf *mcopy = (struct mbuf *)0;
1.29 mrg 177: struct ether_header *eh;
1.24 christos 178: #ifdef INET
1.22 is 179: struct arphdr *ah;
1.24 christos 180: #endif /* INET */
1.23 christos 181: #ifdef NETATALK
182: struct at_ifaddr *aa;
183: #endif /* NETATALK */
1.1 cgd 184:
1.8 mycroft 185: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
186: senderr(ENETDOWN);
187: ifp->if_lastchange = time;
1.18 christos 188: if ((rt = rt0) != NULL) {
1.8 mycroft 189: if ((rt->rt_flags & RTF_UP) == 0) {
1.27 fvdl 190: if ((rt0 = rt = rtalloc1(dst, 1)) != NULL) {
1.8 mycroft 191: rt->rt_refcnt--;
1.27 fvdl 192: if (rt->rt_ifp != ifp)
193: return (*rt->rt_ifp->if_output)
194: (ifp, m0, dst, rt);
195: } else
1.8 mycroft 196: senderr(EHOSTUNREACH);
197: }
1.27 fvdl 198: if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS) {
1.8 mycroft 199: if (rt->rt_gwroute == 0)
200: goto lookup;
201: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
202: rtfree(rt); rt = rt0;
203: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
204: if ((rt = rt->rt_gwroute) == 0)
205: senderr(EHOSTUNREACH);
1.27 fvdl 206: /* the "G" test below also prevents rt == rt0 */
207: if ((rt->rt_flags & RTF_GATEWAY) ||
208: (rt->rt_ifp != ifp)) {
209: rt->rt_refcnt--;
210: rt0->rt_gwroute = 0;
211: senderr(EHOSTUNREACH);
212: }
1.8 mycroft 213: }
214: }
215: if (rt->rt_flags & RTF_REJECT)
216: if (rt->rt_rmx.rmx_expire == 0 ||
217: time.tv_sec < rt->rt_rmx.rmx_expire)
218: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
1.1 cgd 219: }
220: switch (dst->sa_family) {
221:
222: #ifdef INET
223: case AF_INET:
1.22 is 224: if (m->m_flags & M_BCAST)
225: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
226: sizeof(edst));
227:
228: else if (m->m_flags & M_MCAST) {
229: ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
230: (caddr_t)edst)
231:
232: } else if (!arpresolve(ifp, rt, m, dst, edst))
1.1 cgd 233: return (0); /* if not yet resolved */
1.3 hpeyerl 234: /* If broadcasting on a simplex interface, loopback a copy */
235: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
1.1 cgd 236: mcopy = m_copy(m, 0, (int)M_COPYALL);
1.17 mycroft 237: etype = htons(ETHERTYPE_IP);
1.8 mycroft 238: break;
1.22 is 239:
240: case AF_ARP:
241: ah = mtod(m, struct arphdr *);
242: if (m->m_flags & M_BCAST)
243: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
244: sizeof(edst));
245: else
246: bcopy((caddr_t)ar_tha(ah),
247: (caddr_t)edst, sizeof(edst));
248:
249: ah->ar_hrd = htons(ARPHRD_ETHER);
250:
251: switch(ntohs(ah->ar_op)) {
252: case ARPOP_REVREQUEST:
253: case ARPOP_REVREPLY:
254: etype = htons(ETHERTYPE_REVARP);
255: break;
256:
257: case ARPOP_REQUEST:
258: case ARPOP_REPLY:
259: default:
260: etype = htons(ETHERTYPE_ARP);
261: }
262:
263: break;
1.1 cgd 264: #endif
1.44 itojun 265: #ifdef INET6
266: case AF_INET6:
267: #ifdef NEWIP6OUTPUT
268: if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
269: return(0); /* it must be impossible, but... */
270: #else
271: if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst))
272: return(0); /* if not yet resolves */
273: #endif /* NEWIP6OUTPUT */
274: etype = htons(ETHERTYPE_IPV6);
275: break;
276: #endif
1.23 christos 277: #ifdef NETATALK
278: case AF_APPLETALK:
279: if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
280: #ifdef NETATALKDEBUG
281: printf("aarpresolv failed\n");
282: #endif /* NETATALKDEBUG */
283: return (0);
284: }
285: /*
286: * ifaddr is the first thing in at_ifaddr
287: */
288: aa = (struct at_ifaddr *) at_ifawithnet(
1.25 christos 289: (struct sockaddr_at *)dst, ifp);
1.23 christos 290: if (aa == NULL)
291: goto bad;
292:
293: /*
294: * In the phase 2 case, we need to prepend an mbuf for the
295: * llc header. Since we must preserve the value of m,
296: * which is passed to us by value, we m_copy() the first
297: * mbuf, and use it for our llc header.
298: */
299: if (aa->aa_flags & AFA_PHASE2) {
300: struct llc llc;
301:
1.43 bouyer 302: M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
1.23 christos 303: llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
304: llc.llc_control = LLC_UI;
305: bcopy(at_org_code, llc.llc_snap_org_code,
306: sizeof(llc.llc_snap_org_code));
1.38 kim 307: llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
1.23 christos 308: bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
309: etype = htons(m->m_pkthdr.len);
310: } else {
1.38 kim 311: etype = htons(ETHERTYPE_ATALK);
1.23 christos 312: }
313: break;
314: #endif /* NETATALK */
1.1 cgd 315: #ifdef NS
316: case AF_NS:
1.17 mycroft 317: etype = htons(ETHERTYPE_NS);
1.1 cgd 318: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
319: (caddr_t)edst, sizeof (edst));
320: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
321: return (looutput(ifp, m, dst, rt));
1.3 hpeyerl 322: /* If broadcasting on a simplex interface, loopback a copy */
323: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
1.1 cgd 324: mcopy = m_copy(m, 0, (int)M_COPYALL);
1.8 mycroft 325: break;
1.1 cgd 326: #endif
1.32 christos 327: #ifdef IPX
328: case AF_IPX:
1.39 christos 329: etype = htons(ETHERTYPE_IPX);
330: bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
1.32 christos 331: (caddr_t)edst, sizeof (edst));
332: /* If broadcasting on a simplex interface, loopback a copy */
333: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
334: mcopy = m_copy(m, 0, (int)M_COPYALL);
335: break;
336: #endif
1.1 cgd 337: #ifdef ISO
338: case AF_ISO: {
339: int snpalen;
340: struct llc *l;
1.29 mrg 341: struct sockaddr_dl *sdl;
1.1 cgd 342:
1.8 mycroft 343: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
344: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
345: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
1.18 christos 346: } else {
347: error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
348: (char *)edst, &snpalen);
349: if (error)
350: goto bad; /* Not Resolved */
351: }
1.3 hpeyerl 352: /* If broadcasting on a simplex interface, loopback a copy */
1.8 mycroft 353: if (*edst & 1)
354: m->m_flags |= (M_BCAST|M_MCAST);
1.3 hpeyerl 355: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
1.1 cgd 356: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
357: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
358: if (mcopy) {
359: eh = mtod(mcopy, struct ether_header *);
360: bcopy((caddr_t)edst,
361: (caddr_t)eh->ether_dhost, sizeof (edst));
1.22 is 362: bcopy(LLADDR(ifp->if_sadl),
1.1 cgd 363: (caddr_t)eh->ether_shost, sizeof (edst));
364: }
365: }
366: M_PREPEND(m, 3, M_DONTWAIT);
367: if (m == NULL)
368: return (0);
1.17 mycroft 369: etype = htons(m->m_pkthdr.len);
1.1 cgd 370: l = mtod(m, struct llc *);
371: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
372: l->llc_control = LLC_UI;
1.18 christos 373: #ifdef ARGO_DEBUG
374: if (argo_debug[D_ETHER]) {
1.1 cgd 375: int i;
1.21 christos 376: printf("unoutput: sending pkt to: ");
1.1 cgd 377: for (i=0; i<6; i++)
1.21 christos 378: printf("%x ", edst[i] & 0xff);
379: printf("\n");
1.18 christos 380: }
381: #endif
1.8 mycroft 382: } break;
383: #endif /* ISO */
384: #ifdef LLC
385: /* case AF_NSAP: */
386: case AF_CCITT: {
1.29 mrg 387: struct sockaddr_dl *sdl =
1.8 mycroft 388: (struct sockaddr_dl *) rt -> rt_gateway;
389:
390: if (sdl && sdl->sdl_family == AF_LINK
391: && sdl->sdl_alen > 0) {
392: bcopy(LLADDR(sdl), (char *)edst,
393: sizeof(edst));
394: } else goto bad; /* Not a link interface ? Funny ... */
395: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
396: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
397: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
398: if (mcopy) {
399: eh = mtod(mcopy, struct ether_header *);
400: bcopy((caddr_t)edst,
401: (caddr_t)eh->ether_dhost, sizeof (edst));
1.22 is 402: bcopy(LLADDR(ifp->if_sadl),
1.8 mycroft 403: (caddr_t)eh->ether_shost, sizeof (edst));
404: }
1.3 hpeyerl 405: }
1.17 mycroft 406: etype = htons(m->m_pkthdr.len);
1.8 mycroft 407: #ifdef LLC_DEBUG
408: {
409: int i;
1.29 mrg 410: struct llc *l = mtod(m, struct llc *);
1.8 mycroft 411:
1.21 christos 412: printf("ether_output: sending LLC2 pkt to: ");
1.8 mycroft 413: for (i=0; i<6; i++)
1.21 christos 414: printf("%x ", edst[i] & 0xff);
415: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
1.17 mycroft 416: m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
417: l->llc_control & 0xff);
1.8 mycroft 418:
419: }
420: #endif /* LLC_DEBUG */
421: } break;
422: #endif /* LLC */
1.1 cgd 423:
1.31 thorpej 424: case pseudo_AF_HDRCMPLT:
425: hdrcmplt = 1;
426: eh = (struct ether_header *)dst->sa_data;
427: bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (esrc));
428: /* FALLTHROUGH */
429:
1.1 cgd 430: case AF_UNSPEC:
431: eh = (struct ether_header *)dst->sa_data;
432: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
1.8 mycroft 433: /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
1.17 mycroft 434: etype = eh->ether_type;
1.8 mycroft 435: break;
1.1 cgd 436:
437: default:
1.21 christos 438: printf("%s: can't handle af%d\n", ifp->if_xname,
1.1 cgd 439: dst->sa_family);
1.8 mycroft 440: senderr(EAFNOSUPPORT);
1.1 cgd 441: }
442:
443: if (mcopy)
444: (void) looutput(ifp, mcopy, dst, rt);
1.16 mycroft 445:
1.1 cgd 446: /*
447: * Add local net header. If no space in first mbuf,
448: * allocate another.
449: */
450: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
1.8 mycroft 451: if (m == 0)
452: senderr(ENOBUFS);
1.1 cgd 453: eh = mtod(m, struct ether_header *);
1.8 mycroft 454: bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
1.1 cgd 455: sizeof(eh->ether_type));
456: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
1.31 thorpej 457: if (hdrcmplt)
458: bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
459: sizeof(eh->ether_shost));
460: else
461: bcopy(LLADDR(ifp->if_sadl), (caddr_t)eh->ether_shost,
462: sizeof(eh->ether_shost));
1.1 cgd 463: s = splimp();
464: /*
465: * Queue message on interface, and start output if interface
466: * not yet active.
467: */
468: if (IF_QFULL(&ifp->if_snd)) {
469: IF_DROP(&ifp->if_snd);
470: splx(s);
1.8 mycroft 471: senderr(ENOBUFS);
1.1 cgd 472: }
1.14 mycroft 473: ifp->if_obytes += m->m_pkthdr.len;
1.1 cgd 474: IF_ENQUEUE(&ifp->if_snd, m);
475: if ((ifp->if_flags & IFF_OACTIVE) == 0)
476: (*ifp->if_start)(ifp);
477: splx(s);
1.3 hpeyerl 478: if (m->m_flags & M_MCAST)
1.1 cgd 479: ifp->if_omcasts++;
480: return (error);
481:
482: bad:
483: if (m)
484: m_freem(m);
485: return (error);
486: }
487:
488: /*
489: * Process a received Ethernet packet;
1.42 thorpej 490: * the packet is in the mbuf chain m with
491: * the ether header.
1.1 cgd 492: */
1.42 thorpej 493: static void
494: ether_input(ifp, m)
1.1 cgd 495: struct ifnet *ifp;
496: struct mbuf *m;
497: {
1.29 mrg 498: struct ifqueue *inq;
1.18 christos 499: u_int16_t etype;
500: int s;
1.42 thorpej 501: struct ether_header *eh;
1.23 christos 502: #if defined (ISO) || defined (LLC) || defined(NETATALK)
1.29 mrg 503: struct llc *l;
1.18 christos 504: #endif
1.1 cgd 505:
1.8 mycroft 506: if ((ifp->if_flags & IFF_UP) == 0) {
507: m_freem(m);
508: return;
509: }
1.42 thorpej 510:
511: eh = mtod(m, struct ether_header *);
512:
1.1 cgd 513: ifp->if_lastchange = time;
1.42 thorpej 514: ifp->if_ibytes += m->m_pkthdr.len;
1.8 mycroft 515: if (eh->ether_dhost[0] & 1) {
516: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
517: sizeof(etherbroadcastaddr)) == 0)
518: m->m_flags |= M_BCAST;
519: else
520: m->m_flags |= M_MCAST;
521: }
1.1 cgd 522: if (m->m_flags & (M_BCAST|M_MCAST))
523: ifp->if_imcasts++;
524:
1.5 deraadt 525: etype = ntohs(eh->ether_type);
1.42 thorpej 526:
527: /* Strip off the Ethernet header. */
528: m_adj(m, sizeof(struct ether_header));
1.45 thorpej 529:
530: /* If the CRC is still on the packet, trim it off. */
1.46 thorpej 531: if (m->m_flags & M_HASFCS)
1.45 thorpej 532: m_adj(m, -ETHER_CRC_LEN);
1.42 thorpej 533:
1.5 deraadt 534: switch (etype) {
1.1 cgd 535: #ifdef INET
536: case ETHERTYPE_IP:
1.30 matt 537: #ifdef GATEWAY
538: if (ipflow_fastforward(m))
539: return;
540: #endif
1.1 cgd 541: schednetisr(NETISR_IP);
542: inq = &ipintrq;
543: break;
544:
545: case ETHERTYPE_ARP:
1.8 mycroft 546: schednetisr(NETISR_ARP);
547: inq = &arpintrq;
548: break;
1.7 glass 549:
550: case ETHERTYPE_REVARP:
1.8 mycroft 551: revarpinput(m); /* XXX queue? */
1.1 cgd 552: return;
553: #endif
1.44 itojun 554: #ifdef INET6
555: case ETHERTYPE_IPV6:
556: schednetisr(NETISR_IPV6);
557: inq = &ip6intrq;
558: break;
559: #endif
1.1 cgd 560: #ifdef NS
561: case ETHERTYPE_NS:
562: schednetisr(NETISR_NS);
563: inq = &nsintrq;
564: break;
565:
1.32 christos 566: #endif
567: #ifdef IPX
568: case ETHERTYPE_IPX:
569: schednetisr(NETISR_IPX);
570: inq = &ipxintrq;
571: break;
1.1 cgd 572: #endif
1.23 christos 573: #ifdef NETATALK
1.38 kim 574: case ETHERTYPE_ATALK:
1.23 christos 575: schednetisr(NETISR_ATALK);
576: inq = &atintrq1;
577: break;
578: case ETHERTYPE_AARP:
579: /* probably this should be done with a NETISR as well */
580: aarpinput(ifp, m); /* XXX */
581: return;
582: #endif /* NETATALK */
1.1 cgd 583: default:
1.23 christos 584: #if defined (ISO) || defined (LLC) || defined (NETATALK)
1.11 mycroft 585: if (etype > ETHERMTU)
1.1 cgd 586: goto dropanyway;
587: l = mtod(m, struct llc *);
1.8 mycroft 588: switch (l->llc_dsap) {
1.23 christos 589: #ifdef NETATALK
590: case LLC_SNAP_LSAP:
591: switch (l->llc_control) {
592: case LLC_UI:
593: if (l->llc_ssap != LLC_SNAP_LSAP) {
594: goto dropanyway;
595: }
596:
597: if (Bcmp(&(l->llc_snap_org_code)[0],
598: at_org_code, sizeof(at_org_code)) == 0 &&
599: ntohs(l->llc_snap_ether_type) ==
1.38 kim 600: ETHERTYPE_ATALK) {
1.23 christos 601: inq = &atintrq2;
602: m_adj(m, sizeof(struct llc));
603: schednetisr(NETISR_ATALK);
604: break;
605: }
606:
607: if (Bcmp(&(l->llc_snap_org_code)[0],
608: aarp_org_code,
609: sizeof(aarp_org_code)) == 0 &&
610: ntohs(l->llc_snap_ether_type) ==
611: ETHERTYPE_AARP) {
612: m_adj( m, sizeof(struct llc));
613: aarpinput(ifp, m); /* XXX */
614: return;
615: }
616:
617: default:
618: goto dropanyway;
619: }
620: break;
621: #endif /* NETATALK */
1.8 mycroft 622: #ifdef ISO
623: case LLC_ISO_LSAP:
624: switch (l->llc_control) {
625: case LLC_UI:
626: /* LLC_UI_P forbidden in class 1 service */
627: if ((l->llc_dsap == LLC_ISO_LSAP) &&
628: (l->llc_ssap == LLC_ISO_LSAP)) {
629: /* LSAP for ISO */
1.11 mycroft 630: if (m->m_pkthdr.len > etype)
631: m_adj(m, etype - m->m_pkthdr.len);
1.8 mycroft 632: m->m_data += 3; /* XXX */
633: m->m_len -= 3; /* XXX */
634: m->m_pkthdr.len -= 3; /* XXX */
635: M_PREPEND(m, sizeof *eh, M_DONTWAIT);
636: if (m == 0)
637: return;
638: *mtod(m, struct ether_header *) = *eh;
1.18 christos 639: #ifdef ARGO_DEBUG
640: if (argo_debug[D_ETHER])
1.21 christos 641: printf("clnp packet");
1.18 christos 642: #endif
1.8 mycroft 643: schednetisr(NETISR_ISO);
644: inq = &clnlintrq;
645: break;
646: }
647: goto dropanyway;
648:
649: case LLC_XID:
650: case LLC_XID_P:
651: if(m->m_len < 6)
652: goto dropanyway;
653: l->llc_window = 0;
654: l->llc_fid = 9;
655: l->llc_class = 1;
656: l->llc_dsap = l->llc_ssap = 0;
657: /* Fall through to */
658: case LLC_TEST:
659: case LLC_TEST_P:
660: {
661: struct sockaddr sa;
1.29 mrg 662: struct ether_header *eh2;
1.8 mycroft 663: int i;
664: u_char c = l->llc_dsap;
665:
666: l->llc_dsap = l->llc_ssap;
667: l->llc_ssap = c;
668: if (m->m_flags & (M_BCAST | M_MCAST))
1.22 is 669: bcopy(LLADDR(ifp->if_sadl),
1.8 mycroft 670: (caddr_t)eh->ether_dhost, 6);
671: sa.sa_family = AF_UNSPEC;
672: sa.sa_len = sizeof(sa);
673: eh2 = (struct ether_header *)sa.sa_data;
674: for (i = 0; i < 6; i++) {
1.22 is 675: eh2->ether_shost[i] = c =
676: eh->ether_dhost[i];
1.8 mycroft 677: eh2->ether_dhost[i] =
1.22 is 678: eh->ether_dhost[i] =
679: eh->ether_shost[i];
1.8 mycroft 680: eh->ether_shost[i] = c;
681: }
682: ifp->if_output(ifp, m, &sa, NULL);
683: return;
684: }
685: default:
686: m_freem(m);
687: return;
688: }
689: break;
690: #endif /* ISO */
691: #ifdef LLC
692: case LLC_X25_LSAP:
693: {
1.11 mycroft 694: if (m->m_pkthdr.len > etype)
695: m_adj(m, etype - m->m_pkthdr.len);
1.8 mycroft 696: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
1.1 cgd 697: if (m == 0)
698: return;
1.8 mycroft 699: if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
700: eh->ether_dhost, LLC_X25_LSAP, 6,
701: mtod(m, struct sdl_hdr *)))
702: panic("ETHER cons addr failure");
1.11 mycroft 703: mtod(m, struct sdl_hdr *)->sdlhdr_len = etype;
1.8 mycroft 704: #ifdef LLC_DEBUG
1.21 christos 705: printf("llc packet\n");
1.8 mycroft 706: #endif /* LLC_DEBUG */
707: schednetisr(NETISR_CCITT);
708: inq = &llcintrq;
1.1 cgd 709: break;
710: }
1.8 mycroft 711: #endif /* LLC */
1.1 cgd 712: dropanyway:
713: default:
1.8 mycroft 714: m_freem(m);
715: return;
716: }
1.23 christos 717: #else /* ISO || LLC || NETATALK*/
1.1 cgd 718: m_freem(m);
719: return;
1.23 christos 720: #endif /* ISO || LLC || NETATALK*/
1.1 cgd 721: }
722:
723: s = splimp();
724: if (IF_QFULL(inq)) {
725: IF_DROP(inq);
726: m_freem(m);
727: } else
728: IF_ENQUEUE(inq, m);
729: splx(s);
730: }
731:
732: /*
733: * Convert Ethernet address to printable (loggable) representation.
734: */
735: static char digits[] = "0123456789abcdef";
736: char *
737: ether_sprintf(ap)
1.40 thorpej 738: const u_char *ap;
1.1 cgd 739: {
740: static char etherbuf[18];
1.29 mrg 741: char *cp = etherbuf;
742: int i;
1.1 cgd 743:
744: for (i = 0; i < 6; i++) {
745: *cp++ = digits[*ap >> 4];
746: *cp++ = digits[*ap++ & 0xf];
747: *cp++ = ':';
748: }
749: *--cp = 0;
750: return (etherbuf);
751: }
1.8 mycroft 752:
753: /*
754: * Perform common duties while attaching to interface list
755: */
756: void
1.22 is 757: ether_ifattach(ifp, lla)
1.29 mrg 758: struct ifnet *ifp;
1.41 thorpej 759: const u_int8_t *lla;
1.8 mycroft 760: {
1.29 mrg 761: struct sockaddr_dl *sdl;
1.8 mycroft 762:
763: ifp->if_type = IFT_ETHER;
764: ifp->if_addrlen = 6;
765: ifp->if_hdrlen = 14;
766: ifp->if_mtu = ETHERMTU;
1.12 mycroft 767: ifp->if_output = ether_output;
1.42 thorpej 768: ifp->if_input = ether_input;
1.22 is 769: if ((sdl = ifp->if_sadl) &&
770: sdl->sdl_family == AF_LINK) {
771: sdl->sdl_type = IFT_ETHER;
772: sdl->sdl_alen = ifp->if_addrlen;
1.41 thorpej 773: bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
1.22 is 774: }
775: LIST_INIT(&((struct ethercom *)ifp)->ec_multiaddrs);
1.26 is 776: ifp->if_broadcastaddr = etherbroadcastaddr;
1.47 ! itojun 777: #ifdef INET6
! 778: in6_ifattach_getifid(ifp);
! 779: #endif
1.8 mycroft 780: }
781:
1.3 hpeyerl 782: u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
783: u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
1.44 itojun 784: #ifdef INET6
785: u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
786: u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
787: #endif
1.3 hpeyerl 788: /*
789: * Add an Ethernet multicast address or range of addresses to the list for a
790: * given interface.
791: */
792: int
1.22 is 793: ether_addmulti(ifr, ec)
1.3 hpeyerl 794: struct ifreq *ifr;
1.29 mrg 795: struct ethercom *ec;
1.3 hpeyerl 796: {
1.29 mrg 797: struct ether_multi *enm;
1.24 christos 798: #ifdef INET
1.3 hpeyerl 799: struct sockaddr_in *sin;
1.24 christos 800: #endif /* INET */
1.44 itojun 801: #ifdef INET6
802: struct sockaddr_in6 *sin6;
803: #endif /* INET6 */
1.3 hpeyerl 804: u_char addrlo[6];
805: u_char addrhi[6];
806: int s = splimp();
807:
808: switch (ifr->ifr_addr.sa_family) {
809:
810: case AF_UNSPEC:
811: bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
812: bcopy(addrlo, addrhi, 6);
813: break;
814:
815: #ifdef INET
816: case AF_INET:
817: sin = (struct sockaddr_in *)&(ifr->ifr_addr);
818: if (sin->sin_addr.s_addr == INADDR_ANY) {
819: /*
820: * An IP address of INADDR_ANY means listen to all
821: * of the Ethernet multicast addresses used for IP.
822: * (This is for the sake of IP multicast routers.)
823: */
824: bcopy(ether_ipmulticast_min, addrlo, 6);
825: bcopy(ether_ipmulticast_max, addrhi, 6);
826: }
827: else {
828: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
829: bcopy(addrlo, addrhi, 6);
830: }
831: break;
832: #endif
1.44 itojun 833: #ifdef INET6
834: case AF_INET6:
835: sin6 = (struct sockaddr_in6 *)
836: &(((struct in6_ifreq *)ifr)->ifr_addr);
1.47 ! itojun 837: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1.44 itojun 838: /*
839: * An IP6 address of 0 means listen to all
840: * of the Ethernet multicast address used for IP6.
841: * (This is used for multicast routers.)
842: */
843: bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
844: bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
845: #if 0
846: set_allmulti = 1;
847: #endif
848: } else {
849: ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
850: bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
851: }
852: break;
853: #endif
1.3 hpeyerl 854:
855: default:
856: splx(s);
857: return (EAFNOSUPPORT);
858: }
859:
860: /*
861: * Verify that we have valid Ethernet multicast addresses.
862: */
863: if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
864: splx(s);
865: return (EINVAL);
866: }
867: /*
868: * See if the address range is already in the list.
869: */
1.22 is 870: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 871: if (enm != NULL) {
872: /*
873: * Found it; just increment the reference count.
874: */
875: ++enm->enm_refcount;
876: splx(s);
877: return (0);
878: }
879: /*
880: * New address or range; malloc a new multicast record
881: * and link it into the interface's multicast list.
882: */
883: enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
884: if (enm == NULL) {
885: splx(s);
886: return (ENOBUFS);
887: }
888: bcopy(addrlo, enm->enm_addrlo, 6);
889: bcopy(addrhi, enm->enm_addrhi, 6);
1.22 is 890: enm->enm_ec = ec;
1.3 hpeyerl 891: enm->enm_refcount = 1;
1.22 is 892: LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list);
893: ec->ec_multicnt++;
1.3 hpeyerl 894: splx(s);
895: /*
896: * Return ENETRESET to inform the driver that the list has changed
897: * and its reception filter should be adjusted accordingly.
898: */
899: return (ENETRESET);
900: }
901:
902: /*
903: * Delete a multicast address record.
904: */
905: int
1.22 is 906: ether_delmulti(ifr, ec)
1.3 hpeyerl 907: struct ifreq *ifr;
1.29 mrg 908: struct ethercom *ec;
1.3 hpeyerl 909: {
1.29 mrg 910: struct ether_multi *enm;
1.24 christos 911: #ifdef INET
1.3 hpeyerl 912: struct sockaddr_in *sin;
1.24 christos 913: #endif /* INET */
1.44 itojun 914: #ifdef INET6
915: struct sockaddr_in6 *sin6;
916: #endif /* INET6 */
1.3 hpeyerl 917: u_char addrlo[6];
918: u_char addrhi[6];
919: int s = splimp();
920:
921: switch (ifr->ifr_addr.sa_family) {
922:
923: case AF_UNSPEC:
924: bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
925: bcopy(addrlo, addrhi, 6);
926: break;
927:
928: #ifdef INET
929: case AF_INET:
930: sin = (struct sockaddr_in *)&(ifr->ifr_addr);
931: if (sin->sin_addr.s_addr == INADDR_ANY) {
932: /*
933: * An IP address of INADDR_ANY means stop listening
934: * to the range of Ethernet multicast addresses used
935: * for IP.
936: */
937: bcopy(ether_ipmulticast_min, addrlo, 6);
938: bcopy(ether_ipmulticast_max, addrhi, 6);
939: }
940: else {
941: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
942: bcopy(addrlo, addrhi, 6);
1.44 itojun 943: }
944: break;
945: #endif
946: #ifdef INET6
947: case AF_INET6:
948: sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);
1.47 ! itojun 949: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1.44 itojun 950: /*
951: * An IP6 address of all 0 means stop listening
952: * to the range of Ethernet multicast addresses used
953: * for IP6
954: */
955: bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
956: bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
957: } else {
958: ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
959: bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1.3 hpeyerl 960: }
961: break;
962: #endif
963:
964: default:
965: splx(s);
966: return (EAFNOSUPPORT);
967: }
968:
969: /*
970: * Look up the address in our list.
971: */
1.22 is 972: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 973: if (enm == NULL) {
974: splx(s);
975: return (ENXIO);
976: }
977: if (--enm->enm_refcount != 0) {
978: /*
979: * Still some claims to this record.
980: */
981: splx(s);
982: return (0);
983: }
984: /*
985: * No remaining claims to this record; unlink and free it.
986: */
1.13 mycroft 987: LIST_REMOVE(enm, enm_list);
1.3 hpeyerl 988: free(enm, M_IFMADDR);
1.22 is 989: ec->ec_multicnt--;
1.3 hpeyerl 990: splx(s);
991: /*
992: * Return ENETRESET to inform the driver that the list has changed
993: * and its reception filter should be adjusted accordingly.
994: */
995: return (ENETRESET);
996: }
CVSweb <webmaster@jp.NetBSD.org>