xref: /original-bsd/sys/net/if_ethersubr.c (revision c7ef4596)
1 /*
2  * Copyright (c) 1982, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)if_ethersubr.c	7.21 (Berkeley) 08/14/92
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "kernel.h"
13 #include "malloc.h"
14 #include "mbuf.h"
15 #include "protosw.h"
16 #include "socket.h"
17 #include "ioctl.h"
18 #include "errno.h"
19 #include "syslog.h"
20 #include "machine/cpu.h"
21 
22 #include "if.h"
23 #include "netisr.h"
24 #include "route.h"
25 #include "if_llc.h"
26 #include "if_dl.h"
27 #include "if_types.h"
28 
29 #ifdef INET
30 #include "../netinet/in.h"
31 #include "../netinet/in_var.h"
32 #endif
33 #include "../netinet/if_ether.h"
34 
35 #ifdef NS
36 #include "../netns/ns.h"
37 #include "../netns/ns_if.h"
38 #endif
39 
40 #ifdef ISO
41 #include "../netiso/argo_debug.h"
42 #include "../netiso/iso.h"
43 #include "../netiso/iso_var.h"
44 #include "../netiso/iso_snpac.h"
45 #endif
46 
47 u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
48 extern	struct ifnet loif;
49 #define senderr(e) { error = (e); goto bad;}
50 
51 /*
52  * Ethernet output routine.
53  * Encapsulate a packet of type family for the local net.
54  * Use trailer local net encapsulation if enough data in first
55  * packet leaves a multiple of 512 bytes of data in remainder.
56  * Assumes that ifp is actually pointer to arpcom structure.
57  */
58 ether_output(ifp, m0, dst, rt0)
59 	register struct ifnet *ifp;
60 	struct mbuf *m0;
61 	struct sockaddr *dst;
62 	struct rtentry *rt0;
63 {
64 	short type;
65 	int s, error = 0;
66  	u_char edst[6];
67 	register struct mbuf *m = m0;
68 	register struct rtentry *rt;
69 	struct mbuf *mcopy = (struct mbuf *)0;
70 	register struct ether_header *eh;
71 	int off, len = m->m_pkthdr.len;
72 	struct arpcom *ac = (struct arpcom *)ifp;
73 
74 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
75 		senderr(ENETDOWN);
76 	ifp->if_lastchange = time;
77 	if (rt = rt0) {
78 		if ((rt->rt_flags & RTF_UP) == 0) {
79 			if (rt0 = rt = rtalloc1(dst, 1))
80 				rt->rt_refcnt--;
81 			else
82 				senderr(EHOSTUNREACH);
83 		}
84 		if (rt->rt_flags & RTF_GATEWAY) {
85 			if (rt->rt_gwroute == 0)
86 				goto lookup;
87 			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
88 				rtfree(rt); rt = rt0;
89 			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
90 				if ((rt = rt->rt_gwroute) == 0)
91 					senderr(EHOSTUNREACH);
92 			}
93 		}
94 		if (rt->rt_flags & RTF_REJECT)
95 			if (rt->rt_rmx.rmx_expire == 0 ||
96 			    time.tv_sec < rt->rt_rmx.rmx_expire)
97 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
98 	}
99 	switch (dst->sa_family) {
100 
101 #ifdef INET
102 	case AF_INET:
103 		if (!arpresolve(ac, rt, m, (struct sockaddr_in *)dst,
104 				edst))
105 			return (0);	/* if not yet resolved */
106 		/* If broadcasting on a simplex interface, loopback a copy */
107 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
108 			mcopy = m_copy(m, 0, (int)M_COPYALL);
109 		off = m->m_pkthdr.len - m->m_len;
110 		type = ETHERTYPE_IP;
111 		break;
112 #endif
113 #ifdef NS
114 	case AF_NS:
115 		type = ETHERTYPE_NS;
116  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
117 		    (caddr_t)edst, sizeof (edst));
118 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
119 			return (looutput(ifp, m, dst, rt));
120 		/* If broadcasting on a simplex interface, loopback a copy */
121 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
122 			mcopy = m_copy(m, 0, (int)M_COPYALL);
123 		break;
124 #endif
125 #ifdef	ISO
126 	case AF_ISO: {
127 		int	snpalen;
128 		struct	llc *l;
129 		register struct sockaddr_dl *sdl;
130 
131 		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
132 		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
133 			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
134 		} else if (error =
135 			    iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
136 					    (char *)edst, &snpalen))
137 			goto bad; /* Not Resolved */
138 		/* If broadcasting on a simplex interface, loopback a copy */
139 		if (*edst & 1)
140 			m->m_flags |= (M_BCAST|M_MCAST);
141 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
142 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
143 			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
144 			if (mcopy) {
145 				eh = mtod(mcopy, struct ether_header *);
146 				bcopy((caddr_t)edst,
147 				      (caddr_t)eh->ether_dhost, sizeof (edst));
148 				bcopy((caddr_t)ac->ac_enaddr,
149 				      (caddr_t)eh->ether_shost, sizeof (edst));
150 			}
151 		}
152 		M_PREPEND(m, 3, M_DONTWAIT);
153 		if (m == NULL)
154 			return (0);
155 		type = m->m_pkthdr.len;
156 		l = mtod(m, struct llc *);
157 		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
158 		l->llc_control = LLC_UI;
159 		len += 3;
160 		IFDEBUG(D_ETHER)
161 			int i;
162 			printf("unoutput: sending pkt to: ");
163 			for (i=0; i<6; i++)
164 				printf("%x ", edst[i] & 0xff);
165 			printf("\n");
166 		ENDDEBUG
167 		} break;
168 #endif	ISO
169 
170 	case AF_UNSPEC:
171 		eh = (struct ether_header *)dst->sa_data;
172  		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
173 		type = eh->ether_type;
174 		break;
175 
176 	default:
177 		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
178 			dst->sa_family);
179 		senderr(EAFNOSUPPORT);
180 	}
181 
182 
183 	if (mcopy)
184 		(void) looutput(ifp, mcopy, dst, rt);
185 	/*
186 	 * Add local net header.  If no space in first mbuf,
187 	 * allocate another.
188 	 */
189 	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
190 	if (m == 0)
191 		senderr(ENOBUFS);
192 	eh = mtod(m, struct ether_header *);
193 	type = htons((u_short)type);
194 	bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
195 		sizeof(eh->ether_type));
196  	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
197  	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
198 	    sizeof(eh->ether_shost));
199 	s = splimp();
200 	/*
201 	 * Queue message on interface, and start output if interface
202 	 * not yet active.
203 	 */
204 	if (IF_QFULL(&ifp->if_snd)) {
205 		IF_DROP(&ifp->if_snd);
206 		splx(s);
207 		senderr(ENOBUFS);
208 	}
209 	IF_ENQUEUE(&ifp->if_snd, m);
210 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
211 		(*ifp->if_start)(ifp);
212 	splx(s);
213 	ifp->if_obytes += len + sizeof (struct ether_header);
214 	if (m->m_flags & M_MCAST)
215 		ifp->if_omcasts++;
216 	return (error);
217 
218 bad:
219 	if (m)
220 		m_freem(m);
221 	return (error);
222 }
223 
224 /*
225  * Process a received Ethernet packet;
226  * the packet is in the mbuf chain m without
227  * the ether header, which is provided separately.
228  */
229 ether_input(ifp, eh, m)
230 	struct ifnet *ifp;
231 	register struct ether_header *eh;
232 	struct mbuf *m;
233 {
234 	register struct ifqueue *inq;
235 	register struct llc *l;
236 	int s;
237 
238 	if ((ifp->if_flags & IFF_UP) == 0) {
239 		m_freem(m);
240 		return;
241 	}
242 	ifp->if_lastchange = time;
243 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
244 	if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
245 	    sizeof(etherbroadcastaddr)) == 0)
246 		m->m_flags |= M_BCAST;
247 	else if (eh->ether_dhost[0] & 1)
248 		m->m_flags |= M_MCAST;
249 	if (m->m_flags & (M_BCAST|M_MCAST))
250 		ifp->if_imcasts++;
251 
252 	switch (eh->ether_type) {
253 #ifdef INET
254 	case ETHERTYPE_IP:
255 		schednetisr(NETISR_IP);
256 		inq = &ipintrq;
257 		break;
258 
259 	case ETHERTYPE_ARP:
260 		schednetisr(NETISR_ARP);
261 		inq = &arpintrq;
262 		break;
263 #endif
264 #ifdef NS
265 	case ETHERTYPE_NS:
266 		schednetisr(NETISR_NS);
267 		inq = &nsintrq;
268 		break;
269 
270 #endif
271 	default:
272 #ifdef	ISO
273 		if (eh->ether_type > ETHERMTU)
274 			goto dropanyway;
275 		l = mtod(m, struct llc *);
276 		switch (l->llc_control) {
277 		case LLC_UI:
278 		/* LLC_UI_P forbidden in class 1 service */
279 		    if ((l->llc_dsap == LLC_ISO_LSAP) &&
280 			(l->llc_ssap == LLC_ISO_LSAP)) {
281 				/* LSAP for ISO */
282 			if (m->m_pkthdr.len > eh->ether_type)
283 				m_adj(m, eh->ether_type - m->m_pkthdr.len);
284 			m->m_data += 3;		/* XXX */
285 			m->m_len -= 3;		/* XXX */
286 			m->m_pkthdr.len -= 3;	/* XXX */
287 			M_PREPEND(m, sizeof *eh, M_DONTWAIT);
288 			if (m == 0)
289 				return;
290 			*mtod(m, struct ether_header *) = *eh;
291 			IFDEBUG(D_ETHER)
292 			    printf("clnp packet");
293 			ENDDEBUG
294 			schednetisr(NETISR_ISO);
295 			inq = &clnlintrq;
296 			break;
297 		    }
298 		    goto dropanyway;
299 
300 		case LLC_XID:
301 		case LLC_XID_P:
302 		    if(m->m_len < 6)
303 			goto dropanyway;
304 		    l->llc_window = 0;
305 		    l->llc_fid = 9;
306 		    l->llc_class = 1;
307 		    l->llc_dsap = l->llc_ssap = 0;
308 		    /* Fall through to */
309 		case LLC_TEST:
310 		case LLC_TEST_P:
311 		{
312 		    struct sockaddr sa;
313 		    register struct ether_header *eh2;
314 		    int i;
315 		    u_char c = l->llc_dsap;
316 		    l->llc_dsap = l->llc_ssap;
317 		    l->llc_ssap = c;
318 		    if (m->m_flags & (M_BCAST | M_MCAST))
319 			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
320 			      (caddr_t)eh->ether_dhost, 6);
321 		    sa.sa_family = AF_UNSPEC;
322 		    sa.sa_len = sizeof(sa);
323 		    eh2 = (struct ether_header *)sa.sa_data;
324 		    for (i = 0; i < 6; i++) {
325 			eh2->ether_shost[i] = c = eh->ether_dhost[i];
326 			eh2->ether_dhost[i] =
327 				eh->ether_dhost[i] = eh->ether_shost[i];
328 			eh->ether_shost[i] = c;
329 		    }
330 		    ifp->if_output(ifp, m, &sa, (struct rtentry *)0);
331 		    return;
332 		}
333 		dropanyway:
334 		default:
335 		    m_freem(m);
336 		    return;
337 	    }
338 #else
339 	    m_freem(m);
340 	    return;
341 #endif	ISO
342 	}
343 
344 	s = splimp();
345 	if (IF_QFULL(inq)) {
346 		IF_DROP(inq);
347 		m_freem(m);
348 	} else
349 		IF_ENQUEUE(inq, m);
350 	splx(s);
351 }
352 
353 /*
354  * Convert Ethernet address to printable (loggable) representation.
355  */
356 static char digits[] = "0123456789abcdef";
357 char *
358 ether_sprintf(ap)
359 	register u_char *ap;
360 {
361 	register i;
362 	static char etherbuf[18];
363 	register char *cp = etherbuf;
364 
365 	for (i = 0; i < 6; i++) {
366 		*cp++ = digits[*ap >> 4];
367 		*cp++ = digits[*ap++ & 0xf];
368 		*cp++ = ':';
369 	}
370 	*--cp = 0;
371 	return (etherbuf);
372 }
373 
374 /*
375  * Perform common duties while attaching to interface list
376  */
377 ether_ifattach(ifp)
378 	register struct ifnet *ifp;
379 {
380 	register struct ifaddr *ifa;
381 	register struct sockaddr_dl *sdl;
382 
383 	ifp->if_type = IFT_ETHER;
384 	ifp->if_addrlen = 6;
385 	ifp->if_hdrlen = 14;
386 	ifp->if_mtu = ETHERMTU;
387 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
388 		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
389 		    sdl->sdl_family == AF_LINK) {
390 			sdl->sdl_type = IFT_ETHER;
391 			sdl->sdl_alen = ifp->if_addrlen;
392 			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
393 			      LLADDR(sdl), ifp->if_addrlen);
394 			break;
395 		}
396 }
397 
398 #ifdef MULTICAST
399 u_char	ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
400 u_char	ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
401 /*
402  * Add an Ethernet multicast address or range of addresses to the list for a
403  * given interface.
404  */
405 int
406 ether_addmulti(ifr, ac)
407 	struct ifreq *ifr;
408 	register struct arpcom *ac;
409 {
410 	register struct ether_multi *enm;
411 	struct sockaddr_in *sin;
412 	u_char addrlo[6];
413 	u_char addrhi[6];
414 	int s = splimp();
415 
416 	switch (ifr->ifr_addr.sa_family) {
417 
418 	case AF_UNSPEC:
419 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
420 		bcopy(addrlo, addrhi, 6);
421 		break;
422 
423 #ifdef INET
424 	case AF_INET:
425 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
426 		if (sin->sin_addr.s_addr == INADDR_ANY) {
427 			/*
428 			 * An IP address of INADDR_ANY means listen to all
429 			 * of the Ethernet multicast addresses used for IP.
430 			 * (This is for the sake of IP multicast routers.)
431 			 */
432 			bcopy(ether_ipmulticast_min, addrlo, 6);
433 			bcopy(ether_ipmulticast_max, addrhi, 6);
434 		}
435 		else {
436 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
437 			bcopy(addrlo, addrhi, 6);
438 		}
439 		break;
440 #endif
441 
442 	default:
443 		splx(s);
444 		return (EAFNOSUPPORT);
445 	}
446 
447 	/*
448 	 * Verify that we have valid Ethernet multicast addresses.
449 	 */
450 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
451 		splx(s);
452 		return (EINVAL);
453 	}
454 	/*
455 	 * See if the address range is already in the list.
456 	 */
457 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
458 	if (enm != NULL) {
459 		/*
460 		 * Found it; just increment the reference count.
461 		 */
462 		++enm->enm_refcount;
463 		splx(s);
464 		return (0);
465 	}
466 	/*
467 	 * New address or range; malloc a new multicast record
468 	 * and link it into the interface's multicast list.
469 	 */
470 	enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
471 	if (enm == NULL) {
472 		splx(s);
473 		return (ENOBUFS);
474 	}
475 	bcopy(addrlo, enm->enm_addrlo, 6);
476 	bcopy(addrhi, enm->enm_addrhi, 6);
477 	enm->enm_ac = ac;
478 	enm->enm_refcount = 1;
479 	enm->enm_next = ac->ac_multiaddrs;
480 	ac->ac_multiaddrs = enm;
481 	ac->ac_multicnt++;
482 	splx(s);
483 	/*
484 	 * Return ENETRESET to inform the driver that the list has changed
485 	 * and its reception filter should be adjusted accordingly.
486 	 */
487 	return (ENETRESET);
488 }
489 
490 /*
491  * Delete a multicast address record.
492  */
493 int
494 ether_delmulti(ifr, ac)
495 	struct ifreq *ifr;
496 	register struct arpcom *ac;
497 {
498 	register struct ether_multi *enm;
499 	register struct ether_multi **p;
500 	struct sockaddr_in *sin;
501 	u_char addrlo[6];
502 	u_char addrhi[6];
503 	int s = splimp();
504 
505 	switch (ifr->ifr_addr.sa_family) {
506 
507 	case AF_UNSPEC:
508 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
509 		bcopy(addrlo, addrhi, 6);
510 		break;
511 
512 #ifdef INET
513 	case AF_INET:
514 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
515 		if (sin->sin_addr.s_addr == INADDR_ANY) {
516 			/*
517 			 * An IP address of INADDR_ANY means stop listening
518 			 * to the range of Ethernet multicast addresses used
519 			 * for IP.
520 			 */
521 			bcopy(ether_ipmulticast_min, addrlo, 6);
522 			bcopy(ether_ipmulticast_max, addrhi, 6);
523 		}
524 		else {
525 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
526 			bcopy(addrlo, addrhi, 6);
527 		}
528 		break;
529 #endif
530 
531 	default:
532 		splx(s);
533 		return (EAFNOSUPPORT);
534 	}
535 
536 	/*
537 	 * Look up the address in our list.
538 	 */
539 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
540 	if (enm == NULL) {
541 		splx(s);
542 		return (ENXIO);
543 	}
544 	if (--enm->enm_refcount != 0) {
545 		/*
546 		 * Still some claims to this record.
547 		 */
548 		splx(s);
549 		return (0);
550 	}
551 	/*
552 	 * No remaining claims to this record; unlink and free it.
553 	 */
554 	for (p = &enm->enm_ac->ac_multiaddrs;
555 	     *p != enm;
556 	     p = &(*p)->enm_next)
557 		continue;
558 	*p = (*p)->enm_next;
559 	free(enm, M_IFMADDR);
560 	ac->ac_multicnt--;
561 	splx(s);
562 	/*
563 	 * Return ENETRESET to inform the driver that the list has changed
564 	 * and its reception filter should be adjusted accordingly.
565 	 */
566 	return (ENETRESET);
567 }
568 #endif
569