Home | History | Annotate | Line # | Download | only in net
if_ethersubr.c revision 1.1.1.2
      1      1.1   cgd /*
      2  1.1.1.2  fvdl  * Copyright (c) 1982, 1989, 1993
      3  1.1.1.2  fvdl  *	The Regents of the University of California.  All rights reserved.
      4      1.1   cgd  *
      5      1.1   cgd  * Redistribution and use in source and binary forms, with or without
      6      1.1   cgd  * modification, are permitted provided that the following conditions
      7      1.1   cgd  * are met:
      8      1.1   cgd  * 1. Redistributions of source code must retain the above copyright
      9      1.1   cgd  *    notice, this list of conditions and the following disclaimer.
     10      1.1   cgd  * 2. Redistributions in binary form must reproduce the above copyright
     11      1.1   cgd  *    notice, this list of conditions and the following disclaimer in the
     12      1.1   cgd  *    documentation and/or other materials provided with the distribution.
     13      1.1   cgd  * 3. All advertising materials mentioning features or use of this software
     14      1.1   cgd  *    must display the following acknowledgement:
     15      1.1   cgd  *	This product includes software developed by the University of
     16      1.1   cgd  *	California, Berkeley and its contributors.
     17      1.1   cgd  * 4. Neither the name of the University nor the names of its contributors
     18      1.1   cgd  *    may be used to endorse or promote products derived from this software
     19      1.1   cgd  *    without specific prior written permission.
     20      1.1   cgd  *
     21      1.1   cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22      1.1   cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23      1.1   cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24      1.1   cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25      1.1   cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26      1.1   cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27      1.1   cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28      1.1   cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29      1.1   cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30      1.1   cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31      1.1   cgd  * SUCH DAMAGE.
     32      1.1   cgd  *
     33  1.1.1.2  fvdl  *	@(#)if_ethersubr.c	8.1 (Berkeley) 6/10/93
     34      1.1   cgd  */
     35      1.1   cgd 
     36  1.1.1.2  fvdl #include <sys/param.h>
     37  1.1.1.2  fvdl #include <sys/systm.h>
     38  1.1.1.2  fvdl #include <sys/kernel.h>
     39  1.1.1.2  fvdl #include <sys/malloc.h>
     40  1.1.1.2  fvdl #include <sys/mbuf.h>
     41  1.1.1.2  fvdl #include <sys/protosw.h>
     42  1.1.1.2  fvdl #include <sys/socket.h>
     43  1.1.1.2  fvdl #include <sys/ioctl.h>
     44  1.1.1.2  fvdl #include <sys/errno.h>
     45  1.1.1.2  fvdl #include <sys/syslog.h>
     46  1.1.1.2  fvdl 
     47  1.1.1.2  fvdl #include <machine/cpu.h>
     48  1.1.1.2  fvdl 
     49  1.1.1.2  fvdl #include <net/if.h>
     50  1.1.1.2  fvdl #include <net/netisr.h>
     51  1.1.1.2  fvdl #include <net/route.h>
     52  1.1.1.2  fvdl #include <net/if_llc.h>
     53  1.1.1.2  fvdl #include <net/if_dl.h>
     54  1.1.1.2  fvdl #include <net/if_types.h>
     55      1.1   cgd 
     56      1.1   cgd #ifdef INET
     57  1.1.1.2  fvdl #include <netinet/in.h>
     58  1.1.1.2  fvdl #include <netinet/in_var.h>
     59      1.1   cgd #endif
     60  1.1.1.2  fvdl #include <netinet/if_ether.h>
     61      1.1   cgd 
     62      1.1   cgd #ifdef NS
     63  1.1.1.2  fvdl #include <netns/ns.h>
     64  1.1.1.2  fvdl #include <netns/ns_if.h>
     65      1.1   cgd #endif
     66      1.1   cgd 
     67      1.1   cgd #ifdef ISO
     68  1.1.1.2  fvdl #include <netiso/argo_debug.h>
     69  1.1.1.2  fvdl #include <netiso/iso.h>
     70  1.1.1.2  fvdl #include <netiso/iso_var.h>
     71  1.1.1.2  fvdl #include <netiso/iso_snpac.h>
     72  1.1.1.2  fvdl #endif
     73  1.1.1.2  fvdl 
     74  1.1.1.2  fvdl #ifdef LLC
     75  1.1.1.2  fvdl #include <netccitt/dll.h>
     76  1.1.1.2  fvdl #include <netccitt/llc_var.h>
     77  1.1.1.2  fvdl #endif
     78  1.1.1.2  fvdl 
     79  1.1.1.2  fvdl #if defined(LLC) && defined(CCITT)
     80  1.1.1.2  fvdl extern struct ifqueue pkintrq;
     81      1.1   cgd #endif
     82      1.1   cgd 
     83      1.1   cgd u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     84      1.1   cgd extern	struct ifnet loif;
     85  1.1.1.2  fvdl #define senderr(e) { error = (e); goto bad;}
     86      1.1   cgd 
     87      1.1   cgd /*
     88      1.1   cgd  * Ethernet output routine.
     89      1.1   cgd  * Encapsulate a packet of type family for the local net.
     90      1.1   cgd  * Use trailer local net encapsulation if enough data in first
     91      1.1   cgd  * packet leaves a multiple of 512 bytes of data in remainder.
     92      1.1   cgd  * Assumes that ifp is actually pointer to arpcom structure.
     93      1.1   cgd  */
     94  1.1.1.2  fvdl int
     95  1.1.1.2  fvdl ether_output(ifp, m0, dst, rt0)
     96      1.1   cgd 	register struct ifnet *ifp;
     97      1.1   cgd 	struct mbuf *m0;
     98      1.1   cgd 	struct sockaddr *dst;
     99  1.1.1.2  fvdl 	struct rtentry *rt0;
    100      1.1   cgd {
    101      1.1   cgd 	short type;
    102      1.1   cgd 	int s, error = 0;
    103      1.1   cgd  	u_char edst[6];
    104      1.1   cgd 	register struct mbuf *m = m0;
    105  1.1.1.2  fvdl 	register struct rtentry *rt;
    106      1.1   cgd 	struct mbuf *mcopy = (struct mbuf *)0;
    107      1.1   cgd 	register struct ether_header *eh;
    108  1.1.1.2  fvdl 	int off, len = m->m_pkthdr.len;
    109  1.1.1.2  fvdl 	struct arpcom *ac = (struct arpcom *)ifp;
    110      1.1   cgd 
    111  1.1.1.2  fvdl 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
    112  1.1.1.2  fvdl 		senderr(ENETDOWN);
    113      1.1   cgd 	ifp->if_lastchange = time;
    114  1.1.1.2  fvdl 	if (rt = rt0) {
    115  1.1.1.2  fvdl 		if ((rt->rt_flags & RTF_UP) == 0) {
    116  1.1.1.2  fvdl 			if (rt0 = rt = rtalloc1(dst, 1))
    117  1.1.1.2  fvdl 				rt->rt_refcnt--;
    118  1.1.1.2  fvdl 			else
    119  1.1.1.2  fvdl 				senderr(EHOSTUNREACH);
    120  1.1.1.2  fvdl 		}
    121  1.1.1.2  fvdl 		if (rt->rt_flags & RTF_GATEWAY) {
    122  1.1.1.2  fvdl 			if (rt->rt_gwroute == 0)
    123  1.1.1.2  fvdl 				goto lookup;
    124  1.1.1.2  fvdl 			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
    125  1.1.1.2  fvdl 				rtfree(rt); rt = rt0;
    126  1.1.1.2  fvdl 			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
    127  1.1.1.2  fvdl 				if ((rt = rt->rt_gwroute) == 0)
    128  1.1.1.2  fvdl 					senderr(EHOSTUNREACH);
    129  1.1.1.2  fvdl 			}
    130  1.1.1.2  fvdl 		}
    131  1.1.1.2  fvdl 		if (rt->rt_flags & RTF_REJECT)
    132  1.1.1.2  fvdl 			if (rt->rt_rmx.rmx_expire == 0 ||
    133  1.1.1.2  fvdl 			    time.tv_sec < rt->rt_rmx.rmx_expire)
    134  1.1.1.2  fvdl 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
    135  1.1.1.2  fvdl 	}
    136      1.1   cgd 	switch (dst->sa_family) {
    137      1.1   cgd 
    138      1.1   cgd #ifdef INET
    139      1.1   cgd 	case AF_INET:
    140  1.1.1.2  fvdl 		if (!arpresolve(ac, rt, m, dst, edst))
    141      1.1   cgd 			return (0);	/* if not yet resolved */
    142  1.1.1.2  fvdl 		/* If broadcasting on a simplex interface, loopback a copy */
    143  1.1.1.2  fvdl 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
    144      1.1   cgd 			mcopy = m_copy(m, 0, (int)M_COPYALL);
    145      1.1   cgd 		off = m->m_pkthdr.len - m->m_len;
    146      1.1   cgd 		type = ETHERTYPE_IP;
    147  1.1.1.2  fvdl 		break;
    148      1.1   cgd #endif
    149      1.1   cgd #ifdef NS
    150      1.1   cgd 	case AF_NS:
    151      1.1   cgd 		type = ETHERTYPE_NS;
    152      1.1   cgd  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
    153      1.1   cgd 		    (caddr_t)edst, sizeof (edst));
    154      1.1   cgd 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
    155      1.1   cgd 			return (looutput(ifp, m, dst, rt));
    156  1.1.1.2  fvdl 		/* If broadcasting on a simplex interface, loopback a copy */
    157  1.1.1.2  fvdl 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
    158      1.1   cgd 			mcopy = m_copy(m, 0, (int)M_COPYALL);
    159  1.1.1.2  fvdl 		break;
    160      1.1   cgd #endif
    161      1.1   cgd #ifdef	ISO
    162      1.1   cgd 	case AF_ISO: {
    163      1.1   cgd 		int	snpalen;
    164      1.1   cgd 		struct	llc *l;
    165  1.1.1.2  fvdl 		register struct sockaddr_dl *sdl;
    166      1.1   cgd 
    167  1.1.1.2  fvdl 		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
    168  1.1.1.2  fvdl 		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
    169  1.1.1.2  fvdl 			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
    170  1.1.1.2  fvdl 		} else if (error =
    171  1.1.1.2  fvdl 			    iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
    172  1.1.1.2  fvdl 					    (char *)edst, &snpalen))
    173      1.1   cgd 			goto bad; /* Not Resolved */
    174  1.1.1.2  fvdl 		/* If broadcasting on a simplex interface, loopback a copy */
    175  1.1.1.2  fvdl 		if (*edst & 1)
    176  1.1.1.2  fvdl 			m->m_flags |= (M_BCAST|M_MCAST);
    177  1.1.1.2  fvdl 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
    178      1.1   cgd 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
    179      1.1   cgd 			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
    180      1.1   cgd 			if (mcopy) {
    181      1.1   cgd 				eh = mtod(mcopy, struct ether_header *);
    182      1.1   cgd 				bcopy((caddr_t)edst,
    183      1.1   cgd 				      (caddr_t)eh->ether_dhost, sizeof (edst));
    184      1.1   cgd 				bcopy((caddr_t)ac->ac_enaddr,
    185      1.1   cgd 				      (caddr_t)eh->ether_shost, sizeof (edst));
    186      1.1   cgd 			}
    187      1.1   cgd 		}
    188      1.1   cgd 		M_PREPEND(m, 3, M_DONTWAIT);
    189      1.1   cgd 		if (m == NULL)
    190      1.1   cgd 			return (0);
    191      1.1   cgd 		type = m->m_pkthdr.len;
    192      1.1   cgd 		l = mtod(m, struct llc *);
    193      1.1   cgd 		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
    194      1.1   cgd 		l->llc_control = LLC_UI;
    195      1.1   cgd 		len += 3;
    196      1.1   cgd 		IFDEBUG(D_ETHER)
    197      1.1   cgd 			int i;
    198      1.1   cgd 			printf("unoutput: sending pkt to: ");
    199      1.1   cgd 			for (i=0; i<6; i++)
    200      1.1   cgd 				printf("%x ", edst[i] & 0xff);
    201      1.1   cgd 			printf("\n");
    202      1.1   cgd 		ENDDEBUG
    203  1.1.1.2  fvdl 		} break;
    204  1.1.1.2  fvdl #endif /* ISO */
    205  1.1.1.2  fvdl #ifdef	LLC
    206  1.1.1.2  fvdl /*	case AF_NSAP: */
    207  1.1.1.2  fvdl 	case AF_CCITT: {
    208  1.1.1.2  fvdl 		register struct sockaddr_dl *sdl =
    209  1.1.1.2  fvdl 			(struct sockaddr_dl *) rt -> rt_gateway;
    210  1.1.1.2  fvdl 
    211  1.1.1.2  fvdl 		if (sdl && sdl->sdl_family == AF_LINK
    212  1.1.1.2  fvdl 		    && sdl->sdl_alen > 0) {
    213  1.1.1.2  fvdl 			bcopy(LLADDR(sdl), (char *)edst,
    214  1.1.1.2  fvdl 				sizeof(edst));
    215  1.1.1.2  fvdl 		} else goto bad; /* Not a link interface ? Funny ... */
    216  1.1.1.2  fvdl 		if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
    217  1.1.1.2  fvdl 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
    218  1.1.1.2  fvdl 			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
    219  1.1.1.2  fvdl 			if (mcopy) {
    220  1.1.1.2  fvdl 				eh = mtod(mcopy, struct ether_header *);
    221  1.1.1.2  fvdl 				bcopy((caddr_t)edst,
    222  1.1.1.2  fvdl 				      (caddr_t)eh->ether_dhost, sizeof (edst));
    223  1.1.1.2  fvdl 				bcopy((caddr_t)ac->ac_enaddr,
    224  1.1.1.2  fvdl 				      (caddr_t)eh->ether_shost, sizeof (edst));
    225  1.1.1.2  fvdl 			}
    226  1.1.1.2  fvdl 		}
    227  1.1.1.2  fvdl 		type = m->m_pkthdr.len;
    228  1.1.1.2  fvdl #ifdef LLC_DEBUG
    229  1.1.1.2  fvdl 		{
    230  1.1.1.2  fvdl 			int i;
    231  1.1.1.2  fvdl 			register struct llc *l = mtod(m, struct llc *);
    232  1.1.1.2  fvdl 
    233  1.1.1.2  fvdl 			printf("ether_output: sending LLC2 pkt to: ");
    234  1.1.1.2  fvdl 			for (i=0; i<6; i++)
    235  1.1.1.2  fvdl 				printf("%x ", edst[i] & 0xff);
    236  1.1.1.2  fvdl 			printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
    237  1.1.1.2  fvdl 			       type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
    238  1.1.1.2  fvdl 			       l->llc_control & 0xff);
    239  1.1.1.2  fvdl 
    240  1.1.1.2  fvdl 		}
    241  1.1.1.2  fvdl #endif /* LLC_DEBUG */
    242  1.1.1.2  fvdl 		} break;
    243  1.1.1.2  fvdl #endif /* LLC */
    244      1.1   cgd 
    245      1.1   cgd 	case AF_UNSPEC:
    246      1.1   cgd 		eh = (struct ether_header *)dst->sa_data;
    247      1.1   cgd  		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
    248      1.1   cgd 		type = eh->ether_type;
    249  1.1.1.2  fvdl 		break;
    250      1.1   cgd 
    251      1.1   cgd 	default:
    252      1.1   cgd 		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
    253      1.1   cgd 			dst->sa_family);
    254  1.1.1.2  fvdl 		senderr(EAFNOSUPPORT);
    255      1.1   cgd 	}
    256      1.1   cgd 
    257      1.1   cgd 
    258      1.1   cgd 	if (mcopy)
    259      1.1   cgd 		(void) looutput(ifp, mcopy, dst, rt);
    260      1.1   cgd 	/*
    261      1.1   cgd 	 * Add local net header.  If no space in first mbuf,
    262      1.1   cgd 	 * allocate another.
    263      1.1   cgd 	 */
    264      1.1   cgd 	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
    265  1.1.1.2  fvdl 	if (m == 0)
    266  1.1.1.2  fvdl 		senderr(ENOBUFS);
    267      1.1   cgd 	eh = mtod(m, struct ether_header *);
    268      1.1   cgd 	type = htons((u_short)type);
    269      1.1   cgd 	bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
    270      1.1   cgd 		sizeof(eh->ether_type));
    271      1.1   cgd  	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
    272      1.1   cgd  	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
    273      1.1   cgd 	    sizeof(eh->ether_shost));
    274      1.1   cgd 	s = splimp();
    275      1.1   cgd 	/*
    276      1.1   cgd 	 * Queue message on interface, and start output if interface
    277      1.1   cgd 	 * not yet active.
    278      1.1   cgd 	 */
    279      1.1   cgd 	if (IF_QFULL(&ifp->if_snd)) {
    280      1.1   cgd 		IF_DROP(&ifp->if_snd);
    281      1.1   cgd 		splx(s);
    282  1.1.1.2  fvdl 		senderr(ENOBUFS);
    283      1.1   cgd 	}
    284      1.1   cgd 	IF_ENQUEUE(&ifp->if_snd, m);
    285      1.1   cgd 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
    286      1.1   cgd 		(*ifp->if_start)(ifp);
    287      1.1   cgd 	splx(s);
    288      1.1   cgd 	ifp->if_obytes += len + sizeof (struct ether_header);
    289  1.1.1.2  fvdl 	if (m->m_flags & M_MCAST)
    290      1.1   cgd 		ifp->if_omcasts++;
    291      1.1   cgd 	return (error);
    292      1.1   cgd 
    293      1.1   cgd bad:
    294      1.1   cgd 	if (m)
    295      1.1   cgd 		m_freem(m);
    296      1.1   cgd 	return (error);
    297      1.1   cgd }
    298      1.1   cgd 
    299      1.1   cgd /*
    300      1.1   cgd  * Process a received Ethernet packet;
    301      1.1   cgd  * the packet is in the mbuf chain m without
    302      1.1   cgd  * the ether header, which is provided separately.
    303      1.1   cgd  */
    304  1.1.1.2  fvdl void
    305      1.1   cgd ether_input(ifp, eh, m)
    306      1.1   cgd 	struct ifnet *ifp;
    307      1.1   cgd 	register struct ether_header *eh;
    308      1.1   cgd 	struct mbuf *m;
    309      1.1   cgd {
    310      1.1   cgd 	register struct ifqueue *inq;
    311      1.1   cgd 	register struct llc *l;
    312  1.1.1.2  fvdl 	struct arpcom *ac = (struct arpcom *)ifp;
    313      1.1   cgd 	int s;
    314      1.1   cgd 
    315  1.1.1.2  fvdl 	if ((ifp->if_flags & IFF_UP) == 0) {
    316  1.1.1.2  fvdl 		m_freem(m);
    317  1.1.1.2  fvdl 		return;
    318  1.1.1.2  fvdl 	}
    319      1.1   cgd 	ifp->if_lastchange = time;
    320      1.1   cgd 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
    321      1.1   cgd 	if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
    322      1.1   cgd 	    sizeof(etherbroadcastaddr)) == 0)
    323      1.1   cgd 		m->m_flags |= M_BCAST;
    324      1.1   cgd 	else if (eh->ether_dhost[0] & 1)
    325      1.1   cgd 		m->m_flags |= M_MCAST;
    326      1.1   cgd 	if (m->m_flags & (M_BCAST|M_MCAST))
    327      1.1   cgd 		ifp->if_imcasts++;
    328      1.1   cgd 
    329      1.1   cgd 	switch (eh->ether_type) {
    330      1.1   cgd #ifdef INET
    331      1.1   cgd 	case ETHERTYPE_IP:
    332      1.1   cgd 		schednetisr(NETISR_IP);
    333      1.1   cgd 		inq = &ipintrq;
    334      1.1   cgd 		break;
    335      1.1   cgd 
    336      1.1   cgd 	case ETHERTYPE_ARP:
    337  1.1.1.2  fvdl 		schednetisr(NETISR_ARP);
    338  1.1.1.2  fvdl 		inq = &arpintrq;
    339  1.1.1.2  fvdl 		break;
    340      1.1   cgd #endif
    341      1.1   cgd #ifdef NS
    342      1.1   cgd 	case ETHERTYPE_NS:
    343      1.1   cgd 		schednetisr(NETISR_NS);
    344      1.1   cgd 		inq = &nsintrq;
    345      1.1   cgd 		break;
    346      1.1   cgd 
    347      1.1   cgd #endif
    348      1.1   cgd 	default:
    349  1.1.1.2  fvdl #if defined (ISO) || defined (LLC)
    350      1.1   cgd 		if (eh->ether_type > ETHERMTU)
    351      1.1   cgd 			goto dropanyway;
    352      1.1   cgd 		l = mtod(m, struct llc *);
    353  1.1.1.2  fvdl 		switch (l->llc_dsap) {
    354  1.1.1.2  fvdl #ifdef	ISO
    355  1.1.1.2  fvdl 		case LLC_ISO_LSAP:
    356  1.1.1.2  fvdl 			switch (l->llc_control) {
    357  1.1.1.2  fvdl 			case LLC_UI:
    358  1.1.1.2  fvdl 				/* LLC_UI_P forbidden in class 1 service */
    359  1.1.1.2  fvdl 				if ((l->llc_dsap == LLC_ISO_LSAP) &&
    360  1.1.1.2  fvdl 				    (l->llc_ssap == LLC_ISO_LSAP)) {
    361  1.1.1.2  fvdl 					/* LSAP for ISO */
    362  1.1.1.2  fvdl 					if (m->m_pkthdr.len > eh->ether_type)
    363  1.1.1.2  fvdl 						m_adj(m, eh->ether_type - m->m_pkthdr.len);
    364  1.1.1.2  fvdl 					m->m_data += 3;		/* XXX */
    365  1.1.1.2  fvdl 					m->m_len -= 3;		/* XXX */
    366  1.1.1.2  fvdl 					m->m_pkthdr.len -= 3;	/* XXX */
    367  1.1.1.2  fvdl 					M_PREPEND(m, sizeof *eh, M_DONTWAIT);
    368  1.1.1.2  fvdl 					if (m == 0)
    369  1.1.1.2  fvdl 						return;
    370  1.1.1.2  fvdl 					*mtod(m, struct ether_header *) = *eh;
    371  1.1.1.2  fvdl 					IFDEBUG(D_ETHER)
    372  1.1.1.2  fvdl 						printf("clnp packet");
    373  1.1.1.2  fvdl 					ENDDEBUG
    374  1.1.1.2  fvdl 					schednetisr(NETISR_ISO);
    375  1.1.1.2  fvdl 					inq = &clnlintrq;
    376  1.1.1.2  fvdl 					break;
    377  1.1.1.2  fvdl 				}
    378  1.1.1.2  fvdl 				goto dropanyway;
    379  1.1.1.2  fvdl 
    380  1.1.1.2  fvdl 			case LLC_XID:
    381  1.1.1.2  fvdl 			case LLC_XID_P:
    382  1.1.1.2  fvdl 				if(m->m_len < 6)
    383  1.1.1.2  fvdl 					goto dropanyway;
    384  1.1.1.2  fvdl 				l->llc_window = 0;
    385  1.1.1.2  fvdl 				l->llc_fid = 9;
    386  1.1.1.2  fvdl 				l->llc_class = 1;
    387  1.1.1.2  fvdl 				l->llc_dsap = l->llc_ssap = 0;
    388  1.1.1.2  fvdl 				/* Fall through to */
    389  1.1.1.2  fvdl 			case LLC_TEST:
    390  1.1.1.2  fvdl 			case LLC_TEST_P:
    391  1.1.1.2  fvdl 			{
    392  1.1.1.2  fvdl 				struct sockaddr sa;
    393  1.1.1.2  fvdl 				register struct ether_header *eh2;
    394  1.1.1.2  fvdl 				int i;
    395  1.1.1.2  fvdl 				u_char c = l->llc_dsap;
    396  1.1.1.2  fvdl 
    397  1.1.1.2  fvdl 				l->llc_dsap = l->llc_ssap;
    398  1.1.1.2  fvdl 				l->llc_ssap = c;
    399  1.1.1.2  fvdl 				if (m->m_flags & (M_BCAST | M_MCAST))
    400  1.1.1.2  fvdl 					bcopy((caddr_t)ac->ac_enaddr,
    401  1.1.1.2  fvdl 					      (caddr_t)eh->ether_dhost, 6);
    402  1.1.1.2  fvdl 				sa.sa_family = AF_UNSPEC;
    403  1.1.1.2  fvdl 				sa.sa_len = sizeof(sa);
    404  1.1.1.2  fvdl 				eh2 = (struct ether_header *)sa.sa_data;
    405  1.1.1.2  fvdl 				for (i = 0; i < 6; i++) {
    406  1.1.1.2  fvdl 					eh2->ether_shost[i] = c = eh->ether_dhost[i];
    407  1.1.1.2  fvdl 					eh2->ether_dhost[i] =
    408  1.1.1.2  fvdl 						eh->ether_dhost[i] = eh->ether_shost[i];
    409  1.1.1.2  fvdl 					eh->ether_shost[i] = c;
    410  1.1.1.2  fvdl 				}
    411  1.1.1.2  fvdl 				ifp->if_output(ifp, m, &sa, NULL);
    412  1.1.1.2  fvdl 				return;
    413  1.1.1.2  fvdl 			}
    414  1.1.1.2  fvdl 			default:
    415  1.1.1.2  fvdl 				m_freem(m);
    416  1.1.1.2  fvdl 				return;
    417  1.1.1.2  fvdl 			}
    418  1.1.1.2  fvdl 			break;
    419  1.1.1.2  fvdl #endif /* ISO */
    420  1.1.1.2  fvdl #ifdef LLC
    421  1.1.1.2  fvdl 		case LLC_X25_LSAP:
    422  1.1.1.2  fvdl 		{
    423      1.1   cgd 			if (m->m_pkthdr.len > eh->ether_type)
    424      1.1   cgd 				m_adj(m, eh->ether_type - m->m_pkthdr.len);
    425  1.1.1.2  fvdl 			M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
    426      1.1   cgd 			if (m == 0)
    427      1.1   cgd 				return;
    428  1.1.1.2  fvdl 			if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
    429  1.1.1.2  fvdl 					    eh->ether_dhost, LLC_X25_LSAP, 6,
    430  1.1.1.2  fvdl 					    mtod(m, struct sdl_hdr *)))
    431  1.1.1.2  fvdl 				panic("ETHER cons addr failure");
    432  1.1.1.2  fvdl 			mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type;
    433  1.1.1.2  fvdl #ifdef LLC_DEBUG
    434  1.1.1.2  fvdl 				printf("llc packet\n");
    435  1.1.1.2  fvdl #endif /* LLC_DEBUG */
    436  1.1.1.2  fvdl 			schednetisr(NETISR_CCITT);
    437  1.1.1.2  fvdl 			inq = &llcintrq;
    438      1.1   cgd 			break;
    439      1.1   cgd 		}
    440  1.1.1.2  fvdl #endif /* LLC */
    441      1.1   cgd 		dropanyway:
    442      1.1   cgd 		default:
    443  1.1.1.2  fvdl 			m_freem(m);
    444  1.1.1.2  fvdl 			return;
    445  1.1.1.2  fvdl 		}
    446  1.1.1.2  fvdl #else /* ISO || LLC */
    447      1.1   cgd 	    m_freem(m);
    448      1.1   cgd 	    return;
    449  1.1.1.2  fvdl #endif /* ISO || LLC */
    450      1.1   cgd 	}
    451      1.1   cgd 
    452      1.1   cgd 	s = splimp();
    453      1.1   cgd 	if (IF_QFULL(inq)) {
    454      1.1   cgd 		IF_DROP(inq);
    455      1.1   cgd 		m_freem(m);
    456      1.1   cgd 	} else
    457      1.1   cgd 		IF_ENQUEUE(inq, m);
    458      1.1   cgd 	splx(s);
    459      1.1   cgd }
    460      1.1   cgd 
    461      1.1   cgd /*
    462      1.1   cgd  * Convert Ethernet address to printable (loggable) representation.
    463      1.1   cgd  */
    464      1.1   cgd static char digits[] = "0123456789abcdef";
    465      1.1   cgd char *
    466      1.1   cgd ether_sprintf(ap)
    467      1.1   cgd 	register u_char *ap;
    468      1.1   cgd {
    469      1.1   cgd 	register i;
    470      1.1   cgd 	static char etherbuf[18];
    471      1.1   cgd 	register char *cp = etherbuf;
    472      1.1   cgd 
    473      1.1   cgd 	for (i = 0; i < 6; i++) {
    474      1.1   cgd 		*cp++ = digits[*ap >> 4];
    475      1.1   cgd 		*cp++ = digits[*ap++ & 0xf];
    476      1.1   cgd 		*cp++ = ':';
    477      1.1   cgd 	}
    478      1.1   cgd 	*--cp = 0;
    479      1.1   cgd 	return (etherbuf);
    480  1.1.1.2  fvdl }
    481  1.1.1.2  fvdl 
    482  1.1.1.2  fvdl /*
    483  1.1.1.2  fvdl  * Perform common duties while attaching to interface list
    484  1.1.1.2  fvdl  */
    485  1.1.1.2  fvdl void
    486  1.1.1.2  fvdl ether_ifattach(ifp)
    487  1.1.1.2  fvdl 	register struct ifnet *ifp;
    488  1.1.1.2  fvdl {
    489  1.1.1.2  fvdl 	register struct ifaddr *ifa;
    490  1.1.1.2  fvdl 	register struct sockaddr_dl *sdl;
    491  1.1.1.2  fvdl 
    492  1.1.1.2  fvdl 	ifp->if_type = IFT_ETHER;
    493  1.1.1.2  fvdl 	ifp->if_addrlen = 6;
    494  1.1.1.2  fvdl 	ifp->if_hdrlen = 14;
    495  1.1.1.2  fvdl 	ifp->if_mtu = ETHERMTU;
    496  1.1.1.2  fvdl 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
    497  1.1.1.2  fvdl 		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
    498  1.1.1.2  fvdl 		    sdl->sdl_family == AF_LINK) {
    499  1.1.1.2  fvdl 			sdl->sdl_type = IFT_ETHER;
    500  1.1.1.2  fvdl 			sdl->sdl_alen = ifp->if_addrlen;
    501  1.1.1.2  fvdl 			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
    502  1.1.1.2  fvdl 			      LLADDR(sdl), ifp->if_addrlen);
    503  1.1.1.2  fvdl 			break;
    504  1.1.1.2  fvdl 		}
    505  1.1.1.2  fvdl }
    506  1.1.1.2  fvdl 
    507  1.1.1.2  fvdl u_char	ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
    508  1.1.1.2  fvdl u_char	ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
    509  1.1.1.2  fvdl /*
    510  1.1.1.2  fvdl  * Add an Ethernet multicast address or range of addresses to the list for a
    511  1.1.1.2  fvdl  * given interface.
    512  1.1.1.2  fvdl  */
    513  1.1.1.2  fvdl int
    514  1.1.1.2  fvdl ether_addmulti(ifr, ac)
    515  1.1.1.2  fvdl 	struct ifreq *ifr;
    516  1.1.1.2  fvdl 	register struct arpcom *ac;
    517  1.1.1.2  fvdl {
    518  1.1.1.2  fvdl 	register struct ether_multi *enm;
    519  1.1.1.2  fvdl 	struct sockaddr_in *sin;
    520  1.1.1.2  fvdl 	u_char addrlo[6];
    521  1.1.1.2  fvdl 	u_char addrhi[6];
    522  1.1.1.2  fvdl 	int s = splimp();
    523  1.1.1.2  fvdl 
    524  1.1.1.2  fvdl 	switch (ifr->ifr_addr.sa_family) {
    525  1.1.1.2  fvdl 
    526  1.1.1.2  fvdl 	case AF_UNSPEC:
    527  1.1.1.2  fvdl 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
    528  1.1.1.2  fvdl 		bcopy(addrlo, addrhi, 6);
    529  1.1.1.2  fvdl 		break;
    530  1.1.1.2  fvdl 
    531  1.1.1.2  fvdl #ifdef INET
    532  1.1.1.2  fvdl 	case AF_INET:
    533  1.1.1.2  fvdl 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
    534  1.1.1.2  fvdl 		if (sin->sin_addr.s_addr == INADDR_ANY) {
    535  1.1.1.2  fvdl 			/*
    536  1.1.1.2  fvdl 			 * An IP address of INADDR_ANY means listen to all
    537  1.1.1.2  fvdl 			 * of the Ethernet multicast addresses used for IP.
    538  1.1.1.2  fvdl 			 * (This is for the sake of IP multicast routers.)
    539  1.1.1.2  fvdl 			 */
    540  1.1.1.2  fvdl 			bcopy(ether_ipmulticast_min, addrlo, 6);
    541  1.1.1.2  fvdl 			bcopy(ether_ipmulticast_max, addrhi, 6);
    542  1.1.1.2  fvdl 		}
    543  1.1.1.2  fvdl 		else {
    544  1.1.1.2  fvdl 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
    545  1.1.1.2  fvdl 			bcopy(addrlo, addrhi, 6);
    546  1.1.1.2  fvdl 		}
    547  1.1.1.2  fvdl 		break;
    548  1.1.1.2  fvdl #endif
    549  1.1.1.2  fvdl 
    550  1.1.1.2  fvdl 	default:
    551  1.1.1.2  fvdl 		splx(s);
    552  1.1.1.2  fvdl 		return (EAFNOSUPPORT);
    553  1.1.1.2  fvdl 	}
    554  1.1.1.2  fvdl 
    555  1.1.1.2  fvdl 	/*
    556  1.1.1.2  fvdl 	 * Verify that we have valid Ethernet multicast addresses.
    557  1.1.1.2  fvdl 	 */
    558  1.1.1.2  fvdl 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
    559  1.1.1.2  fvdl 		splx(s);
    560  1.1.1.2  fvdl 		return (EINVAL);
    561  1.1.1.2  fvdl 	}
    562  1.1.1.2  fvdl 	/*
    563  1.1.1.2  fvdl 	 * See if the address range is already in the list.
    564  1.1.1.2  fvdl 	 */
    565  1.1.1.2  fvdl 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
    566  1.1.1.2  fvdl 	if (enm != NULL) {
    567  1.1.1.2  fvdl 		/*
    568  1.1.1.2  fvdl 		 * Found it; just increment the reference count.
    569  1.1.1.2  fvdl 		 */
    570  1.1.1.2  fvdl 		++enm->enm_refcount;
    571  1.1.1.2  fvdl 		splx(s);
    572  1.1.1.2  fvdl 		return (0);
    573  1.1.1.2  fvdl 	}
    574  1.1.1.2  fvdl 	/*
    575  1.1.1.2  fvdl 	 * New address or range; malloc a new multicast record
    576  1.1.1.2  fvdl 	 * and link it into the interface's multicast list.
    577  1.1.1.2  fvdl 	 */
    578  1.1.1.2  fvdl 	enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
    579  1.1.1.2  fvdl 	if (enm == NULL) {
    580  1.1.1.2  fvdl 		splx(s);
    581  1.1.1.2  fvdl 		return (ENOBUFS);
    582  1.1.1.2  fvdl 	}
    583  1.1.1.2  fvdl 	bcopy(addrlo, enm->enm_addrlo, 6);
    584  1.1.1.2  fvdl 	bcopy(addrhi, enm->enm_addrhi, 6);
    585  1.1.1.2  fvdl 	enm->enm_ac = ac;
    586  1.1.1.2  fvdl 	enm->enm_refcount = 1;
    587  1.1.1.2  fvdl 	enm->enm_next = ac->ac_multiaddrs;
    588  1.1.1.2  fvdl 	ac->ac_multiaddrs = enm;
    589  1.1.1.2  fvdl 	ac->ac_multicnt++;
    590  1.1.1.2  fvdl 	splx(s);
    591  1.1.1.2  fvdl 	/*
    592  1.1.1.2  fvdl 	 * Return ENETRESET to inform the driver that the list has changed
    593  1.1.1.2  fvdl 	 * and its reception filter should be adjusted accordingly.
    594  1.1.1.2  fvdl 	 */
    595  1.1.1.2  fvdl 	return (ENETRESET);
    596  1.1.1.2  fvdl }
    597  1.1.1.2  fvdl 
    598  1.1.1.2  fvdl /*
    599  1.1.1.2  fvdl  * Delete a multicast address record.
    600  1.1.1.2  fvdl  */
    601  1.1.1.2  fvdl int
    602  1.1.1.2  fvdl ether_delmulti(ifr, ac)
    603  1.1.1.2  fvdl 	struct ifreq *ifr;
    604  1.1.1.2  fvdl 	register struct arpcom *ac;
    605  1.1.1.2  fvdl {
    606  1.1.1.2  fvdl 	register struct ether_multi *enm;
    607  1.1.1.2  fvdl 	register struct ether_multi **p;
    608  1.1.1.2  fvdl 	struct sockaddr_in *sin;
    609  1.1.1.2  fvdl 	u_char addrlo[6];
    610  1.1.1.2  fvdl 	u_char addrhi[6];
    611  1.1.1.2  fvdl 	int s = splimp();
    612  1.1.1.2  fvdl 
    613  1.1.1.2  fvdl 	switch (ifr->ifr_addr.sa_family) {
    614  1.1.1.2  fvdl 
    615  1.1.1.2  fvdl 	case AF_UNSPEC:
    616  1.1.1.2  fvdl 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
    617  1.1.1.2  fvdl 		bcopy(addrlo, addrhi, 6);
    618  1.1.1.2  fvdl 		break;
    619  1.1.1.2  fvdl 
    620  1.1.1.2  fvdl #ifdef INET
    621  1.1.1.2  fvdl 	case AF_INET:
    622  1.1.1.2  fvdl 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
    623  1.1.1.2  fvdl 		if (sin->sin_addr.s_addr == INADDR_ANY) {
    624  1.1.1.2  fvdl 			/*
    625  1.1.1.2  fvdl 			 * An IP address of INADDR_ANY means stop listening
    626  1.1.1.2  fvdl 			 * to the range of Ethernet multicast addresses used
    627  1.1.1.2  fvdl 			 * for IP.
    628  1.1.1.2  fvdl 			 */
    629  1.1.1.2  fvdl 			bcopy(ether_ipmulticast_min, addrlo, 6);
    630  1.1.1.2  fvdl 			bcopy(ether_ipmulticast_max, addrhi, 6);
    631  1.1.1.2  fvdl 		}
    632  1.1.1.2  fvdl 		else {
    633  1.1.1.2  fvdl 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
    634  1.1.1.2  fvdl 			bcopy(addrlo, addrhi, 6);
    635  1.1.1.2  fvdl 		}
    636  1.1.1.2  fvdl 		break;
    637  1.1.1.2  fvdl #endif
    638  1.1.1.2  fvdl 
    639  1.1.1.2  fvdl 	default:
    640  1.1.1.2  fvdl 		splx(s);
    641  1.1.1.2  fvdl 		return (EAFNOSUPPORT);
    642  1.1.1.2  fvdl 	}
    643  1.1.1.2  fvdl 
    644  1.1.1.2  fvdl 	/*
    645  1.1.1.2  fvdl 	 * Look up the address in our list.
    646  1.1.1.2  fvdl 	 */
    647  1.1.1.2  fvdl 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
    648  1.1.1.2  fvdl 	if (enm == NULL) {
    649  1.1.1.2  fvdl 		splx(s);
    650  1.1.1.2  fvdl 		return (ENXIO);
    651  1.1.1.2  fvdl 	}
    652  1.1.1.2  fvdl 	if (--enm->enm_refcount != 0) {
    653  1.1.1.2  fvdl 		/*
    654  1.1.1.2  fvdl 		 * Still some claims to this record.
    655  1.1.1.2  fvdl 		 */
    656  1.1.1.2  fvdl 		splx(s);
    657  1.1.1.2  fvdl 		return (0);
    658  1.1.1.2  fvdl 	}
    659  1.1.1.2  fvdl 	/*
    660  1.1.1.2  fvdl 	 * No remaining claims to this record; unlink and free it.
    661  1.1.1.2  fvdl 	 */
    662  1.1.1.2  fvdl 	for (p = &enm->enm_ac->ac_multiaddrs;
    663  1.1.1.2  fvdl 	     *p != enm;
    664  1.1.1.2  fvdl 	     p = &(*p)->enm_next)
    665  1.1.1.2  fvdl 		continue;
    666  1.1.1.2  fvdl 	*p = (*p)->enm_next;
    667  1.1.1.2  fvdl 	free(enm, M_IFMADDR);
    668  1.1.1.2  fvdl 	ac->ac_multicnt--;
    669  1.1.1.2  fvdl 	splx(s);
    670  1.1.1.2  fvdl 	/*
    671  1.1.1.2  fvdl 	 * Return ENETRESET to inform the driver that the list has changed
    672  1.1.1.2  fvdl 	 * and its reception filter should be adjusted accordingly.
    673  1.1.1.2  fvdl 	 */
    674  1.1.1.2  fvdl 	return (ENETRESET);
    675      1.1   cgd }
    676