Annotation of src/sys/net/if_ethersubr.c, Revision 1.223
1.223 ! ozaki-r 1: /* $NetBSD: if_ethersubr.c,v 1.222 2016/04/28 00:16:56 ozaki-r Exp $ */
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.223 ! ozaki-r 64: __KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.222 2016/04/28 00:16:56 ozaki-r Exp $");
1.1 cgd 65:
1.212 pooka 66: #ifdef _KERNEL_OPT
1.33 jonathan 67: #include "opt_inet.h"
68: #include "opt_atalk.h"
1.112 martin 69: #include "opt_mbuftrace.h"
1.182 kefren 70: #include "opt_mpls.h"
1.30 matt 71: #include "opt_gateway.h"
1.135 pavel 72: #include "opt_pppoe.h"
1.206 ozaki-r 73: #include "opt_net_mpsafe.h"
1.212 pooka 74: #endif
75:
1.59 thorpej 76: #include "vlan.h"
1.81 martin 77: #include "pppoe.h"
1.78 thorpej 78: #include "bridge.h"
1.93 martin 79: #include "arp.h"
1.121 yamt 80: #include "agr.h"
1.30 matt 81:
1.200 joerg 82: #include <sys/sysctl.h>
1.4 mycroft 83: #include <sys/malloc.h>
84: #include <sys/mbuf.h>
1.211 ozaki-r 85: #include <sys/mutex.h>
1.4 mycroft 86: #include <sys/ioctl.h>
87: #include <sys/errno.h>
1.158 dyoung 88: #include <sys/device.h>
1.204 tls 89: #include <sys/rnd.h>
1.207 riastrad 90: #include <sys/rndsource.h>
1.216 ozaki-r 91: #include <sys/cpu.h>
1.8 mycroft 92:
1.4 mycroft 93: #include <net/if.h>
94: #include <net/netisr.h>
95: #include <net/route.h>
96: #include <net/if_llc.h>
97: #include <net/if_dl.h>
1.8 mycroft 98: #include <net/if_types.h>
1.211 ozaki-r 99: #include <net/pktqueue.h>
1.93 martin 100:
1.158 dyoung 101: #include <net/if_media.h>
102: #include <dev/mii/mii.h>
103: #include <dev/mii/miivar.h>
104:
1.93 martin 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.69 thorpej 112: #include <net/bpf.h>
113:
1.22 is 114: #include <net/if_ether.h>
1.59 thorpej 115: #include <net/if_vlanvar.h>
1.22 is 116:
1.81 martin 117: #if NPPPOE > 0
118: #include <net/if_pppoe.h>
119: #endif
120:
1.121 yamt 121: #if NAGR > 0
122: #include <net/agr/ieee8023_slowprotocols.h> /* XXX */
123: #include <net/agr/ieee8023ad.h>
124: #include <net/agr/if_agrvar.h>
125: #endif
126:
1.78 thorpej 127: #if NBRIDGE > 0
128: #include <net/if_bridgevar.h>
129: #endif
130:
1.15 phil 131: #include <netinet/in.h>
1.1 cgd 132: #ifdef INET
1.4 mycroft 133: #include <netinet/in_var.h>
1.1 cgd 134: #endif
1.22 is 135: #include <netinet/if_inarp.h>
1.1 cgd 136:
1.44 itojun 137: #ifdef INET6
138: #ifndef INET
139: #include <netinet/in.h>
140: #endif
141: #include <netinet6/in6_var.h>
142: #include <netinet6/nd6.h>
143: #endif
144:
1.1 cgd 145:
1.133 liamjfoy 146: #include "carp.h"
147: #if NCARP > 0
148: #include <netinet/ip_carp.h>
149: #endif
150:
1.23 christos 151: #ifdef NETATALK
152: #include <netatalk/at.h>
153: #include <netatalk/at_var.h>
154: #include <netatalk/at_extern.h>
155:
156: #define llc_snap_org_code llc_un.type_snap.org_code
157: #define llc_snap_ether_type llc_un.type_snap.ether_type
158:
159: extern u_char at_org_code[3];
160: extern u_char aarp_org_code[3];
161: #endif /* NETATALK */
162:
1.182 kefren 163: #ifdef MPLS
164: #include <netmpls/mpls.h>
165: #include <netmpls/mpls_var.h>
166: #endif
167:
1.123 matt 168: static struct timeval bigpktppslim_last;
169: static int bigpktppslim = 2; /* XXX */
170: static int bigpktpps_count;
1.203 ozaki-r 171: static kmutex_t bigpktpps_lock __cacheline_aligned;
1.123 matt 172:
173:
1.118 yamt 174: const uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
175: { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1.121 yamt 176: const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] =
177: { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
1.8 mycroft 178: #define senderr(e) { error = (e); goto bad;}
1.1 cgd 179:
1.128 thorpej 180: static int ether_output(struct ifnet *, struct mbuf *,
1.222 ozaki-r 181: const struct sockaddr *, const struct rtentry *);
1.42 thorpej 182:
1.1 cgd 183: /*
184: * Ethernet output routine.
185: * Encapsulate a packet of type family for the local net.
1.22 is 186: * Assumes that ifp is actually pointer to ethercom structure.
1.1 cgd 187: */
1.42 thorpej 188: static int
1.178 dyoung 189: ether_output(struct ifnet * const ifp0, struct mbuf * const m0,
190: const struct sockaddr * const dst,
1.222 ozaki-r 191: const struct rtentry *rt)
1.1 cgd 192: {
1.162 matt 193: uint16_t etype = 0;
1.122 christos 194: int error = 0, hdrcmplt = 0;
1.145 dyoung 195: uint8_t esrc[6], edst[6];
1.29 mrg 196: struct mbuf *m = m0;
1.151 dyoung 197: struct mbuf *mcopy = NULL;
1.29 mrg 198: struct ether_header *eh;
1.133 liamjfoy 199: struct ifnet *ifp = ifp0;
1.24 christos 200: #ifdef INET
1.22 is 201: struct arphdr *ah;
1.24 christos 202: #endif /* INET */
1.23 christos 203: #ifdef NETATALK
204: struct at_ifaddr *aa;
205: #endif /* NETATALK */
1.1 cgd 206:
1.206 ozaki-r 207: #ifndef NET_MPSAFE
1.197 bouyer 208: KASSERT(KERNEL_LOCKED_P());
1.206 ozaki-r 209: #endif
1.197 bouyer 210:
1.104 matt 211: #ifdef MBUFTRACE
1.116 jonathan 212: m_claimm(m, ifp->if_mowner);
1.104 matt 213: #endif
1.133 liamjfoy 214:
215: #if NCARP > 0
216: if (ifp->if_type == IFT_CARP) {
217: struct ifaddr *ifa;
218:
219: /* loop back if this is going to the carp interface */
220: if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
221: (ifa = ifa_ifwithaddr(dst)) != NULL &&
222: ifa->ifa_ifp == ifp0)
1.210 ozaki-r 223: return looutput(ifp0, m, dst, rt);
1.133 liamjfoy 224:
225: ifp = ifp->if_carpdev;
226: /* ac = (struct arpcom *)ifp; */
227:
228: if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
229: (IFF_UP|IFF_RUNNING))
230: senderr(ENETDOWN);
231: }
232: #endif /* NCARP > 0 */
233:
1.8 mycroft 234: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
235: senderr(ENETDOWN);
1.72 thorpej 236:
1.1 cgd 237: switch (dst->sa_family) {
238:
239: #ifdef INET
240: case AF_INET:
1.22 is 241: if (m->m_flags & M_BCAST)
1.174 isaki 242: (void)memcpy(edst, etherbroadcastaddr, sizeof(edst));
1.145 dyoung 243: else if (m->m_flags & M_MCAST)
244: ETHER_MAP_IP_MULTICAST(&satocsin(dst)->sin_addr, edst);
1.217 christos 245: else if ((error = arpresolve(ifp, rt, m, dst, edst,
246: sizeof(edst))) != 0)
1.214 roy 247: return error == EWOULDBLOCK ? 0 : error;
1.3 hpeyerl 248: /* If broadcasting on a simplex interface, loopback a copy */
249: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
1.1 cgd 250: mcopy = m_copy(m, 0, (int)M_COPYALL);
1.17 mycroft 251: etype = htons(ETHERTYPE_IP);
1.8 mycroft 252: break;
1.22 is 253:
254: case AF_ARP:
255: ah = mtod(m, struct arphdr *);
256: if (m->m_flags & M_BCAST)
1.174 isaki 257: (void)memcpy(edst, etherbroadcastaddr, sizeof(edst));
1.131 mrg 258: else {
1.147 christos 259: void *tha = ar_tha(ah);
1.131 mrg 260:
1.173 christos 261: if (tha == NULL) {
262: /* fake with ARPHDR_IEEE1394 */
263: return 0;
264: }
1.146 dyoung 265: memcpy(edst, tha, sizeof(edst));
1.131 mrg 266: }
1.120 perry 267:
1.22 is 268: ah->ar_hrd = htons(ARPHRD_ETHER);
269:
1.107 itojun 270: switch (ntohs(ah->ar_op)) {
1.22 is 271: case ARPOP_REVREQUEST:
272: case ARPOP_REVREPLY:
273: etype = htons(ETHERTYPE_REVARP);
274: break;
275:
276: case ARPOP_REQUEST:
277: case ARPOP_REPLY:
278: default:
279: etype = htons(ETHERTYPE_ARP);
280: }
281:
282: break;
1.1 cgd 283: #endif
1.44 itojun 284: #ifdef INET6
285: case AF_INET6:
1.166 dyoung 286: if (!nd6_storelladdr(ifp, rt, m, dst, edst, sizeof(edst))){
1.67 itojun 287: /* something bad happened */
1.99 itojun 288: return (0);
1.51 itojun 289: }
1.44 itojun 290: etype = htons(ETHERTYPE_IPV6);
291: break;
292: #endif
1.23 christos 293: #ifdef NETATALK
294: case AF_APPLETALK:
1.214 roy 295: if (aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) {
1.23 christos 296: #ifdef NETATALKDEBUG
297: printf("aarpresolv failed\n");
298: #endif /* NETATALKDEBUG */
299: return (0);
300: }
301: /*
302: * ifaddr is the first thing in at_ifaddr
303: */
304: aa = (struct at_ifaddr *) at_ifawithnet(
1.145 dyoung 305: (const struct sockaddr_at *)dst, ifp);
1.23 christos 306: if (aa == NULL)
307: goto bad;
1.120 perry 308:
1.23 christos 309: /*
310: * In the phase 2 case, we need to prepend an mbuf for the
311: * llc header. Since we must preserve the value of m,
312: * which is passed to us by value, we m_copy() the first
313: * mbuf, and use it for our llc header.
314: */
315: if (aa->aa_flags & AFA_PHASE2) {
316: struct llc llc;
317:
1.43 bouyer 318: M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
1.23 christos 319: llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
320: llc.llc_control = LLC_UI;
1.146 dyoung 321: memcpy(llc.llc_snap_org_code, at_org_code,
1.23 christos 322: sizeof(llc.llc_snap_org_code));
1.38 kim 323: llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
1.147 christos 324: memcpy(mtod(m, void *), &llc, sizeof(struct llc));
1.23 christos 325: } else {
1.38 kim 326: etype = htons(ETHERTYPE_ATALK);
1.23 christos 327: }
328: break;
329: #endif /* NETATALK */
1.31 thorpej 330: case pseudo_AF_HDRCMPLT:
331: hdrcmplt = 1;
1.146 dyoung 332: memcpy(esrc,
333: ((const struct ether_header *)dst->sa_data)->ether_shost,
334: sizeof(esrc));
1.31 thorpej 335: /* FALLTHROUGH */
336:
1.1 cgd 337: case AF_UNSPEC:
1.146 dyoung 338: memcpy(edst,
339: ((const struct ether_header *)dst->sa_data)->ether_dhost,
340: sizeof(edst));
1.8 mycroft 341: /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
1.145 dyoung 342: etype = ((const struct ether_header *)dst->sa_data)->ether_type;
1.8 mycroft 343: break;
1.1 cgd 344:
345: default:
1.21 christos 346: printf("%s: can't handle af%d\n", ifp->if_xname,
1.1 cgd 347: dst->sa_family);
1.8 mycroft 348: senderr(EAFNOSUPPORT);
1.1 cgd 349: }
350:
1.182 kefren 351: #ifdef MPLS
1.210 ozaki-r 352: {
353: struct m_tag *mtag;
354: mtag = m_tag_find(m, PACKET_TAG_MPLS, NULL);
355: if (mtag != NULL) {
356: /* Having the tag itself indicates it's MPLS */
1.184 dyoung 357: etype = htons(ETHERTYPE_MPLS);
1.210 ozaki-r 358: m_tag_delete(m, mtag);
359: }
1.184 dyoung 360: }
1.182 kefren 361: #endif
362:
1.1 cgd 363: if (mcopy)
1.145 dyoung 364: (void)looutput(ifp, mcopy, dst, rt);
1.16 mycroft 365:
1.50 matt 366: /* If no ether type is set, this must be a 802.2 formatted packet.
367: */
368: if (etype == 0)
369: etype = htons(m->m_pkthdr.len);
1.1 cgd 370: /*
371: * Add local net header. If no space in first mbuf,
372: * allocate another.
373: */
374: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
1.8 mycroft 375: if (m == 0)
376: senderr(ENOBUFS);
1.1 cgd 377: eh = mtod(m, struct ether_header *);
1.96 thorpej 378: /* Note: etype is already in network byte order. */
1.143 cbiere 379: (void)memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type));
1.146 dyoung 380: memcpy(eh->ether_dhost, edst, sizeof(edst));
1.31 thorpej 381: if (hdrcmplt)
1.146 dyoung 382: memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
1.31 thorpej 383: else
1.153 dyoung 384: memcpy(eh->ether_shost, CLLADDR(ifp->if_sadl),
1.31 thorpej 385: sizeof(eh->ether_shost));
1.77 thorpej 386:
1.133 liamjfoy 387: #if NCARP > 0
388: if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
1.153 dyoung 389: memcpy(eh->ether_shost, CLLADDR(ifp0->if_sadl),
1.133 liamjfoy 390: sizeof(eh->ether_shost));
391: }
392: #endif /* NCARP > 0 */
393:
1.195 rmind 394: if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0)
1.77 thorpej 395: return (error);
396: if (m == NULL)
397: return (0);
398:
1.78 thorpej 399: #if NBRIDGE > 0
400: /*
401: * Bridges require special output handling.
402: */
403: if (ifp->if_bridge)
404: return (bridge_output(ifp, m, NULL, NULL));
405: #endif
406:
1.133 liamjfoy 407: #if NCARP > 0
408: if (ifp != ifp0)
409: ifp0->if_obytes += m->m_pkthdr.len + ETHER_HDR_LEN;
410: #endif /* NCARP > 0 */
411:
1.77 thorpej 412: #ifdef ALTQ
413: /*
414: * If ALTQ is enabled on the parent interface, do
415: * classification; the queueing discipline might not
416: * require classification, but might require the
417: * address family/header pointer in the pktattr.
418: */
419: if (ALTQ_IS_ENABLED(&ifp->if_snd))
1.220 knakahar 420: altq_etherclassify(&ifp->if_snd, m);
1.77 thorpej 421: #endif
1.221 knakahar 422: return ifq_enqueue(ifp, m);
1.1 cgd 423:
424: bad:
425: if (m)
426: m_freem(m);
427: return (error);
428: }
1.76 thorpej 429:
430: #ifdef ALTQ
431: /*
432: * This routine is a slight hack to allow a packet to be classified
433: * if the Ethernet headers are present. It will go away when ALTQ's
434: * classification engine understands link headers.
435: */
436: void
1.220 knakahar 437: altq_etherclassify(struct ifaltq *ifq, struct mbuf *m)
1.76 thorpej 438: {
439: struct ether_header *eh;
1.162 matt 440: uint16_t ether_type;
1.76 thorpej 441: int hlen, af, hdrsize;
1.147 christos 442: void *hdr;
1.76 thorpej 443:
444: hlen = ETHER_HDR_LEN;
445: eh = mtod(m, struct ether_header *);
446:
447: ether_type = htons(eh->ether_type);
448:
449: if (ether_type < ETHERMTU) {
450: /* LLC/SNAP */
451: struct llc *llc = (struct llc *)(eh + 1);
452: hlen += 8;
453:
454: if (m->m_len < hlen ||
455: llc->llc_dsap != LLC_SNAP_LSAP ||
456: llc->llc_ssap != LLC_SNAP_LSAP ||
457: llc->llc_control != LLC_UI) {
458: /* Not SNAP. */
459: goto bad;
460: }
461:
462: ether_type = htons(llc->llc_un.type_snap.ether_type);
463: }
464:
465: switch (ether_type) {
466: case ETHERTYPE_IP:
467: af = AF_INET;
468: hdrsize = 20; /* sizeof(struct ip) */
469: break;
470:
471: case ETHERTYPE_IPV6:
472: af = AF_INET6;
473: hdrsize = 40; /* sizeof(struct ip6_hdr) */
474: break;
475:
476: default:
477: af = AF_UNSPEC;
478: hdrsize = 0;
479: break;
480: }
481:
1.95 itojun 482: while (m->m_len <= hlen) {
483: hlen -= m->m_len;
484: m = m->m_next;
485: }
1.76 thorpej 486: if (m->m_len < (hlen + hdrsize)) {
487: /*
1.95 itojun 488: * protocol header not in a single mbuf.
489: * We can't cope with this situation right
1.76 thorpej 490: * now (but it shouldn't ever happen, really, anyhow).
491: */
1.92 itojun 492: #ifdef DEBUG
1.78 thorpej 493: printf("altq_etherclassify: headers span multiple mbufs: "
494: "%d < %d\n", m->m_len, (hlen + hdrsize));
1.92 itojun 495: #endif
1.76 thorpej 496: goto bad;
497: }
498:
499: m->m_data += hlen;
500: m->m_len -= hlen;
501:
1.147 christos 502: hdr = mtod(m, void *);
1.76 thorpej 503:
504: if (ALTQ_NEEDS_CLASSIFY(ifq))
1.219 knakahar 505: m->m_pkthdr.pattr_class =
1.76 thorpej 506: (*ifq->altq_classify)(ifq->altq_clfier, m, af);
1.219 knakahar 507: m->m_pkthdr.pattr_af = af;
508: m->m_pkthdr.pattr_hdr = hdr;
1.76 thorpej 509:
510: m->m_data -= hlen;
511: m->m_len += hlen;
512:
513: return;
514:
515: bad:
1.219 knakahar 516: m->m_pkthdr.pattr_class = NULL;
517: m->m_pkthdr.pattr_hdr = NULL;
518: m->m_pkthdr.pattr_af = AF_UNSPEC;
1.76 thorpej 519: }
520: #endif /* ALTQ */
1.1 cgd 521:
522: /*
523: * Process a received Ethernet packet;
1.42 thorpej 524: * the packet is in the mbuf chain m with
525: * the ether header.
1.1 cgd 526: */
1.133 liamjfoy 527: void
1.58 matt 528: ether_input(struct ifnet *ifp, struct mbuf *m)
1.1 cgd 529: {
1.91 thorpej 530: struct ethercom *ec = (struct ethercom *) ifp;
1.199 rmind 531: pktqueue_t *pktq = NULL;
532: struct ifqueue *inq = NULL;
1.162 matt 533: uint16_t etype;
1.42 thorpej 534: struct ether_header *eh;
1.187 matt 535: size_t ehlen;
1.204 tls 536: static int earlypkts;
1.198 msaitoh 537: int isr = 0;
1.194 joerg 538: #if defined (LLC) || defined(NETATALK)
1.29 mrg 539: struct llc *l;
1.18 christos 540: #endif
1.1 cgd 541:
1.216 ozaki-r 542: KASSERT(!cpu_intr_p());
543:
1.8 mycroft 544: if ((ifp->if_flags & IFF_UP) == 0) {
545: m_freem(m);
546: return;
547: }
1.42 thorpej 548:
1.104 matt 549: #ifdef MBUFTRACE
1.116 jonathan 550: m_claimm(m, &ec->ec_rx_mowner);
1.104 matt 551: #endif
1.42 thorpej 552: eh = mtod(m, struct ether_header *);
1.63 thorpej 553: etype = ntohs(eh->ether_type);
1.187 matt 554: ehlen = sizeof(*eh);
1.63 thorpej 555:
1.204 tls 556: if(__predict_false(earlypkts < 100 || !rnd_initial_entropy)) {
557: rnd_add_data(NULL, eh, ehlen, 0);
558: earlypkts++;
559: }
560:
1.63 thorpej 561: /*
562: * Determine if the packet is within its size limits.
563: */
1.182 kefren 564: if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len >
1.83 thorpej 565: ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
1.203 ozaki-r 566: mutex_enter(&bigpktpps_lock);
1.123 matt 567: if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count,
568: bigpktppslim)) {
569: printf("%s: discarding oversize frame (len=%d)\n",
570: ifp->if_xname, m->m_pkthdr.len);
571: }
1.203 ozaki-r 572: mutex_exit(&bigpktpps_lock);
1.63 thorpej 573: m_freem(m);
574: return;
575: }
1.77 thorpej 576:
1.84 thorpej 577: if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
578: /*
579: * If this is not a simplex interface, drop the packet
580: * if it came from us.
581: */
582: if ((ifp->if_flags & IFF_SIMPLEX) == 0 &&
1.153 dyoung 583: memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost,
1.84 thorpej 584: ETHER_ADDR_LEN) == 0) {
585: m_freem(m);
586: return;
587: }
588:
589: if (memcmp(etherbroadcastaddr,
590: eh->ether_dhost, ETHER_ADDR_LEN) == 0)
591: m->m_flags |= M_BCAST;
592: else
593: m->m_flags |= M_MCAST;
594: ifp->if_imcasts++;
595: }
596:
1.79 thorpej 597: /* If the CRC is still on the packet, trim it off. */
598: if (m->m_flags & M_HASFCS) {
599: m_adj(m, -ETHER_CRC_LEN);
600: m->m_flags &= ~M_HASFCS;
601: }
602:
1.42 thorpej 603: ifp->if_ibytes += m->m_pkthdr.len;
1.78 thorpej 604:
1.201 ozaki-r 605: #if NCARP > 0
606: if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) {
607: /*
608: * clear M_PROMISC, in case the packets comes from a
609: * vlan
610: */
1.137 rpaulo 611: m->m_flags &= ~M_PROMISC;
1.201 ozaki-r 612: if (carp_input(m, (uint8_t *)&eh->ether_shost,
613: (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0)
1.137 rpaulo 614: return;
1.201 ozaki-r 615: }
1.133 liamjfoy 616: #endif /* NCARP > 0 */
1.201 ozaki-r 617: if ((m->m_flags & (M_BCAST|M_MCAST|M_PROMISC)) == 0 &&
618: (ifp->if_flags & IFF_PROMISC) != 0 &&
619: memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
620: ETHER_ADDR_LEN) != 0) {
621: m->m_flags |= M_PROMISC;
1.70 bouyer 622: }
1.78 thorpej 623:
1.106 bouyer 624: if ((m->m_flags & M_PROMISC) == 0) {
1.195 rmind 625: if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0)
1.106 bouyer 626: return;
627: if (m == NULL)
628: return;
1.78 thorpej 629:
1.106 bouyer 630: eh = mtod(m, struct ether_header *);
631: etype = ntohs(eh->ether_type);
1.187 matt 632: ehlen = sizeof(*eh);
1.106 bouyer 633: }
1.70 bouyer 634:
1.172 darran 635: #if NAGR > 0
636: if (ifp->if_agrprivate &&
637: __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) {
638: m->m_flags &= ~M_PROMISC;
639: agr_input(ifp, m);
640: return;
641: }
642: #endif /* NAGR > 0 */
643:
1.91 thorpej 644: /*
645: * If VLANs are configured on the interface, check to
646: * see if the device performed the decapsulation and
647: * provided us with the tag.
648: */
1.114 simonb 649: if (ec->ec_nvlans && m_tag_find(m, PACKET_TAG_VLAN, NULL) != NULL) {
1.70 bouyer 650: #if NVLAN > 0
651: /*
652: * vlan_input() will either recursively call ether_input()
653: * or drop the packet.
654: */
1.91 thorpej 655: vlan_input(ifp, m);
656: #else
657: m_freem(m);
1.70 bouyer 658: #endif
1.61 thorpej 659: return;
660: }
1.1 cgd 661:
1.59 thorpej 662: /*
663: * Handle protocols that expect to have the Ethernet header
664: * (and possibly FCS) intact.
665: */
666: switch (etype) {
1.187 matt 667: case ETHERTYPE_VLAN: {
668: struct ether_vlan_header *evl = (void *)eh;
669: /*
670: * If there is a tag of 0, then the VLAN header was probably
671: * just being used to store the priority. Extract the ether
672: * type, and if IP or IPV6, let them deal with it.
673: */
674: if (m->m_len <= sizeof(*evl)
675: && EVL_VLANOFTAG(evl->evl_tag) == 0) {
676: etype = ntohs(evl->evl_proto);
677: ehlen = sizeof(*evl);
678: if ((m->m_flags & M_PROMISC) == 0
679: && (etype == ETHERTYPE_IP
680: || etype == ETHERTYPE_IPV6))
681: break;
682: }
1.59 thorpej 683: #if NVLAN > 0
684: /*
685: * vlan_input() will either recursively call ether_input()
686: * or drop the packet.
687: */
1.63 thorpej 688: if (((struct ethercom *)ifp)->ec_nvlans != 0)
689: vlan_input(ifp, m);
1.65 enami 690: else
1.187 matt 691: #endif /* NVLAN > 0 */
1.65 enami 692: m_freem(m);
1.59 thorpej 693: return;
1.187 matt 694: }
1.81 martin 695: #if NPPPOE > 0
696: case ETHERTYPE_PPPOEDISC:
1.218 ozaki-r 697: pppoedisc_input(ifp, m);
698: return;
1.81 martin 699: case ETHERTYPE_PPPOE:
1.218 ozaki-r 700: pppoe_input(ifp, m);
1.81 martin 701: return;
702: #endif /* NPPPOE > 0 */
1.121 yamt 703: case ETHERTYPE_SLOWPROTOCOLS: {
704: uint8_t subtype;
705:
706: #if defined(DIAGNOSTIC)
707: if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) {
708: panic("ether_input: too short slow protocol packet");
709: }
710: #endif
711: m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype);
712: switch (subtype) {
713: #if NAGR > 0
714: case SLOWPROTOCOLS_SUBTYPE_LACP:
715: if (ifp->if_agrprivate) {
716: ieee8023ad_lacp_input(ifp, m);
717: return;
718: }
719: break;
720:
721: case SLOWPROTOCOLS_SUBTYPE_MARKER:
722: if (ifp->if_agrprivate) {
723: ieee8023ad_marker_input(ifp, m);
724: return;
725: }
726: break;
727: #endif /* NAGR > 0 */
728: default:
729: if (subtype == 0 || subtype > 10) {
730: /* illegal value */
731: m_freem(m);
732: return;
733: }
734: /* unknown subtype */
735: break;
736: }
737: /* FALLTHROUGH */
738: }
1.59 thorpej 739: default:
1.106 bouyer 740: if (m->m_flags & M_PROMISC) {
741: m_freem(m);
742: return;
743: }
1.59 thorpej 744: }
1.42 thorpej 745:
1.45 thorpej 746: /* If the CRC is still on the packet, trim it off. */
1.79 thorpej 747: if (m->m_flags & M_HASFCS) {
1.45 thorpej 748: m_adj(m, -ETHER_CRC_LEN);
1.79 thorpej 749: m->m_flags &= ~M_HASFCS;
750: }
1.42 thorpej 751:
1.139 is 752: if (etype > ETHERMTU + sizeof (struct ether_header)) {
753: /* Strip off the Ethernet header. */
1.187 matt 754: m_adj(m, ehlen);
1.139 is 755:
756: switch (etype) {
1.1 cgd 757: #ifdef INET
1.139 is 758: case ETHERTYPE_IP:
1.30 matt 759: #ifdef GATEWAY
1.139 is 760: if (ipflow_fastforward(m))
761: return;
1.30 matt 762: #endif
1.199 rmind 763: pktq = ip_pktq;
1.139 is 764: break;
1.1 cgd 765:
1.139 is 766: case ETHERTYPE_ARP:
1.198 msaitoh 767: isr = NETISR_ARP;
1.139 is 768: inq = &arpintrq;
769: break;
1.7 glass 770:
1.139 is 771: case ETHERTYPE_REVARP:
772: revarpinput(m); /* XXX queue? */
773: return;
1.1 cgd 774: #endif
1.44 itojun 775: #ifdef INET6
1.139 is 776: case ETHERTYPE_IPV6:
1.196 pooka 777: if (__predict_false(!in6_present)) {
778: m_freem(m);
779: return;
780: }
1.148 liamjfoy 781: #ifdef GATEWAY
1.192 christos 782: if (ip6flow_fastforward(&m))
1.148 liamjfoy 783: return;
784: #endif
1.199 rmind 785: pktq = ip6_pktq;
1.139 is 786: break;
1.44 itojun 787: #endif
1.23 christos 788: #ifdef NETATALK
1.174 isaki 789: case ETHERTYPE_ATALK:
1.198 msaitoh 790: isr = NETISR_ATALK;
1.174 isaki 791: inq = &atintrq1;
792: break;
793: case ETHERTYPE_AARP:
1.139 is 794: /* probably this should be done with a NETISR as well */
1.175 mbalmer 795: aarpinput(ifp, m); /* XXX */
1.174 isaki 796: return;
1.23 christos 797: #endif /* NETATALK */
1.182 kefren 798: #ifdef MPLS
799: case ETHERTYPE_MPLS:
1.198 msaitoh 800: isr = NETISR_MPLS;
1.182 kefren 801: inq = &mplsintrq;
802: break;
803: #endif
1.139 is 804: default:
805: m_freem(m);
806: return;
807: }
808: } else {
1.194 joerg 809: #if defined (LLC) || defined (NETATALK)
1.139 is 810: l = (struct llc *)(eh+1);
1.8 mycroft 811: switch (l->llc_dsap) {
1.23 christos 812: #ifdef NETATALK
813: case LLC_SNAP_LSAP:
814: switch (l->llc_control) {
815: case LLC_UI:
816: if (l->llc_ssap != LLC_SNAP_LSAP) {
817: goto dropanyway;
818: }
1.120 perry 819:
1.166 dyoung 820: if (memcmp(&(l->llc_snap_org_code)[0],
1.23 christos 821: at_org_code, sizeof(at_org_code)) == 0 &&
822: ntohs(l->llc_snap_ether_type) ==
1.38 kim 823: ETHERTYPE_ATALK) {
1.23 christos 824: inq = &atintrq2;
1.139 is 825: m_adj(m, sizeof(struct ether_header)
826: + sizeof(struct llc));
1.198 msaitoh 827: isr = NETISR_ATALK;
1.23 christos 828: break;
829: }
830:
1.166 dyoung 831: if (memcmp(&(l->llc_snap_org_code)[0],
1.23 christos 832: aarp_org_code,
833: sizeof(aarp_org_code)) == 0 &&
834: ntohs(l->llc_snap_ether_type) ==
835: ETHERTYPE_AARP) {
1.139 is 836: m_adj( m, sizeof(struct ether_header)
837: + sizeof(struct llc));
1.23 christos 838: aarpinput(ifp, m); /* XXX */
839: return;
840: }
1.120 perry 841:
1.23 christos 842: default:
843: goto dropanyway;
844: }
845: break;
1.1 cgd 846: dropanyway:
1.142 bouyer 847: #endif
1.1 cgd 848: default:
1.8 mycroft 849: m_freem(m);
850: return;
851: }
1.139 is 852: #else /* ISO || LLC || NETATALK*/
853: m_freem(m);
854: return;
1.23 christos 855: #endif /* ISO || LLC || NETATALK*/
1.1 cgd 856: }
857:
1.199 rmind 858: if (__predict_true(pktq)) {
859: const uint32_t h = pktq_rps_hash(m);
860: if (__predict_false(!pktq_enqueue(pktq, m, h))) {
861: m_freem(m);
862: }
863: return;
864: }
865:
866: if (__predict_false(!inq)) {
867: /* Should not happen. */
868: m_freem(m);
869: return;
870: }
1.1 cgd 871: if (IF_QFULL(inq)) {
872: IF_DROP(inq);
873: m_freem(m);
1.198 msaitoh 874: } else {
1.1 cgd 875: IF_ENQUEUE(inq, m);
1.198 msaitoh 876: schednetisr(isr);
877: }
1.1 cgd 878: }
879:
880: /*
881: * Convert Ethernet address to printable (loggable) representation.
882: */
883: char *
1.58 matt 884: ether_sprintf(const u_char *ap)
1.1 cgd 885: {
1.129 christos 886: static char etherbuf[3 * ETHER_ADDR_LEN];
887: return ether_snprintf(etherbuf, sizeof(etherbuf), ap);
888: }
889:
890: char *
891: ether_snprintf(char *buf, size_t len, const u_char *ap)
892: {
893: char *cp = buf;
894: size_t i;
1.1 cgd 895:
1.129 christos 896: for (i = 0; i < len / 3; i++) {
1.124 christos 897: *cp++ = hexdigits[*ap >> 4];
898: *cp++ = hexdigits[*ap++ & 0xf];
1.1 cgd 899: *cp++ = ':';
900: }
1.129 christos 901: *--cp = '\0';
902: return buf;
1.1 cgd 903: }
1.8 mycroft 904:
905: /*
906: * Perform common duties while attaching to interface list
907: */
908: void
1.162 matt 909: ether_ifattach(struct ifnet *ifp, const uint8_t *lla)
1.8 mycroft 910: {
1.104 matt 911: struct ethercom *ec = (struct ethercom *)ifp;
1.8 mycroft 912:
913: ifp->if_type = IFT_ETHER;
1.94 enami 914: ifp->if_hdrlen = ETHER_HDR_LEN;
1.73 thorpej 915: ifp->if_dlt = DLT_EN10MB;
1.8 mycroft 916: ifp->if_mtu = ETHERMTU;
1.12 mycroft 917: ifp->if_output = ether_output;
1.216 ozaki-r 918: ifp->_if_input = ether_input;
1.54 thorpej 919: if (ifp->if_baudrate == 0)
920: ifp->if_baudrate = IF_Mbps(10); /* just a default */
1.75 thorpej 921:
1.170 dyoung 922: if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla));
1.75 thorpej 923:
1.104 matt 924: LIST_INIT(&ec->ec_multiaddrs);
1.26 is 925: ifp->if_broadcastaddr = etherbroadcastaddr;
1.177 joerg 926: bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header));
1.104 matt 927: #ifdef MBUFTRACE
1.108 itojun 928: strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
929: sizeof(ec->ec_tx_mowner.mo_name));
930: strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
931: sizeof(ec->ec_tx_mowner.mo_descr));
932: strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
933: sizeof(ec->ec_rx_mowner.mo_name));
934: strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
935: sizeof(ec->ec_rx_mowner.mo_descr));
1.104 matt 936: MOWNER_ATTACH(&ec->ec_tx_mowner);
937: MOWNER_ATTACH(&ec->ec_rx_mowner);
938: ifp->if_mowner = &ec->ec_tx_mowner;
939: #endif
1.52 thorpej 940: }
941:
942: void
1.58 matt 943: ether_ifdetach(struct ifnet *ifp)
1.52 thorpej 944: {
1.63 thorpej 945: struct ethercom *ec = (void *) ifp;
946: struct ether_multi *enm;
947: int s;
1.69 thorpej 948:
1.190 christos 949: /*
950: * Prevent further calls to ioctl (for example turning off
951: * promiscuous mode from the bridge code), which eventually can
952: * call if_init() which can cause panics because the interface
953: * is in the process of being detached. Return device not configured
954: * instead.
955: */
956: ifp->if_ioctl = (int (*)(struct ifnet *, u_long, void *))enxio;
957:
1.115 dyoung 958: #if NBRIDGE > 0
959: if (ifp->if_bridge)
960: bridge_ifdetach(ifp);
961: #endif
962:
1.177 joerg 963: bpf_detach(ifp);
1.64 thorpej 964:
965: #if NVLAN > 0
966: if (ec->ec_nvlans)
967: vlan_ifdetach(ifp);
968: #endif
1.63 thorpej 969:
1.79 thorpej 970: s = splnet();
1.63 thorpej 971: while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) {
972: LIST_REMOVE(enm, enm_list);
1.100 jdolecek 973: free(enm, M_IFMADDR);
1.63 thorpej 974: ec->ec_multicnt--;
975: }
976: splx(s);
1.52 thorpej 977:
1.189 chs 978: ifp->if_mowner = NULL;
1.104 matt 979: MOWNER_DETACH(&ec->ec_rx_mowner);
980: MOWNER_DETACH(&ec->ec_tx_mowner);
1.53 thorpej 981: }
982:
1.56 thorpej 983: #if 0
984: /*
985: * This is for reference. We have a table-driven version
986: * of the little-endian crc32 generator, which is faster
987: * than the double-loop.
988: */
1.162 matt 989: uint32_t
990: ether_crc32_le(const uint8_t *buf, size_t len)
1.53 thorpej 991: {
1.162 matt 992: uint32_t c, crc, carry;
1.53 thorpej 993: size_t i, j;
994:
995: crc = 0xffffffffU; /* initial value */
996:
997: for (i = 0; i < len; i++) {
998: c = buf[i];
999: for (j = 0; j < 8; j++) {
1000: carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
1001: crc >>= 1;
1002: c >>= 1;
1003: if (carry)
1.56 thorpej 1004: crc = (crc ^ ETHER_CRC_POLY_LE);
1.53 thorpej 1005: }
1006: }
1007:
1008: return (crc);
1009: }
1.56 thorpej 1010: #else
1.162 matt 1011: uint32_t
1012: ether_crc32_le(const uint8_t *buf, size_t len)
1.56 thorpej 1013: {
1.162 matt 1014: static const uint32_t crctab[] = {
1.56 thorpej 1015: 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1016: 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1017: 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1018: 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1019: };
1.162 matt 1020: uint32_t crc;
1.98 thorpej 1021: size_t i;
1.56 thorpej 1022:
1023: crc = 0xffffffffU; /* initial value */
1024:
1025: for (i = 0; i < len; i++) {
1026: crc ^= buf[i];
1027: crc = (crc >> 4) ^ crctab[crc & 0xf];
1028: crc = (crc >> 4) ^ crctab[crc & 0xf];
1029: }
1030:
1031: return (crc);
1032: }
1033: #endif
1.53 thorpej 1034:
1.162 matt 1035: uint32_t
1036: ether_crc32_be(const uint8_t *buf, size_t len)
1.53 thorpej 1037: {
1.162 matt 1038: uint32_t c, crc, carry;
1.53 thorpej 1039: size_t i, j;
1040:
1041: crc = 0xffffffffU; /* initial value */
1042:
1043: for (i = 0; i < len; i++) {
1044: c = buf[i];
1045: for (j = 0; j < 8; j++) {
1046: carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
1047: crc <<= 1;
1048: c >>= 1;
1049: if (carry)
1050: crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
1051: }
1052: }
1053:
1054: return (crc);
1.8 mycroft 1055: }
1056:
1.48 is 1057: #ifdef INET
1.118 yamt 1058: const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN] =
1059: { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
1060: const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN] =
1061: { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
1.48 is 1062: #endif
1.44 itojun 1063: #ifdef INET6
1.118 yamt 1064: const uint8_t ether_ip6multicast_min[ETHER_ADDR_LEN] =
1065: { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
1066: const uint8_t ether_ip6multicast_max[ETHER_ADDR_LEN] =
1067: { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
1.44 itojun 1068: #endif
1.60 enami 1069:
1.3 hpeyerl 1070: /*
1.138 rpaulo 1071: * ether_aton implementation, not using a static buffer.
1072: */
1073: int
1.180 christos 1074: ether_aton_r(u_char *dest, size_t len, const char *str)
1.138 rpaulo 1075: {
1.180 christos 1076: const u_char *cp = (const void *)str;
1077: u_char *ep;
1078:
1.185 tsutsui 1079: #define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10))
1.180 christos 1080:
1081: if (len < ETHER_ADDR_LEN)
1082: return ENOSPC;
1083:
1084: ep = dest + ETHER_ADDR_LEN;
1085:
1086: while (*cp) {
1087: if (!isxdigit(*cp))
1088: return EINVAL;
1089: *dest = atox(*cp);
1090: cp++;
1091: if (isxdigit(*cp)) {
1092: *dest = (*dest << 4) | atox(*cp);
1093: dest++;
1094: cp++;
1095: } else
1.181 christos 1096: dest++;
1.180 christos 1097: if (dest == ep)
1098: return *cp == '\0' ? 0 : ENAMETOOLONG;
1099: switch (*cp) {
1100: case ':':
1101: case '-':
1102: case '.':
1.179 jakllsch 1103: cp++;
1.180 christos 1104: break;
1.179 jakllsch 1105: }
1.180 christos 1106: }
1107: return ENOBUFS;
1.138 rpaulo 1108: }
1109:
1110: /*
1.60 enami 1111: * Convert a sockaddr into an Ethernet address or range of Ethernet
1112: * addresses.
1.3 hpeyerl 1113: */
1114: int
1.162 matt 1115: ether_multiaddr(const struct sockaddr *sa, uint8_t addrlo[ETHER_ADDR_LEN],
1116: uint8_t addrhi[ETHER_ADDR_LEN])
1.3 hpeyerl 1117: {
1.24 christos 1118: #ifdef INET
1.155 dyoung 1119: const struct sockaddr_in *sin;
1.24 christos 1120: #endif /* INET */
1.44 itojun 1121: #ifdef INET6
1.155 dyoung 1122: const struct sockaddr_in6 *sin6;
1.44 itojun 1123: #endif /* INET6 */
1.3 hpeyerl 1124:
1.60 enami 1125: switch (sa->sa_family) {
1.3 hpeyerl 1126:
1127: case AF_UNSPEC:
1.146 dyoung 1128: memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN);
1129: memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
1.3 hpeyerl 1130: break;
1131:
1132: #ifdef INET
1133: case AF_INET:
1.155 dyoung 1134: sin = satocsin(sa);
1.3 hpeyerl 1135: if (sin->sin_addr.s_addr == INADDR_ANY) {
1136: /*
1.60 enami 1137: * An IP address of INADDR_ANY means listen to
1138: * or stop listening to all of the Ethernet
1139: * multicast addresses used for IP.
1.3 hpeyerl 1140: * (This is for the sake of IP multicast routers.)
1141: */
1.146 dyoung 1142: memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
1143: memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
1.3 hpeyerl 1144: }
1145: else {
1146: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
1.146 dyoung 1147: memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
1.3 hpeyerl 1148: }
1149: break;
1150: #endif
1.44 itojun 1151: #ifdef INET6
1152: case AF_INET6:
1.155 dyoung 1153: sin6 = satocsin6(sa);
1.47 itojun 1154: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1.44 itojun 1155: /*
1.60 enami 1156: * An IP6 address of 0 means listen to or stop
1157: * listening to all of the Ethernet multicast
1158: * address used for IP6.
1.44 itojun 1159: * (This is used for multicast routers.)
1160: */
1.146 dyoung 1161: memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN);
1162: memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN);
1.44 itojun 1163: } else {
1164: ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
1.146 dyoung 1165: memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
1.44 itojun 1166: }
1167: break;
1168: #endif
1.3 hpeyerl 1169:
1170: default:
1.146 dyoung 1171: return EAFNOSUPPORT;
1.60 enami 1172: }
1.146 dyoung 1173: return 0;
1.60 enami 1174: }
1175:
1176: /*
1177: * Add an Ethernet multicast address or range of addresses to the list for a
1178: * given interface.
1179: */
1180: int
1.155 dyoung 1181: ether_addmulti(const struct sockaddr *sa, struct ethercom *ec)
1.60 enami 1182: {
1183: struct ether_multi *enm;
1184: u_char addrlo[ETHER_ADDR_LEN];
1185: u_char addrhi[ETHER_ADDR_LEN];
1.79 thorpej 1186: int s = splnet(), error;
1.60 enami 1187:
1.155 dyoung 1188: error = ether_multiaddr(sa, addrlo, addrhi);
1.60 enami 1189: if (error != 0) {
1.3 hpeyerl 1190: splx(s);
1.146 dyoung 1191: return error;
1.3 hpeyerl 1192: }
1193:
1194: /*
1195: * Verify that we have valid Ethernet multicast addresses.
1196: */
1.186 yamt 1197: if (!ETHER_IS_MULTICAST(addrlo) || !ETHER_IS_MULTICAST(addrhi)) {
1.3 hpeyerl 1198: splx(s);
1.146 dyoung 1199: return EINVAL;
1.3 hpeyerl 1200: }
1201: /*
1202: * See if the address range is already in the list.
1203: */
1.22 is 1204: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 1205: if (enm != NULL) {
1206: /*
1207: * Found it; just increment the reference count.
1208: */
1209: ++enm->enm_refcount;
1210: splx(s);
1.146 dyoung 1211: return 0;
1.3 hpeyerl 1212: }
1213: /*
1214: * New address or range; malloc a new multicast record
1215: * and link it into the interface's multicast list.
1216: */
1217: enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
1218: if (enm == NULL) {
1219: splx(s);
1.146 dyoung 1220: return ENOBUFS;
1.3 hpeyerl 1221: }
1.146 dyoung 1222: memcpy(enm->enm_addrlo, addrlo, 6);
1223: memcpy(enm->enm_addrhi, addrhi, 6);
1.3 hpeyerl 1224: enm->enm_refcount = 1;
1.22 is 1225: LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list);
1226: ec->ec_multicnt++;
1.3 hpeyerl 1227: splx(s);
1228: /*
1229: * Return ENETRESET to inform the driver that the list has changed
1230: * and its reception filter should be adjusted accordingly.
1231: */
1.146 dyoung 1232: return ENETRESET;
1.3 hpeyerl 1233: }
1234:
1235: /*
1236: * Delete a multicast address record.
1237: */
1238: int
1.155 dyoung 1239: ether_delmulti(const struct sockaddr *sa, struct ethercom *ec)
1.3 hpeyerl 1240: {
1.29 mrg 1241: struct ether_multi *enm;
1.60 enami 1242: u_char addrlo[ETHER_ADDR_LEN];
1243: u_char addrhi[ETHER_ADDR_LEN];
1.79 thorpej 1244: int s = splnet(), error;
1.3 hpeyerl 1245:
1.155 dyoung 1246: error = ether_multiaddr(sa, addrlo, addrhi);
1.60 enami 1247: if (error != 0) {
1.3 hpeyerl 1248: splx(s);
1.60 enami 1249: return (error);
1.3 hpeyerl 1250: }
1251:
1252: /*
1.66 thorpej 1253: * Look ur the address in our list.
1.3 hpeyerl 1254: */
1.22 is 1255: ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
1.3 hpeyerl 1256: if (enm == NULL) {
1257: splx(s);
1258: return (ENXIO);
1259: }
1260: if (--enm->enm_refcount != 0) {
1261: /*
1262: * Still some claims to this record.
1263: */
1264: splx(s);
1265: return (0);
1266: }
1267: /*
1268: * No remaining claims to this record; unlink and free it.
1269: */
1.13 mycroft 1270: LIST_REMOVE(enm, enm_list);
1.3 hpeyerl 1271: free(enm, M_IFMADDR);
1.22 is 1272: ec->ec_multicnt--;
1.3 hpeyerl 1273: splx(s);
1274: /*
1275: * Return ENETRESET to inform the driver that the list has changed
1276: * and its reception filter should be adjusted accordingly.
1277: */
1278: return (ENETRESET);
1.66 thorpej 1279: }
1280:
1.170 dyoung 1281: void
1282: ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb)
1283: {
1284: ec->ec_ifflags_cb = cb;
1285: }
1286:
1.66 thorpej 1287: /*
1288: * Common ioctls for Ethernet interfaces. Note, we must be
1289: * called at splnet().
1290: */
1291: int
1.147 christos 1292: ether_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.66 thorpej 1293: {
1294: struct ethercom *ec = (void *) ifp;
1.193 msaitoh 1295: struct eccapreq *eccr;
1.66 thorpej 1296: struct ifreq *ifr = (struct ifreq *)data;
1.170 dyoung 1297: struct if_laddrreq *iflr = data;
1298: const struct sockaddr_dl *sdl;
1299: static const uint8_t zero[ETHER_ADDR_LEN];
1.169 dyoung 1300: int error;
1.66 thorpej 1301:
1302: switch (cmd) {
1.170 dyoung 1303: case SIOCINITIFADDR:
1.191 matt 1304: {
1305: struct ifaddr *ifa = (struct ifaddr *)data;
1306: if (ifa->ifa_addr->sa_family != AF_LINK
1307: && (ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
1308: (IFF_UP|IFF_RUNNING)) {
1.170 dyoung 1309: ifp->if_flags |= IFF_UP;
1310: if ((error = (*ifp->if_init)(ifp)) != 0)
1311: return error;
1312: }
1.66 thorpej 1313: #ifdef INET
1.191 matt 1314: if (ifa->ifa_addr->sa_family == AF_INET)
1315: arp_ifinit(ifp, ifa);
1.66 thorpej 1316: #endif /* INET */
1.169 dyoung 1317: return 0;
1.191 matt 1318: }
1.66 thorpej 1319:
1320: case SIOCSIFMTU:
1.82 thorpej 1321: {
1322: int maxmtu;
1323:
1324: if (ec->ec_capabilities & ETHERCAP_JUMBO_MTU)
1325: maxmtu = ETHERMTU_JUMBO;
1326: else
1327: maxmtu = ETHERMTU;
1328:
1329: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > maxmtu)
1.169 dyoung 1330: return EINVAL;
1331: else if ((error = ifioctl_common(ifp, cmd, data)) != ENETRESET)
1332: return error;
1333: else if (ifp->if_flags & IFF_UP) {
1.88 thorpej 1334: /* Make sure the device notices the MTU change. */
1.169 dyoung 1335: return (*ifp->if_init)(ifp);
1336: } else
1337: return 0;
1.82 thorpej 1338: }
1.66 thorpej 1339:
1340: case SIOCSIFFLAGS:
1.170 dyoung 1341: if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1342: return error;
1.169 dyoung 1343: switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
1344: case IFF_RUNNING:
1.66 thorpej 1345: /*
1346: * If interface is marked down and it is running,
1347: * then stop and disable it.
1348: */
1349: (*ifp->if_stop)(ifp, 1);
1.169 dyoung 1350: break;
1351: case IFF_UP:
1.66 thorpej 1352: /*
1353: * If interface is marked up and it is stopped, then
1354: * start it.
1355: */
1.169 dyoung 1356: return (*ifp->if_init)(ifp);
1357: case IFF_UP|IFF_RUNNING:
1.170 dyoung 1358: error = 0;
1359: if (ec->ec_ifflags_cb == NULL ||
1360: (error = (*ec->ec_ifflags_cb)(ec)) == ENETRESET) {
1361: /*
1362: * Reset the interface to pick up
1363: * changes in any other flags that
1364: * affect the hardware state.
1365: */
1366: return (*ifp->if_init)(ifp);
1367: } else
1368: return error;
1.169 dyoung 1369: case 0:
1370: break;
1.66 thorpej 1371: }
1.169 dyoung 1372: return 0;
1.193 msaitoh 1373: case SIOCGETHERCAP:
1374: eccr = (struct eccapreq *)data;
1375: eccr->eccr_capabilities = ec->ec_capabilities;
1376: eccr->eccr_capenable = ec->ec_capenable;
1377: return 0;
1.66 thorpej 1378: case SIOCADDMULTI:
1.169 dyoung 1379: return ether_addmulti(ifreq_getaddr(cmd, ifr), ec);
1.66 thorpej 1380: case SIOCDELMULTI:
1.169 dyoung 1381: return ether_delmulti(ifreq_getaddr(cmd, ifr), ec);
1.160 dyoung 1382: case SIOCSIFMEDIA:
1383: case SIOCGIFMEDIA:
1384: if (ec->ec_mii == NULL)
1.169 dyoung 1385: return ENOTTY;
1386: return ifmedia_ioctl(ifp, ifr, &ec->ec_mii->mii_media, cmd);
1.170 dyoung 1387: case SIOCALIFADDR:
1388: sdl = satocsdl(sstocsa(&iflr->addr));
1389: if (sdl->sdl_family != AF_LINK)
1390: ;
1391: else if (ETHER_IS_MULTICAST(CLLADDR(sdl)))
1392: return EINVAL;
1393: else if (memcmp(zero, CLLADDR(sdl), sizeof(zero)) == 0)
1394: return EINVAL;
1395: /*FALLTHROUGH*/
1396: default:
1.161 dyoung 1397: return ifioctl_common(ifp, cmd, data);
1.66 thorpej 1398: }
1.169 dyoung 1399: return 0;
1.3 hpeyerl 1400: }
1.200 joerg 1401:
1.215 christos 1402: /*
1403: * Enable/disable passing VLAN packets if the parent interface supports it.
1404: * Return:
1405: * 0: Ok
1406: * -1: Parent interface does not support vlans
1407: * >0: Error
1408: */
1409: int
1410: ether_enable_vlan_mtu(struct ifnet *ifp)
1411: {
1412: int error;
1413: struct ethercom *ec = (void *)ifp;
1414:
1415: /* Already have VLAN's do nothing. */
1416: if (ec->ec_nvlans != 0)
1417: return 0;
1418:
1419: /* Parent does not support VLAN's */
1420: if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0)
1421: return -1;
1422:
1423: /*
1424: * Parent supports the VLAN_MTU capability,
1425: * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames;
1426: * enable it.
1427: */
1428: ec->ec_capenable |= ETHERCAP_VLAN_MTU;
1429:
1430: /* Interface is down, defer for later */
1431: if ((ifp->if_flags & IFF_UP) == 0)
1432: return 0;
1433:
1434: if ((error = if_flags_set(ifp, ifp->if_flags)) == 0)
1435: return 0;
1436:
1437: ec->ec_capenable &= ~ETHERCAP_VLAN_MTU;
1438: return error;
1439: }
1440:
1441: int
1442: ether_disable_vlan_mtu(struct ifnet *ifp)
1443: {
1444: int error;
1445: struct ethercom *ec = (void *)ifp;
1446:
1447: /* We still have VLAN's, defer for later */
1448: if (ec->ec_nvlans != 0)
1449: return 0;
1450:
1451: /* Parent does not support VLAB's, nothing to do. */
1452: if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0)
1453: return -1;
1454:
1455: /*
1456: * Disable Tx/Rx of VLAN-sized frames.
1457: */
1458: ec->ec_capenable &= ~ETHERCAP_VLAN_MTU;
1459:
1460: /* Interface is down, defer for later */
1461: if ((ifp->if_flags & IFF_UP) == 0)
1462: return 0;
1463:
1464: if ((error = if_flags_set(ifp, ifp->if_flags)) == 0)
1465: return 0;
1466:
1467: ec->ec_capenable |= ETHERCAP_VLAN_MTU;
1468: return error;
1469: }
1470:
1.200 joerg 1471: static int
1472: ether_multicast_sysctl(SYSCTLFN_ARGS)
1473: {
1474: struct ether_multi *enm;
1475: struct ether_multi_sysctl addr;
1476: struct ifnet *ifp;
1477: struct ethercom *ec;
1.223 ! ozaki-r 1478: int error = 0;
1.200 joerg 1479: size_t written;
1.223 ! ozaki-r 1480: struct psref psref;
! 1481: int bound;
1.200 joerg 1482:
1483: if (namelen != 1)
1484: return EINVAL;
1485:
1.223 ! ozaki-r 1486: bound = curlwp_bind();
! 1487: ifp = if_get_byindex(name[0], &psref);
! 1488: if (ifp == NULL) {
! 1489: error = ENODEV;
! 1490: goto out;
! 1491: }
1.200 joerg 1492: if (ifp->if_type != IFT_ETHER) {
1.223 ! ozaki-r 1493: if_put(ifp, &psref);
1.200 joerg 1494: *oldlenp = 0;
1.223 ! ozaki-r 1495: goto out;
1.200 joerg 1496: }
1497: ec = (struct ethercom *)ifp;
1498:
1499: if (oldp == NULL) {
1.223 ! ozaki-r 1500: if_put(ifp, &psref);
1.200 joerg 1501: *oldlenp = ec->ec_multicnt * sizeof(addr);
1.223 ! ozaki-r 1502: goto out;
1.200 joerg 1503: }
1504:
1505: memset(&addr, 0, sizeof(addr));
1506: error = 0;
1507: written = 0;
1508:
1509: LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) {
1510: if (written + sizeof(addr) > *oldlenp)
1511: break;
1512: addr.enm_refcount = enm->enm_refcount;
1513: memcpy(addr.enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
1514: memcpy(addr.enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
1515: error = sysctl_copyout(l, &addr, oldp, sizeof(addr));
1516: if (error)
1517: break;
1518: written += sizeof(addr);
1519: oldp = (char *)oldp + sizeof(addr);
1520: }
1.223 ! ozaki-r 1521: if_put(ifp, &psref);
1.200 joerg 1522:
1523: *oldlenp = written;
1.223 ! ozaki-r 1524: out:
! 1525: curlwp_bindx(bound);
1.200 joerg 1526: return error;
1527: }
1528:
1529: SYSCTL_SETUP(sysctl_net_ether_setup, "sysctl net.ether subtree setup")
1530: {
1531: const struct sysctlnode *rnode = NULL;
1532:
1533: sysctl_createv(clog, 0, NULL, &rnode,
1534: CTLFLAG_PERMANENT,
1535: CTLTYPE_NODE, "ether",
1536: SYSCTL_DESCR("Ethernet-specific information"),
1537: NULL, 0, NULL, 0,
1538: CTL_NET, CTL_CREATE, CTL_EOL);
1539:
1540: sysctl_createv(clog, 0, &rnode, NULL,
1541: CTLFLAG_PERMANENT,
1542: CTLTYPE_NODE, "multicast",
1543: SYSCTL_DESCR("multicast addresses"),
1544: ether_multicast_sysctl, 0, NULL, 0,
1545: CTL_CREATE, CTL_EOL);
1546: }
1.203 ozaki-r 1547:
1548: void
1549: etherinit(void)
1550: {
1551: mutex_init(&bigpktpps_lock, MUTEX_DEFAULT, IPL_NET);
1552: }
CVSweb <webmaster@jp.NetBSD.org>