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