Annotation of src/sys/net/if_ethersubr.c, Revision 1.129.2.1
1.129.2.1! tron 1: /* $NetBSD$ */
1.44 itojun 2:
3: /*
4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5: * All rights reserved.
1.120 perry 6: *
1.44 itojun 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.
1.120 perry 18: *
1.44 itojun 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.
1.113 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: *
1.27 fvdl 60: * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96
1.1 cgd 61: */
1.90 lukem 62:
63: #include <sys/cdefs.h>
1.129.2.1! tron 64: __KERNEL_RCSID(0, "$NetBSD$");
1.1 cgd 65:
1.33 jonathan 66: #include "opt_inet.h"
67: #include "opt_atalk.h"
1.34 jonathan 68: #include "opt_ccitt.h"
1.35 jonathan 69: #include "opt_llc.h"
1.36 jonathan 70: #include "opt_iso.h"
1.112 martin 71: #include "opt_ipx.h"
72: #include "opt_mbuftrace.h"
1.37 jonathan 73: #include "opt_ns.h"
1.30 matt 74: #include "opt_gateway.h"
1.77 thorpej 75: #include "opt_pfil_hooks.h"
1.59 thorpej 76: #include "vlan.h"
1.81 martin 77: #include "pppoe.h"
1.78 thorpej 78: #include "bridge.h"
1.69 thorpej 79: #include "bpfilter.h"
1.93 martin 80: #include "arp.h"
1.121 yamt 81: #include "agr.h"
1.30 matt 82:
1.4 mycroft 83: #include <sys/param.h>
84: #include <sys/systm.h>
85: #include <sys/kernel.h>
1.81 martin 86: #include <sys/callout.h>
1.4 mycroft 87: #include <sys/malloc.h>
88: #include <sys/mbuf.h>
89: #include <sys/protosw.h>
90: #include <sys/socket.h>
91: #include <sys/ioctl.h>
92: #include <sys/errno.h>
93: #include <sys/syslog.h>
1.129.2.1! tron 94: #include <sys/kauth.h>
1.4 mycroft 95:
1.8 mycroft 96: #include <machine/cpu.h>
97:
1.4 mycroft 98: #include <net/if.h>
99: #include <net/netisr.h>
100: #include <net/route.h>
101: #include <net/if_llc.h>
102: #include <net/if_dl.h>
1.8 mycroft 103: #include <net/if_types.h>
1.93 martin 104:
105: #if NARP == 0
106: /*
1.102 jmmv 107: * XXX there should really be a way to issue this warning from within config(8)
1.93 martin 108: */
1.111 martin 109: #error You have included NETATALK or a pseudo-device in your configuration that depends on the presence of ethernet interfaces, but have no such interfaces configured. Check if you really need pseudo-device bridge, pppoe, vlan or options NETATALK.
1.93 martin 110: #endif
1.1 cgd 111:
1.120 perry 112: #if NBPFILTER > 0
1.69 thorpej 113: #include <net/bpf.h>
114: #endif
115:
1.22 is 116: #include <net/if_ether.h>
1.59 thorpej 117: #if NVLAN > 0
118: #include <net/if_vlanvar.h>
119: #endif
1.22 is 120:
1.81 martin 121: #if NPPPOE > 0
122: #include <net/if_pppoe.h>
123: #endif
124:
1.121 yamt 125: #if NAGR > 0
126: #include <net/agr/ieee8023_slowprotocols.h> /* XXX */
127: #include <net/agr/ieee8023ad.h>
128: #include <net/agr/if_agrvar.h>
129: #endif
130:
1.78 thorpej 131: #if NBRIDGE > 0
132: #include <net/if_bridgevar.h>
133: #endif
134:
1.15 phil 135: #include <netinet/in.h>
1.1 cgd 136: #ifdef INET
1.4 mycroft 137: #include <netinet/in_var.h>
1.1 cgd 138: #endif
1.22 is 139: #include <netinet/if_inarp.h>
1.1 cgd 140:
1.44 itojun 141: #ifdef INET6
142: #ifndef INET
143: #include <netinet/in.h>
144: #endif
145: #include <netinet6/in6_var.h>
146: #include <netinet6/nd6.h>
147: #endif
148:
1.1 cgd 149: #ifdef NS
1.4 mycroft 150: #include <netns/ns.h>
151: #include <netns/ns_if.h>
1.1 cgd 152: #endif
153:
1.129.2.1! tron 154: #include "carp.h"
! 155: #if NCARP > 0
! 156: #include <netinet/ip_carp.h>
! 157: #endif
! 158:
1.32 christos 159: #ifdef IPX
160: #include <netipx/ipx.h>
161: #include <netipx/ipx_if.h>
162: #endif
163:
1.1 cgd 164: #ifdef ISO
1.4 mycroft 165: #include <netiso/argo_debug.h>
166: #include <netiso/iso.h>
167: #include <netiso/iso_var.h>
168: #include <netiso/iso_snpac.h>
1.1 cgd 169: #endif
1.4 mycroft 170:
1.8 mycroft 171: #ifdef LLC
172: #include <netccitt/dll.h>
173: #include <netccitt/llc_var.h>
174: #endif
175:
176: #if defined(LLC) && defined(CCITT)
177: extern struct ifqueue pkintrq;
178: #endif
1.1 cgd 179:
1.23 christos 180: #ifdef NETATALK
181: #include <netatalk/at.h>
182: #include <netatalk/at_var.h>
183: #include <netatalk/at_extern.h>
184:
185: #define llc_snap_org_code llc_un.type_snap.org_code
186: #define llc_snap_ether_type llc_un.type_snap.ether_type
187:
188: extern u_char at_org_code[3];
189: extern u_char aarp_org_code[3];
190: #endif /* NETATALK */
191:
1.123 matt 192: static struct timeval bigpktppslim_last;
193: static int bigpktppslim = 2; /* XXX */
194: static int bigpktpps_count;
195:
196:
1.118 yamt 197: const uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
198: { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1.121 yamt 199: const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] =
200: { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
1.8 mycroft 201: #define senderr(e) { error = (e); goto bad;}
1.1 cgd 202:
1.22 is 203: #define SIN(x) ((struct sockaddr_in *)x)
204:
1.128 thorpej 205: static int ether_output(struct ifnet *, struct mbuf *,
206: struct sockaddr *, struct rtentry *);
1.42 thorpej 207:
1.1 cgd 208: /*
209: * Ethernet output routine.
210: * Encapsulate a packet of type family for the local net.
1.22 is 211: * Assumes that ifp is actually pointer to ethercom structure.
1.1 cgd 212: */
1.42 thorpej 213: static int
1.129.2.1! tron 214: ether_output(struct ifnet *ifp0, struct mbuf *m0, struct sockaddr *dst,
1.58 matt 215: struct rtentry *rt0)
1.1 cgd 216: {
1.49 matt 217: u_int16_t etype = 0;
1.122 christos 218: int error = 0, hdrcmplt = 0;
1.31 thorpej 219: u_char esrc[6], edst[6];
1.29 mrg 220: struct mbuf *m = m0;
221: struct rtentry *rt;
1.1 cgd 222: struct mbuf *mcopy = (struct mbuf *)0;
1.29 mrg 223: struct ether_header *eh;
1.129.2.1! tron 224: struct ifnet *ifp = ifp0;
1.72 thorpej 225: ALTQ_DECL(struct altq_pktattr pktattr;)
1.24 christos 226: #ifdef INET
1.22 is 227: struct arphdr *ah;
1.24 christos 228: #endif /* INET */
1.23 christos 229: #ifdef NETATALK
230: struct at_ifaddr *aa;
231: #endif /* NETATALK */
1.1 cgd 232:
1.104 matt 233: #ifdef MBUFTRACE
1.116 jonathan 234: m_claimm(m, ifp->if_mowner);
1.104 matt 235: #endif
1.129.2.1! tron 236:
! 237: #if NCARP > 0
! 238: if (ifp->if_type == IFT_CARP) {
! 239: struct ifaddr *ifa;
! 240:
! 241: /* loop back if this is going to the carp interface */
! 242: if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
! 243: (ifa = ifa_ifwithaddr(dst)) != NULL &&
! 244: ifa->ifa_ifp == ifp0)
! 245: return (looutput(ifp0, m, dst, rt0));
! 246:
! 247: ifp = ifp->if_carpdev;
! 248: /* ac = (struct arpcom *)ifp; */
! 249:
! 250: if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
! 251: (IFF_UP|IFF_RUNNING))
! 252: senderr(ENETDOWN);
! 253: }
! 254: #endif /* NCARP > 0 */
! 255:
1.8 mycroft 256: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
257: senderr(ENETDOWN);
1.18 christos 258: if ((rt = rt0) != NULL) {
1.8 mycroft 259: if ((rt->rt_flags & RTF_UP) == 0) {
1.27 fvdl 260: if ((rt0 = rt = rtalloc1(dst, 1)) != NULL) {
1.8 mycroft 261: rt->rt_refcnt--;
1.27 fvdl 262: if (rt->rt_ifp != ifp)
263: return (*rt->rt_ifp->if_output)
264: (ifp, m0, dst, rt);
1.120 perry 265: } else
1.8 mycroft 266: senderr(EHOSTUNREACH);
267: }
1.27 fvdl 268: if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS) {
1.8 mycroft 269: if (rt->rt_gwroute == 0)
270: goto lookup;
271: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
272: rtfree(rt); rt = rt0;
273: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
274: if ((rt = rt->rt_gwroute) == 0)
275: senderr(EHOSTUNREACH);
1.27 fvdl 276: /* the "G" test below also prevents rt == rt0 */
277: if ((rt->rt_flags & RTF_GATEWAY) ||
278: (rt->rt_ifp != ifp)) {
279: rt->rt_refcnt--;
280: rt0->rt_gwroute = 0;
281: senderr(EHOSTUNREACH);
282: }
1.8 mycroft 283: }
284: }
285: if (rt->rt_flags & RTF_REJECT)
286: if (rt->rt_rmx.rmx_expire == 0 ||
1.98 thorpej 287: (u_long) time.tv_sec < rt->rt_rmx.rmx_expire)
1.8 mycroft 288: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
1.1 cgd 289: }
1.72 thorpej 290:
1.1 cgd 291: switch (dst->sa_family) {
292:
293: #ifdef INET
294: case AF_INET:
1.22 is 295: if (m->m_flags & M_BCAST)
1.125 christos 296: (void)memcpy(edst, etherbroadcastaddr, sizeof(edst));
1.22 is 297:
298: else if (m->m_flags & M_MCAST) {
299: ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
300: (caddr_t)edst)
301:
302: } else if (!arpresolve(ifp, rt, m, dst, edst))
1.1 cgd 303: return (0); /* if not yet resolved */
1.3 hpeyerl 304: /* If broadcasting on a simplex interface, loopback a copy */
305: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
1.1 cgd 306: mcopy = m_copy(m, 0, (int)M_COPYALL);
1.17 mycroft 307: etype = htons(ETHERTYPE_IP);
1.8 mycroft 308: break;
1.22 is 309:
310: case AF_ARP:
311: ah = mtod(m, struct arphdr *);
312: if (m->m_flags & M_BCAST)
1.125 christos 313: (void)memcpy(edst, etherbroadcastaddr, sizeof(edst));
1.129.2.1! tron 314: else {
! 315: caddr_t tha = ar_tha(ah);
! 316:
! 317: KASSERT(tha);
! 318: bcopy(tha, (caddr_t)edst, sizeof(edst));
! 319: }
1.120 perry 320:
1.22 is 321: ah->ar_hrd = htons(ARPHRD_ETHER);
322:
1.107 itojun 323: switch (ntohs(ah->ar_op)) {
1.22 is 324: case ARPOP_REVREQUEST:
325: case ARPOP_REVREPLY:
326: etype = htons(ETHERTYPE_REVARP);
327: break;
328:
329: case ARPOP_REQUEST:
330: case ARPOP_REPLY:
331: default:
332: etype = htons(ETHERTYPE_ARP);
333: }
334:
335: break;
1.1 cgd 336: #endif
1.44 itojun 337: #ifdef INET6
338: case AF_INET6:
1.51 itojun 339: if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
1.67 itojun 340: /* something bad happened */
1.99 itojun 341: return (0);
1.51 itojun 342: }
1.44 itojun 343: etype = htons(ETHERTYPE_IPV6);
344: break;
345: #endif
1.23 christos 346: #ifdef NETATALK
347: case AF_APPLETALK:
348: if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
349: #ifdef NETATALKDEBUG
350: printf("aarpresolv failed\n");
351: #endif /* NETATALKDEBUG */
352: return (0);
353: }
354: /*
355: * ifaddr is the first thing in at_ifaddr
356: */
357: aa = (struct at_ifaddr *) at_ifawithnet(
1.25 christos 358: (struct sockaddr_at *)dst, ifp);
1.23 christos 359: if (aa == NULL)
360: goto bad;
1.120 perry 361:
1.23 christos 362: /*
363: * In the phase 2 case, we need to prepend an mbuf for the
364: * llc header. Since we must preserve the value of m,
365: * which is passed to us by value, we m_copy() the first
366: * mbuf, and use it for our llc header.
367: */
368: if (aa->aa_flags & AFA_PHASE2) {
369: struct llc llc;
370:
1.43 bouyer 371: M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
1.23 christos 372: llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
373: llc.llc_control = LLC_UI;
374: bcopy(at_org_code, llc.llc_snap_org_code,
375: sizeof(llc.llc_snap_org_code));
1.38 kim 376: llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
1.23 christos 377: bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
378: } else {
1.38 kim 379: etype = htons(ETHERTYPE_ATALK);
1.23 christos 380: }
381: break;
382: #endif /* NETATALK */
1.1 cgd 383: #ifdef NS
384: case AF_NS:
1.17 mycroft 385: etype = htons(ETHERTYPE_NS);
1.1 cgd 386: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
387: (caddr_t)edst, sizeof (edst));
388: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
389: return (looutput(ifp, m, dst, rt));
1.3 hpeyerl 390: /* If broadcasting on a simplex interface, loopback a copy */
391: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
1.1 cgd 392: mcopy = m_copy(m, 0, (int)M_COPYALL);
1.8 mycroft 393: break;
1.1 cgd 394: #endif
1.32 christos 395: #ifdef IPX
396: case AF_IPX:
1.39 christos 397: etype = htons(ETHERTYPE_IPX);
398: bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
1.32 christos 399: (caddr_t)edst, sizeof (edst));
400: /* If broadcasting on a simplex interface, loopback a copy */
401: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
402: mcopy = m_copy(m, 0, (int)M_COPYALL);
403: break;
404: #endif
1.1 cgd 405: #ifdef ISO
406: case AF_ISO: {
407: int snpalen;
408: struct llc *l;
1.29 mrg 409: struct sockaddr_dl *sdl;
1.1 cgd 410:
1.8 mycroft 411: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
412: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
413: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
1.18 christos 414: } else {
415: error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
416: (char *)edst, &snpalen);
417: if (error)
418: goto bad; /* Not Resolved */
419: }
1.3 hpeyerl 420: /* If broadcasting on a simplex interface, loopback a copy */
1.8 mycroft 421: if (*edst & 1)
422: m->m_flags |= (M_BCAST|M_MCAST);
1.3 hpeyerl 423: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
1.1 cgd 424: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
425: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
426: if (mcopy) {
427: eh = mtod(mcopy, struct ether_header *);
428: bcopy((caddr_t)edst,
429: (caddr_t)eh->ether_dhost, sizeof (edst));
1.22 is 430: bcopy(LLADDR(ifp->if_sadl),
1.1 cgd 431: (caddr_t)eh->ether_shost, sizeof (edst));
432: }
433: }
434: M_PREPEND(m, 3, M_DONTWAIT);
435: if (m == NULL)
436: return (0);
437: l = mtod(m, struct llc *);
438: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
439: l->llc_control = LLC_UI;
1.18 christos 440: #ifdef ARGO_DEBUG
441: if (argo_debug[D_ETHER]) {
1.1 cgd 442: int i;
1.21 christos 443: printf("unoutput: sending pkt to: ");
1.1 cgd 444: for (i=0; i<6; i++)
1.21 christos 445: printf("%x ", edst[i] & 0xff);
446: printf("\n");
1.18 christos 447: }
448: #endif
1.8 mycroft 449: } break;
450: #endif /* ISO */
451: #ifdef LLC
452: /* case AF_NSAP: */
453: case AF_CCITT: {
1.129.2.1! tron 454: struct sockaddr_dl *sdl = rt ?
! 455: (struct sockaddr_dl *) rt -> rt_gateway : NULL;
1.8 mycroft 456:
457: if (sdl && sdl->sdl_family == AF_LINK
458: && sdl->sdl_alen > 0) {
459: bcopy(LLADDR(sdl), (char *)edst,
460: sizeof(edst));
461: } else goto bad; /* Not a link interface ? Funny ... */
462: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
463: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
464: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
465: if (mcopy) {
466: eh = mtod(mcopy, struct ether_header *);
467: bcopy((caddr_t)edst,
468: (caddr_t)eh->ether_dhost, sizeof (edst));
1.22 is 469: bcopy(LLADDR(ifp->if_sadl),
1.8 mycroft 470: (caddr_t)eh->ether_shost, sizeof (edst));
471: }
1.3 hpeyerl 472: }
1.8 mycroft 473: #ifdef LLC_DEBUG
474: {
475: int i;
1.29 mrg 476: struct llc *l = mtod(m, struct llc *);
1.8 mycroft 477:
1.21 christos 478: printf("ether_output: sending LLC2 pkt to: ");
1.8 mycroft 479: for (i=0; i<6; i++)
1.21 christos 480: printf("%x ", edst[i] & 0xff);
1.120 perry 481: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
1.17 mycroft 482: m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
483: l->llc_control & 0xff);
1.8 mycroft 484:
485: }
486: #endif /* LLC_DEBUG */
487: } break;
1.120 perry 488: #endif /* LLC */
1.1 cgd 489:
1.31 thorpej 490: case pseudo_AF_HDRCMPLT:
491: hdrcmplt = 1;
492: eh = (struct ether_header *)dst->sa_data;
493: bcopy((caddr_t)eh->ether_shost, (caddr_t)esrc, sizeof (esrc));
494: /* FALLTHROUGH */
495:
1.1 cgd 496: case AF_UNSPEC:
497: eh = (struct ether_header *)dst->sa_data;
498: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
1.8 mycroft 499: /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
1.17 mycroft 500: etype = eh->ether_type;
1.8 mycroft 501: break;
1.1 cgd 502:
503: default:
1.21 christos 504: printf("%s: can't handle af%d\n", ifp->if_xname,
1.1 cgd 505: dst->sa_family);
1.8 mycroft 506: senderr(EAFNOSUPPORT);
1.1 cgd 507: }
508:
509: if (mcopy)
510: (void) looutput(ifp, mcopy, dst, rt);
1.16 mycroft 511:
1.50 matt 512: /* If no ether type is set, this must be a 802.2 formatted packet.
513: */
514: if (etype == 0)
515: etype = htons(m->m_pkthdr.len);
1.1 cgd 516: /*
517: * Add local net header. If no space in first mbuf,
518: * allocate another.
519: */
520: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
1.8 mycroft 521: if (m == 0)
522: senderr(ENOBUFS);
1.1 cgd 523: eh = mtod(m, struct ether_header *);
1.96 thorpej 524: /* Note: etype is already in network byte order. */
525: #ifdef __NO_STRICT_ALIGNMENT
1.97 kristerw 526: eh->ether_type = etype;
1.96 thorpej 527: #else
528: {
529: uint8_t *dstp = (uint8_t *) &eh->ether_type;
530: #if BYTE_ORDER == BIG_ENDIAN
531: dstp[0] = etype >> 8;
1.120 perry 532: dstp[1] = etype;
1.96 thorpej 533: #else
534: dstp[0] = etype;
535: dstp[1] = etype >> 8;
536: #endif /* BYTE_ORDER == BIG_ENDIAN */
537: }
538: #endif /* __NO_STRICT_ALIGNMENT */
1.1 cgd 539: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
1.31 thorpej 540: if (hdrcmplt)
541: bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost,
542: sizeof(eh->ether_shost));
543: else
544: bcopy(LLADDR(ifp->if_sadl), (caddr_t)eh->ether_shost,
545: sizeof(eh->ether_shost));
1.77 thorpej 546:
1.129.2.1! tron 547: #if NCARP > 0
! 548: if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
! 549: bcopy(LLADDR(ifp0->if_sadl), (caddr_t)eh->ether_shost,
! 550: sizeof(eh->ether_shost));
! 551: }
! 552: #endif /* NCARP > 0 */
! 553:
1.77 thorpej 554: #ifdef PFIL_HOOKS
555: if ((error = pfil_run_hooks(&ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0)
556: return (error);
557: if (m == NULL)
558: return (0);
559: #endif
560:
1.78 thorpej 561: #if NBRIDGE > 0
562: /*
563: * Bridges require special output handling.
564: */
565: if (ifp->if_bridge)
566: return (bridge_output(ifp, m, NULL, NULL));
567: #endif
568:
1.129.2.1! tron 569: #if NCARP > 0
! 570: if (ifp != ifp0)
! 571: ifp0->if_obytes += m->m_pkthdr.len + ETHER_HDR_LEN;
! 572: #endif /* NCARP > 0 */
! 573:
1.77 thorpej 574: #ifdef ALTQ
575: /*
576: * If ALTQ is enabled on the parent interface, do
577: * classification; the queueing discipline might not
578: * require classification, but might require the
579: * address family/header pointer in the pktattr.
580: */
581: if (ALTQ_IS_ENABLED(&ifp->if_snd))
582: altq_etherclassify(&ifp->if_snd, m, &pktattr);
583: #endif
584:
1.122 christos 585: return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
1.1 cgd 586:
587: bad:
588: if (m)
589: m_freem(m);
590: return (error);
591: }
1.76 thorpej 592:
593: #ifdef ALTQ
594: /*
595: * This routine is a slight hack to allow a packet to be classified
596: * if the Ethernet headers are present. It will go away when ALTQ's
597: * classification engine understands link headers.
598: */
599: void
600: altq_etherclassify(struct ifaltq *ifq, struct mbuf *m,
601: struct altq_pktattr *pktattr)
602: {
603: struct ether_header *eh;
604: u_int16_t ether_type;
605: int hlen, af, hdrsize;
606: caddr_t hdr;
607:
608: hlen = ETHER_HDR_LEN;
609: eh = mtod(m, struct ether_header *);
610:
611: ether_type = htons(eh->ether_type);
612:
613: if (ether_type < ETHERMTU) {
614: /* LLC/SNAP */
615: struct llc *llc = (struct llc *)(eh + 1);
616: hlen += 8;
617:
618: if (m->m_len < hlen ||
619: llc->llc_dsap != LLC_SNAP_LSAP ||
620: llc->llc_ssap != LLC_SNAP_LSAP ||
621: llc->llc_control != LLC_UI) {
622: /* Not SNAP. */
623: goto bad;
624: }
625:
626: ether_type = htons(llc->llc_un.type_snap.ether_type);
627: }
628:
629: switch (ether_type) {
630: case ETHERTYPE_IP:
631: af = AF_INET;
632: hdrsize = 20; /* sizeof(struct ip) */
633: break;
634:
635: case ETHERTYPE_IPV6:
636: af = AF_INET6;
637: hdrsize = 40; /* sizeof(struct ip6_hdr) */
638: break;
639:
640: default:
641: af = AF_UNSPEC;
642: hdrsize = 0;
643: break;
644: }
645:
1.95 itojun 646: while (m->m_len <= hlen) {
647: hlen -= m->m_len;
648: m = m->m_next;
649: }
1.76 thorpej 650: if (m->m_len < (hlen + hdrsize)) {
651: /*
1.95 itojun 652: * protocol header not in a single mbuf.
653: * We can't cope with this situation right
1.76 thorpej 654: * now (but it shouldn't ever happen, really, anyhow).
655: */
1.92 itojun 656: #ifdef DEBUG
1.78 thorpej 657: printf("altq_etherclassify: headers span multiple mbufs: "
658: "%d < %d\n", m->m_len, (hlen + hdrsize));
1.92 itojun 659: #endif
1.76 thorpej 660: goto bad;
661: }
662:
663: m->m_data += hlen;
664: m->m_len -= hlen;
665:
666: hdr = mtod(m, caddr_t);
667:
668: if (ALTQ_NEEDS_CLASSIFY(ifq))
669: pktattr->pattr_class =
670: (*ifq->altq_classify)(ifq->altq_clfier, m, af);
671: pktattr->pattr_af = af;
672: pktattr->pattr_hdr = hdr;
673:
674: m->m_data -= hlen;
675: m->m_len += hlen;
676:
677: return;
678:
679: bad:
680: pktattr->pattr_class = NULL;
681: pktattr->pattr_hdr = NULL;
682: pktattr->pattr_af = AF_UNSPEC;
683: }
684: #endif /* ALTQ */
1.1 cgd 685:
686: /*
687: * Process a received Ethernet packet;
1.42 thorpej 688: * the packet is in the mbuf chain m with
689: * the ether header.
1.1 cgd 690: */
1.129.2.1! tron 691: void
1.58 matt 692: ether_input(struct ifnet *ifp, struct mbuf *m)
1.1 cgd 693: {
1.91 thorpej 694: struct ethercom *ec = (struct ethercom *) ifp;
1.29 mrg 695: struct ifqueue *inq;
1.18 christos 696: u_int16_t etype;
1.42 thorpej 697: struct ether_header *eh;
1.23 christos 698: #if defined (ISO) || defined (LLC) || defined(NETATALK)
1.29 mrg 699: struct llc *l;
1.18 christos 700: #endif
1.1 cgd 701:
1.8 mycroft 702: if ((ifp->if_flags & IFF_UP) == 0) {
703: m_freem(m);
704: return;
705: }
1.42 thorpej 706:
1.104 matt 707: #ifdef MBUFTRACE
1.116 jonathan 708: m_claimm(m, &ec->ec_rx_mowner);
1.104 matt 709: #endif
1.42 thorpej 710: eh = mtod(m, struct ether_header *);
1.63 thorpej 711: etype = ntohs(eh->ether_type);
712:
713: /*
714: * Determine if the packet is within its size limits.
715: */
1.83 thorpej 716: if (m->m_pkthdr.len >
717: ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
1.123 matt 718: if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count,
719: bigpktppslim)) {
720: printf("%s: discarding oversize frame (len=%d)\n",
721: ifp->if_xname, m->m_pkthdr.len);
722: }
1.63 thorpej 723: m_freem(m);
724: return;
725: }
1.77 thorpej 726:
1.84 thorpej 727: if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
728: /*
729: * If this is not a simplex interface, drop the packet
730: * if it came from us.
731: */
732: if ((ifp->if_flags & IFF_SIMPLEX) == 0 &&
733: memcmp(LLADDR(ifp->if_sadl), eh->ether_shost,
734: ETHER_ADDR_LEN) == 0) {
735: m_freem(m);
736: return;
737: }
738:
739: if (memcmp(etherbroadcastaddr,
740: eh->ether_dhost, ETHER_ADDR_LEN) == 0)
741: m->m_flags |= M_BCAST;
742: else
743: m->m_flags |= M_MCAST;
744: ifp->if_imcasts++;
745: }
746:
1.79 thorpej 747: /* If the CRC is still on the packet, trim it off. */
748: if (m->m_flags & M_HASFCS) {
749: m_adj(m, -ETHER_CRC_LEN);
750: m->m_flags &= ~M_HASFCS;
751: }
752:
1.42 thorpej 753: ifp->if_ibytes += m->m_pkthdr.len;
1.78 thorpej 754:
755: #if NBRIDGE > 0
756: /*
757: * Tap the packet off here for a bridge. bridge_input()
758: * will return NULL if it has consumed the packet, otherwise
759: * it gets processed as normal. Note that bridge_input()
760: * will always return the original packet if we need to
761: * process it locally.
762: */
763: if (ifp->if_bridge) {
1.119 kim 764: if(m->m_flags & M_PROTO1) {
765: m->m_flags &= ~M_PROTO1;
766: } else {
767: /* clear M_PROMISC, in case the packets comes from a vlan */
768: m->m_flags &= ~M_PROMISC;
769: m = bridge_input(ifp, m);
770: if (m == NULL)
771: return;
1.78 thorpej 772:
1.119 kim 773: /*
774: * Bridge has determined that the packet is for us.
775: * Update our interface pointer -- we may have had
776: * to "bridge" the packet locally.
777: */
778: ifp = m->m_pkthdr.rcvif;
779: }
1.120 perry 780: } else
1.78 thorpej 781: #endif /* NBRIDGE > 0 */
1.106 bouyer 782: {
1.129.2.1! tron 783:
! 784: #if NCARP > 0
! 785: if (ifp->if_carp && ifp->if_type != IFT_CARP &&
! 786: (carp_input(m, (u_int8_t *)&eh->ether_shost,
! 787: (u_int8_t *)&eh->ether_dhost, eh->ether_type) == 0)) {
! 788: return;
! 789: }
! 790: #endif /* NCARP > 0 */
1.106 bouyer 791: if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
792: (ifp->if_flags & IFF_PROMISC) != 0 &&
793: memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost,
794: ETHER_ADDR_LEN) != 0) {
795: m->m_flags |= M_PROMISC;
796: }
1.70 bouyer 797: }
1.78 thorpej 798:
799: #ifdef PFIL_HOOKS
1.106 bouyer 800: if ((m->m_flags & M_PROMISC) == 0) {
801: if (pfil_run_hooks(&ifp->if_pfil, &m, ifp, PFIL_IN) != 0)
802: return;
803: if (m == NULL)
804: return;
1.78 thorpej 805:
1.106 bouyer 806: eh = mtod(m, struct ether_header *);
807: etype = ntohs(eh->ether_type);
808: }
1.78 thorpej 809: #endif
1.70 bouyer 810:
1.91 thorpej 811: /*
812: * If VLANs are configured on the interface, check to
813: * see if the device performed the decapsulation and
814: * provided us with the tag.
815: */
1.114 simonb 816: if (ec->ec_nvlans && m_tag_find(m, PACKET_TAG_VLAN, NULL) != NULL) {
1.70 bouyer 817: #if NVLAN > 0
818: /*
819: * vlan_input() will either recursively call ether_input()
820: * or drop the packet.
821: */
1.91 thorpej 822: vlan_input(ifp, m);
823: #else
824: m_freem(m);
1.70 bouyer 825: #endif
1.61 thorpej 826: return;
827: }
1.1 cgd 828:
1.121 yamt 829: #if NAGR > 0
830: if (ifp->if_agrprivate &&
831: __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) {
832: m->m_flags &= ~M_PROMISC;
833: agr_input(ifp, m);
834: return;
835: }
836: #endif /* NAGR > 0 */
837:
1.59 thorpej 838: /*
839: * Handle protocols that expect to have the Ethernet header
840: * (and possibly FCS) intact.
841: */
842: switch (etype) {
843: #if NVLAN > 0
844: case ETHERTYPE_VLAN:
845: /*
846: * vlan_input() will either recursively call ether_input()
847: * or drop the packet.
848: */
1.63 thorpej 849: if (((struct ethercom *)ifp)->ec_nvlans != 0)
850: vlan_input(ifp, m);
1.65 enami 851: else
852: m_freem(m);
1.59 thorpej 853: return;
854: #endif /* NVLAN > 0 */
1.81 martin 855: #if NPPPOE > 0
856: case ETHERTYPE_PPPOEDISC:
857: case ETHERTYPE_PPPOE:
1.106 bouyer 858: if (m->m_flags & M_PROMISC) {
859: m_freem(m);
860: return;
861: }
1.105 aymeric 862: #ifndef PPPOE_SERVER
863: if (m->m_flags & (M_MCAST | M_BCAST)) {
864: m_freem(m);
865: return;
866: }
867: #endif
868:
1.120 perry 869: if (etype == ETHERTYPE_PPPOEDISC)
1.81 martin 870: inq = &ppoediscinq;
871: else
872: inq = &ppoeinq;
873: if (IF_QFULL(inq)) {
874: IF_DROP(inq);
875: m_freem(m);
876: } else
877: IF_ENQUEUE(inq, m);
878: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1.103 thorpej 879: if (!callout_pending(&pppoe_softintr))
1.81 martin 880: callout_reset(&pppoe_softintr, 1, pppoe_softintr_handler, NULL);
881: #else
882: softintr_schedule(pppoe_softintr);
883: #endif
884: return;
885: #endif /* NPPPOE > 0 */
1.121 yamt 886: case ETHERTYPE_SLOWPROTOCOLS: {
887: uint8_t subtype;
888:
889: #if defined(DIAGNOSTIC)
890: if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) {
891: panic("ether_input: too short slow protocol packet");
892: }
893: #endif
894: m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype);
895: switch (subtype) {
896: #if NAGR > 0
897: case SLOWPROTOCOLS_SUBTYPE_LACP:
898: if (ifp->if_agrprivate) {
899: ieee8023ad_lacp_input(ifp, m);
900: return;
901: }
902: break;
903:
904: case SLOWPROTOCOLS_SUBTYPE_MARKER:
905: if (ifp->if_agrprivate) {
906: ieee8023ad_marker_input(ifp, m);
907: return;
908: }
909: break;
910: #endif /* NAGR > 0 */
911: default:
912: if (subtype == 0 || subtype > 10) {
913: /* illegal value */
914: m_freem(m);
915: return;
916: }
917: /* unknown subtype */
918: break;
919: }
920: /* FALLTHROUGH */
921: }
1.59 thorpej 922: default:
1.106 bouyer 923: if (m->m_flags & M_PROMISC) {
924: m_freem(m);
925: return;
926: }
1.59 thorpej 927: }
1.42 thorpej 928:
929: /* Strip off the Ethernet header. */
930: m_adj(m, sizeof(struct ether_header));
1.45 thorpej 931:
932: /* If the CRC is still on the packet, trim it off. */
1.79 thorpej 933: if (m->m_flags & M_HASFCS) {
1.45 thorpej 934: m_adj(m, -ETHER_CRC_LEN);
1.79 thorpej 935: m->m_flags &= ~M_HASFCS;
936: }
1.42 thorpej 937:
1.5 deraadt 938: switch (etype) {
1.1 cgd 939: #ifdef INET
940: case ETHERTYPE_IP:
1.30 matt 941: #ifdef GATEWAY
942: if (ipflow_fastforward(m))
943: return;
944: #endif
1.1 cgd 945: schednetisr(NETISR_IP);
946: inq = &ipintrq;
947: break;
948:
949: case ETHERTYPE_ARP:
1.8 mycroft 950: schednetisr(NETISR_ARP);
951: inq = &arpintrq;
952: break;
1.7 glass 953:
954: case ETHERTYPE_REVARP:
1.8 mycroft 955: revarpinput(m); /* XXX queue? */
1.1 cgd 956: return;
957: #endif
1.44 itojun 958: #ifdef INET6
959: case ETHERTYPE_IPV6:
960: schednetisr(NETISR_IPV6);
961: inq = &ip6intrq;
962: break;
963: #endif
1.1 cgd 964: #ifdef NS
965: case ETHERTYPE_NS:
966: schednetisr(NETISR_NS);
967: inq = &nsintrq;
968: break;
969:
1.32 christos 970: #endif
971: #ifdef IPX
972: case ETHERTYPE_IPX:
973: schednetisr(NETISR_IPX);
974: inq = &ipxintrq;
975: break;
1.1 cgd 976: #endif
1.23 christos 977: #ifdef NETATALK
1.38 kim 978: case ETHERTYPE_ATALK:
1.23 christos 979: schednetisr(NETISR_ATALK);
980: inq = &atintrq1;
981: break;
982: case ETHERTYPE_AARP:
983: /* probably this should be done with a NETISR as well */
984: aarpinput(ifp, m); /* XXX */
985: return;
986: #endif /* NETATALK */
1.1 cgd 987: default:
1.23 christos 988: #if defined (ISO) || defined (LLC) || defined (NETATALK)
1.11 mycroft 989: if (etype > ETHERMTU)
1.1 cgd 990: goto dropanyway;
991: l = mtod(m, struct llc *);
1.8 mycroft 992: switch (l->llc_dsap) {
1.23 christos 993: #ifdef NETATALK
994: case LLC_SNAP_LSAP:
995: switch (l->llc_control) {
996: case LLC_UI:
997: if (l->llc_ssap != LLC_SNAP_LSAP) {
998: goto dropanyway;
999: }
1.120 perry 1000:
1.23 christos 1001: if (Bcmp(&(l->llc_snap_org_code)[0],
1002: at_org_code, sizeof(at_org_code)) == 0 &&
1003: ntohs(l->llc_snap_ether_type) ==
1.38 kim 1004: ETHERTYPE_ATALK) {
1.23 christos 1005: inq = &atintrq2;
1006: m_adj(m, sizeof(struct llc));
1007: schednetisr(NETISR_ATALK);
1008: break;
1009: }
1010:
1011: if (Bcmp(&(l->llc_snap_org_code)[0],
1012: aarp_org_code,
1013: sizeof(aarp_org_code)) == 0 &&
1014: ntohs(l->llc_snap_ether_type) ==
1015: ETHERTYPE_AARP) {
1016: m_adj( m, sizeof(struct llc));
1017: aarpinput(ifp, m); /* XXX */
1018: return;
1019: }
1.120 perry 1020:
1.23 christos 1021: default:
1022: goto dropanyway;
1023: }
1024: break;
1025: #endif /* NETATALK */
1.8 mycroft 1026: #ifdef ISO
1.120 perry 1027: case LLC_ISO_LSAP:
1.8 mycroft 1028: switch (l->llc_control) {
1029: case LLC_UI:
1030: /* LLC_UI_P forbidden in class 1 service */
1031: if ((l->llc_dsap == LLC_ISO_LSAP) &&
1032: (l->llc_ssap == LLC_ISO_LSAP)) {
1033: /* LSAP for ISO */
1.11 mycroft 1034: if (m->m_pkthdr.len > etype)
1035: m_adj(m, etype - m->m_pkthdr.len);
1.8 mycroft 1036: m->m_data += 3; /* XXX */
1037: m->m_len -= 3; /* XXX */
1038: m->m_pkthdr.len -= 3; /* XXX */
1039: M_PREPEND(m, sizeof *eh, M_DONTWAIT);
1040: if (m == 0)
1041: return;
1042: *mtod(m, struct ether_header *) = *eh;
1.18 christos 1043: #ifdef ARGO_DEBUG
1044: if (argo_debug[D_ETHER])
1.21 christos 1045: printf("clnp packet");
1.18 christos 1046: #endif
1.8 mycroft 1047: schednetisr(NETISR_ISO);
1048: inq = &clnlintrq;
1049: break;
1050: }
1051: goto dropanyway;
1.120 perry 1052:
1.8 mycroft 1053: case LLC_XID:
1054: case LLC_XID_P:
1055: if(m->m_len < 6)
1056: goto dropanyway;
1057: l->llc_window = 0;
1058: l->llc_fid = 9;
1059: l->llc_class = 1;
1060: l->llc_dsap = l->llc_ssap = 0;
1061: /* Fall through to */
1062: case LLC_TEST:
1063: case LLC_TEST_P:
1064: {
1065: struct sockaddr sa;
1.29 mrg 1066: struct ether_header *eh2;
1.8 mycroft 1067: int i;
1068: u_char c = l->llc_dsap;
1069:
1070: l->llc_dsap = l->llc_ssap;
1071: l->llc_ssap = c;
1072: if (m->m_flags & (M_BCAST | M_MCAST))
1.22 is 1073: bcopy(LLADDR(ifp->if_sadl),
1.8 mycroft 1074: (caddr_t)eh->ether_dhost, 6);
1075: sa.sa_family = AF_UNSPEC;
1076: sa.sa_len = sizeof(sa);
1077: eh2 = (struct ether_header *)sa.sa_data;
1078: for (i = 0; i < 6; i++) {
1.120 perry 1079: eh2->ether_shost[i] = c =
1.22 is 1080: eh->ether_dhost[i];
1.120 perry 1081: eh2->ether_dhost[i] =
1.22 is 1082: eh->ether_dhost[i] =
1083: eh->ether_shost[i];
1.8 mycroft 1084: eh->ether_shost[i] = c;
1085: }
1086: ifp->if_output(ifp, m, &sa, NULL);
1087: return;
1088: }
1089: default:
1090: m_freem(m);
1091: return;
1092: }
1093: break;
1094: #endif /* ISO */
1095: #ifdef LLC
1096: case LLC_X25_LSAP:
1097: {
1.11 mycroft 1098: if (m->m_pkthdr.len > etype)
1099: m_adj(m, etype - m->m_pkthdr.len);
1.8 mycroft 1100: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
1.1 cgd 1101: if (m == 0)
1102: return;
1.8 mycroft 1103: if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
1.120 perry 1104: eh->ether_dhost, LLC_X25_LSAP, 6,
1.8 mycroft 1105: mtod(m, struct sdl_hdr *)))
1106: panic("ETHER cons addr failure");
1.11 mycroft 1107: mtod(m, struct sdl_hdr *)->sdlhdr_len = etype;
1.8 mycroft 1108: #ifdef LLC_DEBUG
1.21 christos 1109: printf("llc packet\n");
1.8 mycroft 1110: #endif /* LLC_DEBUG */
1111: schednetisr(NETISR_CCITT);
1112: inq = &llcintrq;
1.1 cgd 1113: break;
1114: }
1.8 mycroft 1115: #endif /* LLC */
1.1 cgd 1116: dropanyway:
1117: default:
1.8 mycroft 1118: m_freem(m);
1119: return;
1120: }
1.23 christos 1121: #else /* ISO || LLC || NETATALK*/
1.1 cgd 1122: m_freem(m);
1123: return;
1.23 christos 1124: #endif /* ISO || LLC || NETATALK*/
1.1 cgd 1125: }
1126:
1127: if (IF_QFULL(inq)) {
1128: IF_DROP(inq);
1129: m_freem(m);
1130: } else
1131: IF_ENQUEUE(inq, m);
1132: }
1133:
1134: /*
1135: * Convert Ethernet address to printable (loggable) representation.
1136: */
1137: char *
1.58 matt 1138: ether_sprintf(const u_char *ap)
1.1 cgd 1139: {
1.129 christos 1140: static char etherbuf[3 * ETHER_ADDR_LEN];
1141: return ether_snprintf(etherbuf, sizeof(etherbuf), ap);
1142: return etherbuf;
1143: }
1144:
1145: char *
1146: ether_snprintf(char *buf, size_t len, const u_char *ap)
1147: {
1148: char *cp = buf;
1149: size_t i;
1.1 cgd 1150:
1.129 christos 1151: for (i = 0; i < len / 3; i++) {
1.124 christos 1152: *cp++ = hexdigits[*ap >> 4];
1153: *cp++ = hexdigits[*ap++ & 0xf];
1.1 cgd 1154: *cp++ = ':';
1155: }
1.129 christos 1156: *--cp = '\0';
1157: return buf;
1.1 cgd 1158: }
1.8 mycroft 1159:
1160: /*
1161: * Perform common duties while attaching to interface list
1162: */
1163: void
1.58 matt 1164: ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
1.8 mycroft 1165: {
1.104 matt 1166: struct ethercom *ec = (struct ethercom *)ifp;
1.8 mycroft 1167:
1168: ifp->if_type = IFT_ETHER;
1.75 thorpej 1169: ifp->if_addrlen = ETHER_ADDR_LEN;
1.94 enami 1170: ifp->if_hdrlen = ETHER_HDR_LEN;
1.73 thorpej 1171: ifp->if_dlt = DLT_EN10MB;
1.8 mycroft 1172: ifp->if_mtu = ETHERMTU;
1.12 mycroft 1173: ifp->if_output = ether_output;
1.42 thorpej 1174: ifp->if_input = ether_input;
1.54 thorpej 1175: if (ifp->if_baudrate == 0)
1176: ifp->if_baudrate = IF_Mbps(10); /* just a default */
1.75 thorpej 1177:
1178: if_alloc_sadl(ifp);
1179: memcpy(LLADDR(ifp->if_sadl), lla, ifp->if_addrlen);
1180:
1.104 matt 1181: LIST_INIT(&ec->ec_multiaddrs);
1.26 is 1182: ifp->if_broadcastaddr = etherbroadcastaddr;
1.69 thorpej 1183: #if NBPFILTER > 0
1.71 thorpej 1184: bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
1.69 thorpej 1185: #endif
1.104 matt 1186: #ifdef MBUFTRACE
1.108 itojun 1187: strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
1188: sizeof(ec->ec_tx_mowner.mo_name));
1189: strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
1190: sizeof(ec->ec_tx_mowner.mo_descr));
1191: strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
1192: sizeof(ec->ec_rx_mowner.mo_name));
1193: strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
1194: sizeof(ec->ec_rx_mowner.mo_descr));
1.104 matt 1195: MOWNER_ATTACH(&ec->ec_tx_mowner);
1196: MOWNER_ATTACH(&ec->ec_rx_mowner);
1197: ifp->if_mowner = &ec->ec_tx_mowner;
1198: #endif
1.52 thorpej 1199: }
1200:
1201: void
1.58 matt 1202: ether_ifdetach(struct ifnet *ifp)
1.52 thorpej 1203: {
1.63 thorpej 1204: struct ethercom *ec = (void *) ifp;
1205: struct ether_multi *enm;
1206: int s;
1.69 thorpej 1207:
1.115 dyoung 1208: #if NBRIDGE > 0
1209: if (ifp->if_bridge)
1210: bridge_ifdetach(ifp);
1211: #endif
1212:
1.69 thorpej 1213: #if NBPFILTER > 0
1214: bpfdetach(ifp);
1215: #endif
1.64 thorpej 1216:
1217: #if NVLAN > 0
1218: if (ec->ec_nvlans)
1219: vlan_ifdetach(ifp);
1220: #endif
1.63 thorpej 1221:
1.79 thorpej 1222: s = splnet();
1.63 thorpej 1223: while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) {
1224: LIST_REMOVE(enm, enm_list);
1.100 jdolecek 1225: free(enm, M_IFMADDR);
1.63 thorpej 1226: ec->ec_multicnt--;
1227: }
1228: splx(s);
1.52 thorpej 1229:
1.109 itojun 1230: #if 0 /* done in if_detach() */
1.75 thorpej 1231: if_free_sadl(ifp);
1.109 itojun 1232: #endif
1.104 matt 1233:
1234: MOWNER_DETACH(&ec->ec_rx_mowner);
1235: MOWNER_DETACH(&ec->ec_tx_mowner);
1.53 thorpej 1236: }
1237:
1.56 thorpej 1238: #if 0
1239: /*
1240: * This is for reference. We have a table-driven version
1241: * of the little-endian crc32 generator, which is faster
1242: * than the double-loop.
1243: */
1.53 thorpej 1244: u_int32_t
1.58 matt 1245: ether_crc32_le(const u_int8_t *buf, size_t len)
1.53 thorpej 1246: {
1247: u_int32_t c, crc, carry;
1248: size_t i, j;
1249:
1250: crc = 0xffffffffU; /* initial value */
1251:
1252: for (i = 0; i < len; i++) {
1253: c = buf[i];
1254: for (j = 0; j < 8; j++) {
1255: carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
1256: crc >>= 1;
1257: c >>= 1;
1258: if (carry)
1.56 thorpej 1259: crc = (crc ^ ETHER_CRC_POLY_LE);
1.53 thorpej 1260: }
1261: }
1262:
1263: return (crc);
1264: }
1.56 thorpej 1265: #else
1266: u_int32_t
1.58 matt 1267: ether_crc32_le(const u_int8_t *buf, size_t len)
1.56 thorpej 1268: {
1269: static const u_int32_t crctab[] = {
1270: 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1271: 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1272: 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1273: 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1274: };
1275: u_int32_t crc;
1.98 thorpej 1276: size_t i;
1.56 thorpej 1277:
1278: crc = 0xffffffffU; /* initial value */
1279:
1280: for (i = 0; i < len; i++) {
1281: crc ^= buf[i];
1282: crc = (crc >> 4) ^ crctab[crc & 0xf];
1283: crc = (crc >> 4) ^ crctab[crc & 0xf];
1284: }
1285:
1286: return (crc);
1287: }
1288: #endif
1.53 thorpej 1289:
1290: u_int32_t
1.58 matt 1291: ether_crc32_be(const u_int8_t *buf, size_t len)
1.53 thorpej 1292: {
1293: u_int32_t c, crc, carry;
1294: size_t i, j;
1295:
1296: crc = 0xffffffffU; /* initial value */
1297:
1298: for (i = 0; i < len; i++) {
1299: c = buf[i];
1300: for (j = 0; j < 8; j++) {
1301: carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
1302: crc <<= 1;
1303: c >>= 1;
1304: if (carry)
1305: crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
1306: }
1307: }
1308:
1309: return (crc);
1.8 mycroft 1310: }
1311:
1.48 is 1312: #ifdef INET
1.118 yamt 1313: const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] =
1314: { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
1315: const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] =
1316: { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
1.48 is 1317: #endif
1.44 itojun 1318: #ifdef INET6
1.118 yamt 1319: const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] =
1320: { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
1321: const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] =
1322: { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
1.44 itojun 1323: #endif
1.60 enami 1324:
1.3 hpeyerl 1325: /*
1.60 enami 1326: * Convert a sockaddr into an Ethernet address or range of Ethernet
1327: * addresses.
1.3 hpeyerl 1328: */
1329: int
1.60 enami 1330: ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
1331: u_int8_t addrhi[ETHER_ADDR_LEN])
1.3 hpeyerl 1332: {
1.24 christos 1333: #ifdef INET
1.3 hpeyerl 1334: struct sockaddr_in *sin;
1.24 christos 1335: #endif /* INET */
1.44 itojun 1336: #ifdef INET6
1337: struct sockaddr_in6 *sin6;
1338: #endif /* INET6 */
1.3 hpeyerl 1339:
1.60 enami 1340: switch (sa->sa_family) {
1.3 hpeyerl 1341:
1342: case AF_UNSPEC:
1.60 enami 1343: bcopy(sa->sa_data, addrlo, ETHER_ADDR_LEN);
1344: bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1.3 hpeyerl 1345: break;
1346:
1347: #ifdef INET
1348: case AF_INET:
1.60 enami 1349: sin = satosin(sa);
1.3 hpeyerl 1350: if (sin->sin_addr.s_addr == INADDR_ANY) {
1351: /*
1.60 enami 1352: * An IP address of INADDR_ANY means listen to
1353: * or stop listening to all of the Ethernet
1354: * multicast addresses used for IP.
1.3 hpeyerl 1355: * (This is for the sake of IP multicast routers.)
1356: */
1.60 enami 1357: bcopy(ether_ipmulticast_min, addrlo, ETHER_ADDR_LEN);
1358: bcopy(ether_ipmulticast_max, addrhi, ETHER_ADDR_LEN);
1.3 hpeyerl 1359: }
1360: else {
1361: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
1.60 enami 1362: bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1.3 hpeyerl 1363: }
1364: break;
1365: #endif
1.44 itojun 1366: #ifdef INET6
1367: case AF_INET6:
1.60 enami 1368: sin6 = satosin6(sa);
1.47 itojun 1369: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1.44 itojun 1370: /*
1.60 enami 1371: * An IP6 address of 0 means listen to or stop
1372: * listening to all of the Ethernet multicast
1373: * address used for IP6.
1.44 itojun 1374: * (This is used for multicast routers.)
1375: */
1376: bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
1377: bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
1378: } else {
1379: ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
1380: bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1381: }
1382: break;
1383: #endif
1.3 hpeyerl 1384:
1385: default:
1.60 enami 1386: return (EAFNOSUPPORT);
1387: }
1388: return (0);
1389: }
1390:
1391: /*
1392: * Add an Ethernet multicast address or range of addresses to the list for a
1393: * given interface.
1394: */
1395: int
1396: ether_addmulti(struct ifreq *ifr, struct ethercom *ec)
1397: {
1398: struct ether_multi *enm;
1399: u_char addrlo[ETHER_ADDR_LEN];
1400: u_char addrhi[ETHER_ADDR_LEN];
1.79 thorpej 1401: int s = splnet(), error;
1.60 enami 1402:
1403: error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
1404: if (error != 0) {
1.3 hpeyerl 1405: splx(s);
1.60 enami 1406: return (error);
1.3 hpeyerl 1407: }
1408:
1409: /*
1410: * Verify that we have valid Ethernet multicast addresses.
1411: */
1412: if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
1413: splx(s);
1414: return (EINVAL);
1415: }
1416: /*
1417: * See if the address range is already in the list.
1418: */
1.22 is 1419: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 1420: if (enm != NULL) {
1421: /*
1422: * Found it; just increment the reference count.
1423: */
1424: ++enm->enm_refcount;
1425: splx(s);
1426: return (0);
1427: }
1428: /*
1429: * New address or range; malloc a new multicast record
1430: * and link it into the interface's multicast list.
1431: */
1432: enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
1433: if (enm == NULL) {
1434: splx(s);
1435: return (ENOBUFS);
1436: }
1437: bcopy(addrlo, enm->enm_addrlo, 6);
1438: bcopy(addrhi, enm->enm_addrhi, 6);
1439: enm->enm_refcount = 1;
1.22 is 1440: LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list);
1441: ec->ec_multicnt++;
1.3 hpeyerl 1442: splx(s);
1443: /*
1444: * Return ENETRESET to inform the driver that the list has changed
1445: * and its reception filter should be adjusted accordingly.
1446: */
1447: return (ENETRESET);
1448: }
1449:
1450: /*
1451: * Delete a multicast address record.
1452: */
1453: int
1.58 matt 1454: ether_delmulti(struct ifreq *ifr, struct ethercom *ec)
1.3 hpeyerl 1455: {
1.29 mrg 1456: struct ether_multi *enm;
1.60 enami 1457: u_char addrlo[ETHER_ADDR_LEN];
1458: u_char addrhi[ETHER_ADDR_LEN];
1.79 thorpej 1459: int s = splnet(), error;
1.3 hpeyerl 1460:
1.60 enami 1461: error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
1462: if (error != 0) {
1.3 hpeyerl 1463: splx(s);
1.60 enami 1464: return (error);
1.3 hpeyerl 1465: }
1466:
1467: /*
1.66 thorpej 1468: * Look ur the address in our list.
1.3 hpeyerl 1469: */
1.22 is 1470: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 1471: if (enm == NULL) {
1472: splx(s);
1473: return (ENXIO);
1474: }
1475: if (--enm->enm_refcount != 0) {
1476: /*
1477: * Still some claims to this record.
1478: */
1479: splx(s);
1480: return (0);
1481: }
1482: /*
1483: * No remaining claims to this record; unlink and free it.
1484: */
1.13 mycroft 1485: LIST_REMOVE(enm, enm_list);
1.3 hpeyerl 1486: free(enm, M_IFMADDR);
1.22 is 1487: ec->ec_multicnt--;
1.3 hpeyerl 1488: splx(s);
1489: /*
1490: * Return ENETRESET to inform the driver that the list has changed
1491: * and its reception filter should be adjusted accordingly.
1492: */
1493: return (ENETRESET);
1.66 thorpej 1494: }
1495:
1496: /*
1497: * Common ioctls for Ethernet interfaces. Note, we must be
1498: * called at splnet().
1499: */
1500: int
1501: ether_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1502: {
1503: struct ethercom *ec = (void *) ifp;
1504: struct ifreq *ifr = (struct ifreq *)data;
1505: struct ifaddr *ifa = (struct ifaddr *)data;
1506: int error = 0;
1507:
1508: switch (cmd) {
1509: case SIOCSIFADDR:
1510: ifp->if_flags |= IFF_UP;
1511: switch (ifa->ifa_addr->sa_family) {
1.75 thorpej 1512: case AF_LINK:
1513: {
1514: struct sockaddr_dl *sdl =
1515: (struct sockaddr_dl *) ifa->ifa_addr;
1516:
1517: if (sdl->sdl_type != IFT_ETHER ||
1518: sdl->sdl_alen != ifp->if_addrlen) {
1519: error = EINVAL;
1520: break;
1521: }
1522:
1523: memcpy(LLADDR(ifp->if_sadl), LLADDR(sdl),
1524: ifp->if_addrlen);
1525:
1526: /* Set new address. */
1527: error = (*ifp->if_init)(ifp);
1528: break;
1529: }
1.66 thorpej 1530: #ifdef INET
1531: case AF_INET:
1.86 thorpej 1532: if ((ifp->if_flags & IFF_RUNNING) == 0 &&
1533: (error = (*ifp->if_init)(ifp)) != 0)
1.66 thorpej 1534: break;
1535: arp_ifinit(ifp, ifa);
1536: break;
1537: #endif /* INET */
1538: #ifdef NS
1539: case AF_NS:
1540: {
1541: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1542:
1543: if (ns_nullhost(*ina))
1544: ina->x_host = *(union ns_host *)
1545: LLADDR(ifp->if_sadl);
1546: else
1547: memcpy(LLADDR(ifp->if_sadl),
1548: ina->x_host.c_host, ifp->if_addrlen);
1549: /* Set new address. */
1550: error = (*ifp->if_init)(ifp);
1551: break;
1552: }
1553: #endif /* NS */
1554: default:
1.86 thorpej 1555: if ((ifp->if_flags & IFF_RUNNING) == 0)
1556: error = (*ifp->if_init)(ifp);
1.66 thorpej 1557: break;
1558: }
1559: break;
1560:
1561: case SIOCGIFADDR:
1562: memcpy(((struct sockaddr *)&ifr->ifr_data)->sa_data,
1563: LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
1564: break;
1565:
1566: case SIOCSIFMTU:
1.82 thorpej 1567: {
1568: int maxmtu;
1569:
1570: if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU)
1571: maxmtu = ETHERMTU_JUMBO;
1572: else
1573: maxmtu = ETHERMTU;
1574:
1575: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu)
1.66 thorpej 1576: error = EINVAL;
1.88 thorpej 1577: else {
1.66 thorpej 1578: ifp->if_mtu = ifr->ifr_mtu;
1.87 thorpej 1579:
1.88 thorpej 1580: /* Make sure the device notices the MTU change. */
1581: if (ifp->if_flags & IFF_UP)
1582: error = (*ifp->if_init)(ifp);
1583: }
1.66 thorpej 1584: break;
1.82 thorpej 1585: }
1.66 thorpej 1586:
1587: case SIOCSIFFLAGS:
1588: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
1589: /*
1590: * If interface is marked down and it is running,
1591: * then stop and disable it.
1592: */
1593: (*ifp->if_stop)(ifp, 1);
1594: } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
1595: /*
1596: * If interface is marked up and it is stopped, then
1597: * start it.
1598: */
1599: error = (*ifp->if_init)(ifp);
1600: } else if ((ifp->if_flags & IFF_UP) != 0) {
1601: /*
1602: * Reset the interface to pick up changes in any other
1603: * flags that affect the hardware state.
1604: */
1605: error = (*ifp->if_init)(ifp);
1606: }
1607: break;
1608:
1609: case SIOCADDMULTI:
1.74 augustss 1610: error = ether_addmulti(ifr, ec);
1611: break;
1612:
1.66 thorpej 1613: case SIOCDELMULTI:
1.74 augustss 1614: error = ether_delmulti(ifr, ec);
1.66 thorpej 1615: break;
1616:
1617: default:
1618: error = ENOTTY;
1619: }
1620:
1621: return (error);
1.3 hpeyerl 1622: }
CVSweb <webmaster@jp.NetBSD.org>