xref: /haiku/src/libs/compat/freebsd_network/if.c (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2009, Colin Günther, coling@gmx.de.
3  * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de.
4  * Copyright 2007, Hugo Santos. All Rights Reserved.
5  * Copyright 2004, Marcus Overhagen. All Rights Reserved.
6  *
7  * Distributed under the terms of the MIT License.
8  */
9 
10 
11 #include "device.h"
12 
13 #include <stdio.h>
14 #include <net/if_types.h>
15 #include <sys/sockio.h>
16 
17 #include <compat/sys/bus.h>
18 #include <compat/sys/kernel.h>
19 #include <compat/sys/taskqueue.h>
20 
21 #include <compat/net/bpf.h>
22 #include <compat/net/ethernet.h>
23 #include <compat/net/if.h>
24 #include <compat/net/if_arp.h>
25 #include <compat/net/if_media.h>
26 #include <compat/net/if_var.h>
27 #include <compat/net/if_vlan_var.h>
28 #include <compat/sys/malloc.h>
29 
30 
31 
32 int ifqmaxlen = IFQ_MAXLEN;
33 
34 static void	if_input_default(struct ifnet *, struct mbuf *);
35 static int	if_requestencap_default(struct ifnet *, struct if_encap_req *);
36 
37 
38 
39 #define IFNET_HOLD (void *)(uintptr_t)(-1)
40 
41 
42 static void
43 insert_into_device_name_list(struct ifnet * ifp)
44 {
45 	int i;
46 	for (i = 0; i < MAX_DEVICES; i++) {
47 		if (gDeviceNameList[i] == NULL) {
48 			gDeviceNameList[i] = ifp->device_name;
49 			return;
50 		}
51 	}
52 
53 	panic("too many devices");
54 }
55 
56 
57 static void
58 remove_from_device_name_list(struct ifnet * ifp)
59 {
60 	int i;
61 	for (i = 0; i < MAX_DEVICES; i++) {
62 		if (ifp->device_name == gDeviceNameList[i]) {
63 			int last;
64 			for (last = i + 1; last < MAX_DEVICES; last++) {
65 				if (gDeviceNameList[last] == NULL)
66 					break;
67 			}
68 			last--;
69 
70 			if (i == last)
71 				gDeviceNameList[i] = NULL;
72 			else {
73 				// switch positions with the last entry
74 				gDeviceNameList[i] = gDeviceNameList[last];
75 				gDeviceNameList[last] = NULL;
76 			}
77 			break;
78 		}
79 	}
80 }
81 
82 
83 static struct ifnet *
84 ifnet_byindex_locked(u_int idx)
85 {
86 	struct ifnet *ifp;
87 
88 	ifp = gDevices[idx];
89 
90 	return (ifp);
91 }
92 
93 
94 if_t
95 ifnet_byindex(u_int idx)
96 {
97 	struct ifnet *ifp;
98 
99 	IFNET_RLOCK_NOSLEEP();
100 	ifp = ifnet_byindex_locked(idx);
101 	IFNET_RUNLOCK_NOSLEEP();
102 
103 	return (ifp);
104 }
105 
106 
107 static void
108 ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp)
109 {
110 	gDevices[idx] = ifp;
111 }
112 
113 
114 static void
115 ifnet_setbyindex(u_short idx, struct ifnet *ifp)
116 {
117 	IFNET_WLOCK();
118 	ifnet_setbyindex_locked(idx, ifp);
119 	IFNET_WUNLOCK();
120 }
121 
122 
123 static int
124 ifindex_alloc_locked(u_short *idxp)
125 {
126 	u_short index;
127 
128 	for (index = 0; index < MAX_DEVICES; index++) {
129 		if (gDevices[index] == NULL) {
130 			break;
131 		}
132 	}
133 
134 	if (index == MAX_DEVICES)
135 		return ENOSPC;
136 
137 	gDeviceCount++;
138 	*idxp = index;
139 
140 	return ENOERR;
141 }
142 
143 
144 static void
145 ifindex_free_locked(u_short idx)
146 {
147 	gDevices[idx] = NULL;
148 	gDeviceCount--;
149 }
150 
151 
152 int
153 if_alloc_inplace(struct ifnet *ifp, u_char type)
154 {
155 	char semName[64];
156 	u_short index;
157 
158 	snprintf(semName, sizeof(semName), "%s receive", gDriverName);
159 
160 	ifp->receive_sem = create_sem(0, semName);
161 	if (ifp->receive_sem < B_OK)
162 		return ifp->receive_sem;
163 
164 	ifp->link_state_sem = -1;
165 	ifp->open_count = 0;
166 	ifp->flags = 0;
167 	ifp->if_type = type;
168 	ifq_init(&ifp->receive_queue, semName);
169 
170 	ifp->scan_done_sem = -1;
171 		// WLAN specific, doesn't hurt when initialized for other devices
172 
173 	// Search for the first free device slot, and use that one
174 	IFNET_WLOCK();
175 	if (ifindex_alloc_locked(&index) != ENOERR) {
176 		IFNET_WUNLOCK();
177 		panic("too many devices");
178 		goto err2;
179 	}
180 	ifnet_setbyindex_locked(index, IFNET_HOLD);
181 	IFNET_WUNLOCK();
182 
183 	ifp->if_index = index;
184 	ifnet_setbyindex(ifp->if_index, ifp);
185 
186 	IF_ADDR_LOCK_INIT(ifp);
187 	return 0;
188 
189 err2:
190 	delete_sem(ifp->receive_sem);
191 
192 	return -1;
193 }
194 
195 
196 struct ifnet *
197 if_alloc(u_char type)
198 {
199 	struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO);
200 	if (ifp == NULL)
201 		return NULL;
202 
203 	if (if_alloc_inplace(ifp, type) != 0) {
204 		_kernel_free(ifp);
205 		return NULL;
206 	}
207 
208 	return ifp;
209 }
210 
211 
212 void
213 if_free_inplace(struct ifnet *ifp)
214 {
215 	// IEEE80211 devices won't be in this list,
216 	// so don't try to remove them.
217 	if (ifp->if_type == IFT_ETHER)
218 		remove_from_device_name_list(ifp);
219 
220 	IFNET_WLOCK();
221 	ifindex_free_locked(ifp->if_index);
222 	IFNET_WUNLOCK();
223 
224 	IF_ADDR_LOCK_DESTROY(ifp);
225 
226 	delete_sem(ifp->receive_sem);
227 	ifq_uninit(&ifp->receive_queue);
228 }
229 
230 
231 void
232 if_free(struct ifnet *ifp)
233 {
234 	if_free_inplace(ifp);
235 
236 	_kernel_free(ifp);
237 }
238 
239 
240 void
241 if_initname(struct ifnet *ifp, const char *name, int unit)
242 {
243 	dprintf("if_initname(%p, %s, %d)\n", ifp, name, unit);
244 
245 	if (name == NULL || name[0] == '\0')
246 		panic("interface goes unnamed");
247 
248 	ifp->if_dname = name;
249 	ifp->if_dunit = unit;
250 
251 	strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname));
252 
253 	snprintf(ifp->device_name, sizeof(ifp->device_name), "net/%s/%i",
254 		gDriverName, ifp->if_index);
255 
256 	driver_printf("%s: /dev/%s\n", gDriverName, ifp->device_name);
257 	insert_into_device_name_list(ifp);
258 
259 	ifp->root_device = find_root_device(unit);
260 }
261 
262 
263 void
264 ifq_init(struct ifqueue *ifq, const char *name)
265 {
266 	ifq->ifq_head = NULL;
267 	ifq->ifq_tail = NULL;
268 	ifq->ifq_len = 0;
269 	ifq->ifq_maxlen = IFQ_MAXLEN;
270 	ifq->ifq_drops = 0;
271 
272 	mtx_init(&ifq->ifq_mtx, name, NULL, MTX_DEF);
273 }
274 
275 
276 void
277 ifq_uninit(struct ifqueue *ifq)
278 {
279 	mtx_destroy(&ifq->ifq_mtx);
280 }
281 
282 
283 static int
284 if_transmit_default(struct ifnet *ifp, struct mbuf *m)
285 {
286 	int error;
287 
288 	IFQ_HANDOFF(ifp, m, error);
289 	return (error);
290 }
291 
292 
293 static void
294 if_input_default(struct ifnet *ifp __unused, struct mbuf *m)
295 {
296 
297 	m_freem(m);
298 }
299 
300 
301 /*
302  * Flush an interface queue.
303  */
304 void
305 if_qflush(struct ifnet *ifp)
306 {
307 	struct mbuf *m, *n;
308 	struct ifaltq *ifq;
309 
310 	ifq = &ifp->if_snd;
311 	IFQ_LOCK(ifq);
312 #ifdef ALTQ
313 	if (ALTQ_IS_ENABLED(ifq))
314 		ALTQ_PURGE(ifq);
315 #endif
316 	n = ifq->ifq_head;
317 	while ((m = n) != NULL) {
318 		n = m->m_nextpkt;
319 		m_freem(m);
320 	}
321 	ifq->ifq_head = 0;
322 	ifq->ifq_tail = 0;
323 	ifq->ifq_len = 0;
324 	IFQ_UNLOCK(ifq);
325 }
326 
327 
328 void
329 if_attach(struct ifnet *ifp)
330 {
331 	unsigned socksize, ifasize;
332 	int namelen, masklen;
333 	struct sockaddr_dl *sdl;
334 	struct ifaddr *ifa;
335 
336 	TAILQ_INIT(&ifp->if_addrhead);
337 	TAILQ_INIT(&ifp->if_prefixhead);
338 	TAILQ_INIT(&ifp->if_multiaddrs);
339 
340 	IF_ADDR_LOCK_INIT(ifp);
341 
342 	ifp->if_lladdr.sdl_family = AF_LINK;
343 
344 	ifq_init((struct ifqueue *) &ifp->if_snd, ifp->if_xname);
345 
346 	if (ifp->if_transmit == NULL) {
347 		ifp->if_transmit = if_transmit_default;
348 		ifp->if_qflush = if_qflush;
349 	}
350 	if (ifp->if_input == NULL)
351 		ifp->if_input = if_input_default;
352 
353 	if (ifp->if_requestencap == NULL)
354 		ifp->if_requestencap = if_requestencap_default;
355 
356 	/*
357 	 * Create a Link Level name for this device.
358 	 */
359 	namelen = strlen(ifp->if_xname);
360 	/*
361 	 * Always save enough space for any possiable name so we
362 	 * can do a rename in place later.
363 	 */
364 	masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + IFNAMSIZ;
365 	socksize = masklen + ifp->if_addrlen;
366 	if (socksize < sizeof(*sdl))
367 		socksize = sizeof(*sdl);
368 	socksize = roundup2(socksize, sizeof(long));
369 	ifasize = sizeof(*ifa) + 2 * socksize;
370 	ifa = ifa_alloc(ifasize, M_WAITOK);
371 	sdl = (struct sockaddr_dl *)(ifa + 1);
372 	sdl->sdl_len = socksize;
373 	sdl->sdl_family = AF_LINK;
374 	bcopy(ifp->if_xname, sdl->sdl_data, namelen);
375 	sdl->sdl_nlen = namelen;
376 	sdl->sdl_index = ifp->if_index;
377 	sdl->sdl_type = ifp->if_type;
378 	ifp->if_addr = ifa;
379 	ifa->ifa_ifp = ifp;
380 	//ifa->ifa_rtrequest = link_rtrequest;
381 	ifa->ifa_addr = (struct sockaddr *)sdl;
382 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
383 	ifa->ifa_netmask = (struct sockaddr *)sdl;
384 	sdl->sdl_len = masklen;
385 	while (namelen != 0)
386 		sdl->sdl_data[--namelen] = 0xff;
387 	dprintf("if_attach %p\n", ifa->ifa_addr);
388 }
389 
390 
391 void
392 if_detach(struct ifnet *ifp)
393 {
394 	if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE))
395 		taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
396 
397 	IF_ADDR_LOCK_DESTROY(ifp);
398 	ifq_uninit((struct ifqueue *) &ifp->if_snd);
399 }
400 
401 
402 void
403 if_start(struct ifnet *ifp)
404 {
405 	ifp->if_start(ifp);
406 }
407 
408 
409 int
410 if_printf(struct ifnet *ifp, const char *format, ...)
411 {
412 	char buf[256];
413 	va_list vl;
414 	va_start(vl, format);
415 	vsnprintf(buf, sizeof(buf), format, vl);
416 	va_end(vl);
417 
418 	dprintf("[%s] %s", ifp->device_name, buf);
419 	return 0;
420 }
421 
422 
423 /*
424  * Compat function for handling basic encapsulation requests.
425  * Not converted stacks (FDDI, IB, ..) supports traditional
426  * output model: ARP (and other similar L2 protocols) are handled
427  * inside output routine, arpresolve/nd6_resolve() returns MAC
428  * address instead of full prepend.
429  *
430  * This function creates calculated header==MAC for IPv4/IPv6 and
431  * returns EAFNOSUPPORT (which is then handled in ARP code) for other
432  * address families.
433  */
434 static int
435 if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
436 {
437 
438 	if (req->rtype != IFENCAP_LL)
439 		return (EOPNOTSUPP);
440 
441 	if (req->bufsize < req->lladdr_len)
442 		return (ENOMEM);
443 
444 	switch (req->family) {
445 	case AF_INET:
446 	case AF_INET6:
447 		break;
448 	default:
449 		return (EAFNOSUPPORT);
450 	}
451 
452 	/* Copy lladdr to storage as is */
453 	memmove(req->buf, req->lladdr, req->lladdr_len);
454 	req->bufsize = req->lladdr_len;
455 	req->lladdr_off = 0;
456 
457 	return (0);
458 }
459 
460 
461 void
462 if_link_state_change(struct ifnet *ifp, int linkState)
463 {
464 	if (ifp->if_link_state == linkState)
465 		return;
466 
467 	ifp->if_link_state = linkState;
468 	release_sem_etc(ifp->link_state_sem, 1, B_DO_NOT_RESCHEDULE);
469 }
470 
471 static struct ifmultiaddr *
472 if_findmulti(struct ifnet *ifp, struct sockaddr *_address)
473 {
474 	struct sockaddr_dl *address = (struct sockaddr_dl *) _address;
475 	struct ifmultiaddr *ifma;
476 
477 	TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) {
478 		if (memcmp(LLADDR(address),
479 			LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETHER_ADDR_LEN) == 0)
480 			return ifma;
481 	}
482 
483 	return NULL;
484 }
485 
486 
487 /*
488  * if_freemulti: free ifmultiaddr structure and possibly attached related
489  * addresses.  The caller is responsible for implementing reference
490  * counting, notifying the driver, handling routing messages, and releasing
491  * any dependent link layer state.
492  */
493 static void
494 if_freemulti(struct ifmultiaddr *ifma)
495 {
496 
497 	KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d",
498 	    ifma->ifma_refcount));
499 	KASSERT(ifma->ifma_protospec == NULL,
500 	    ("if_freemulti: protospec not NULL"));
501 
502 	if (ifma->ifma_lladdr != NULL)
503 		free(ifma->ifma_lladdr);
504 
505 	// Haiku note: We use a field in the ifmultiaddr struct (ifma_addr_storage)
506 	// to store the address and let ifma_addr point to that. We therefore do not
507 	// free it here, as it will be freed as part of freeing the if_multiaddr.
508 	//free(ifma->ifma_addr);
509 
510 	free(ifma);
511 }
512 
513 
514 static struct ifmultiaddr *
515 _if_addmulti(struct ifnet *ifp, struct sockaddr *address)
516 {
517 	struct ifmultiaddr *addr = if_findmulti(ifp, address);
518 
519 	if (addr != NULL) {
520 		addr->ifma_refcount++;
521 		return addr;
522 	}
523 
524 	addr = (struct ifmultiaddr *) malloc(sizeof(struct ifmultiaddr));
525 	if (addr == NULL)
526 		return NULL;
527 
528 	addr->ifma_lladdr = NULL;
529 	addr->ifma_ifp = ifp;
530 	addr->ifma_protospec = NULL;
531 
532 	memcpy(&addr->ifma_addr_storage, address, sizeof(struct sockaddr_dl));
533 	addr->ifma_addr = (struct sockaddr *) &addr->ifma_addr_storage;
534 
535 	addr->ifma_refcount = 1;
536 
537 	TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, addr, ifma_link);
538 
539 	return addr;
540 }
541 
542 
543 int
544 if_addmulti(struct ifnet *ifp, struct sockaddr *address,
545 	struct ifmultiaddr **out)
546 {
547 	struct ifmultiaddr *result;
548 	int refcount = 0;
549 
550 	IF_ADDR_LOCK(ifp);
551 	result = _if_addmulti(ifp, address);
552 	if (result)
553 		refcount = result->ifma_refcount;
554 	IF_ADDR_UNLOCK(ifp);
555 
556 	if (result == NULL)
557 		return ENOBUFS;
558 
559 	if (refcount == 1 && ifp->if_ioctl != NULL)
560 		ifp->if_ioctl(ifp, SIOCADDMULTI, NULL);
561 
562 	if (out)
563 		(*out) = result;
564 
565 	return 0;
566 }
567 
568 
569 static int
570 if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
571 {
572 	struct ifmultiaddr *ll_ifma;
573 
574 	if (ifp != NULL && ifma->ifma_ifp != NULL) {
575 		KASSERT(ifma->ifma_ifp == ifp,
576 		    ("%s: inconsistent ifp %p", __func__, ifp));
577 		IF_ADDR_LOCK_ASSERT(ifp);
578 	}
579 
580 	ifp = ifma->ifma_ifp;
581 
582 	/*
583 	 * If the ifnet is detaching, null out references to ifnet,
584 	 * so that upper protocol layers will notice, and not attempt
585 	 * to obtain locks for an ifnet which no longer exists. The
586 	 * routing socket announcement must happen before the ifnet
587 	 * instance is detached from the system.
588 	 */
589 	if (detaching) {
590 #ifdef DIAGNOSTIC
591 		printf("%s: detaching ifnet instance %p\n", __func__, ifp);
592 #endif
593 		/*
594 		 * ifp may already be nulled out if we are being reentered
595 		 * to delete the ll_ifma.
596 		 */
597 		if (ifp != NULL) {
598 #ifndef __HAIKU__
599 			rt_newmaddrmsg(RTM_DELMADDR, ifma);
600 #endif
601 			ifma->ifma_ifp = NULL;
602 		}
603 	}
604 
605 	if (--ifma->ifma_refcount > 0)
606 		return 0;
607 
608 #ifndef __HAIKU__
609 	/*
610 	 * If this ifma is a network-layer ifma, a link-layer ifma may
611 	 * have been associated with it. Release it first if so.
612 	 */
613 	ll_ifma = ifma->ifma_llifma;
614 	if (ll_ifma != NULL) {
615 		KASSERT(ifma->ifma_lladdr != NULL,
616 		    ("%s: llifma w/o lladdr", __func__));
617 		if (detaching)
618 			ll_ifma->ifma_ifp = NULL;	/* XXX */
619 		if (--ll_ifma->ifma_refcount == 0) {
620 			if (ifp != NULL) {
621 				TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma,
622 				    ifma_link);
623 			}
624 			if_freemulti(ll_ifma);
625 		}
626 	}
627 #endif
628 
629 	if (ifp != NULL)
630 		TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
631 
632 	if_freemulti(ifma);
633 
634 	/*
635 	 * The last reference to this instance of struct ifmultiaddr
636 	 * was released; the hardware should be notified of this change.
637 	 */
638 	return 1;
639 }
640 
641 
642 /*
643  * Delete all multicast group membership for an interface.
644  * Should be used to quickly flush all multicast filters.
645  */
646 void
647 if_delallmulti(struct ifnet *ifp)
648 {
649 	struct ifmultiaddr *ifma;
650 	struct ifmultiaddr *next;
651 
652 	IF_ADDR_LOCK(ifp);
653 	TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
654 		if_delmulti_locked(ifp, ifma, 0);
655 	IF_ADDR_UNLOCK(ifp);
656 }
657 
658 
659 static void
660 if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma)
661 {
662 	TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
663 	free(ifma);
664 }
665 
666 
667 int
668 if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
669 {
670 	struct ifmultiaddr *ifma;
671 	int lastref;
672 #if 0 /* def INVARIANTS */
673 	struct ifnet *oifp;
674 
675 	IFNET_RLOCK_NOSLEEP();
676 	TAILQ_FOREACH(oifp, &V_ifnet, if_link)
677 		if (ifp == oifp)
678 			break;
679 	if (ifp != oifp)
680 		ifp = NULL;
681 	IFNET_RUNLOCK_NOSLEEP();
682 
683 	KASSERT(ifp != NULL, ("%s: ifnet went away", __func__));
684 #endif
685 	if (ifp == NULL)
686 		return (ENOENT);
687 
688 	IF_ADDR_LOCK(ifp);
689 	lastref = 0;
690 	ifma = if_findmulti(ifp, sa);
691 	if (ifma != NULL)
692 		lastref = if_delmulti_locked(ifp, ifma, 0);
693 	IF_ADDR_UNLOCK(ifp);
694 
695 	if (ifma == NULL)
696 		return (ENOENT);
697 
698 	if (lastref && ifp->if_ioctl != NULL) {
699 		(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
700 	}
701 
702 	return (0);
703 }
704 
705 
706 /*
707  * Return counter values from counter(9)s stored in ifnet.
708  */
709 uint64_t
710 if_get_counter_default(struct ifnet *ifp, ift_counter cnt)
711 {
712 
713 	KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
714 
715 	switch (cnt) {
716 		case IFCOUNTER_IPACKETS:
717 			return atomic_get64((int64 *)&ifp->if_ipackets);
718 		case IFCOUNTER_IERRORS:
719 			return atomic_get64((int64 *)&ifp->if_ierrors);
720 		case IFCOUNTER_OPACKETS:
721 			return atomic_get64((int64 *)&ifp->if_opackets);
722 		case IFCOUNTER_OERRORS:
723 			return atomic_get64((int64 *)&ifp->if_oerrors);
724 		case IFCOUNTER_COLLISIONS:
725 			return atomic_get64((int64 *)&ifp->if_collisions);
726 		case IFCOUNTER_IBYTES:
727 			return atomic_get64((int64 *)&ifp->if_ibytes);
728 		case IFCOUNTER_OBYTES:
729 			return atomic_get64((int64 *)&ifp->if_obytes);
730 		case IFCOUNTER_IMCASTS:
731 			return atomic_get64((int64 *)&ifp->if_imcasts);
732 		case IFCOUNTER_OMCASTS:
733 			return atomic_get64((int64 *)&ifp->if_omcasts);
734 		case IFCOUNTER_IQDROPS:
735 			return atomic_get64((int64 *)&ifp->if_iqdrops);
736 		case IFCOUNTER_OQDROPS:
737 			return atomic_get64((int64 *)&ifp->if_oqdrops);
738 		case IFCOUNTER_NOPROTO:
739 			return atomic_get64((int64 *)&ifp->if_noproto);
740 		case IFCOUNTERS:
741 			KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
742 	}
743 	return 0;
744 }
745 
746 void
747 if_addr_rlock(struct ifnet *ifp)
748 {
749 	IF_ADDR_LOCK(ifp);
750 }
751 
752 
753 void
754 if_addr_runlock(struct ifnet *ifp)
755 {
756 	IF_ADDR_UNLOCK(ifp);
757 }
758 
759 
760 void
761 if_maddr_rlock(struct ifnet *ifp)
762 {
763 	IF_ADDR_LOCK(ifp);
764 }
765 
766 
767 void
768 if_maddr_runlock(struct ifnet *ifp)
769 {
770 	IF_ADDR_UNLOCK(ifp);
771 }
772 
773 
774 int
775 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
776 	struct route *ro)
777 {
778 	int error = 0;
779 	IFQ_HANDOFF(ifp, m, error);
780 	return error;
781 }
782 
783 
784 static void
785 ether_input(struct ifnet *ifp, struct mbuf *m)
786 {
787 	int32 count = 0;
788 
789 	IF_LOCK(&ifp->receive_queue);
790 	while (m != NULL) {
791 		struct mbuf *mn = m->m_nextpkt;
792 		m->m_nextpkt = NULL;
793 
794 		_IF_ENQUEUE(&ifp->receive_queue, m);
795 		count++;
796 
797 		m = mn;
798 	}
799 	IF_UNLOCK(&ifp->receive_queue);
800 
801 	release_sem_etc(ifp->receive_sem, count, B_DO_NOT_RESCHEDULE);
802 }
803 
804 
805 void
806 ether_ifattach(struct ifnet *ifp, const uint8_t *lla)
807 {
808 	struct ifaddr *ifa;
809 	struct sockaddr_dl *sdl;
810 
811 	ifp->if_addrlen = ETHER_ADDR_LEN;
812 	ifp->if_hdrlen = ETHER_HDR_LEN;
813 	if_attach(ifp);
814 	ifp->if_mtu = ETHERMTU;
815 	ifp->if_output = ether_output;
816 	ifp->if_input = ether_input;
817 	ifp->if_resolvemulti = NULL; // done in the stack
818 	ifp->if_get_counter = NULL;
819 	ifp->if_broadcastaddr = etherbroadcastaddr;
820 
821 	ifa = ifp->if_addr;
822 	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
823 	sdl->sdl_type = IFT_ETHER;
824 	sdl->sdl_alen = ifp->if_addrlen;
825 	bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
826 }
827 
828 
829 void
830 ether_ifdetach(struct ifnet *ifp)
831 {
832 	if_detach(ifp);
833 }
834 
835 
836 int
837 ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
838 {
839 	struct ifreq *ifr = (struct ifreq *) data;
840 
841 	//dprintf("ether_ioctl: received %d\n", command);
842 
843 	switch (command) {
844 		case SIOCSIFMTU:
845 			if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
846 				return EINVAL;
847 			ifp->if_mtu = ifr->ifr_mtu;
848 			break;
849 
850 		default:
851 			return EINVAL;
852 	}
853 
854 	return 0;
855 }
856 
857 
858 /*
859  * Initialization, destruction and refcounting functions for ifaddrs.
860  */
861 struct ifaddr *
862 ifa_alloc(size_t size, int flags)
863 {
864 	struct ifaddr *ifa;
865 
866 	KASSERT(size >= sizeof(struct ifaddr),
867 	    ("%s: invalid size %zu", __func__, size));
868 
869 	ifa = _kernel_malloc(size, M_ZERO | flags);
870 	if (ifa == NULL)
871 		return (NULL);
872 
873 	//refcount_init(&ifa->ifa_refcnt, 1);
874 
875 	return (ifa);
876 
877 fail:
878 	/* free(NULL) is okay */
879 	free(ifa);
880 
881 	return (NULL);
882 }
883 
884 void
885 if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc)
886 {
887 	switch (cnt) {
888 		case IFCOUNTER_IPACKETS:
889 			atomic_add64((int64 *)&ifp->if_ipackets, inc);
890 			break;
891 		case IFCOUNTER_IERRORS:
892 			atomic_add64((int64 *)&ifp->if_ierrors, inc);
893 			break;
894 		case IFCOUNTER_OPACKETS:
895 			atomic_add64((int64 *)&ifp->if_opackets, inc);
896 			break;
897 		case IFCOUNTER_OERRORS:
898 			atomic_add64((int64 *)&ifp->if_oerrors, inc);
899 			break;
900 		case IFCOUNTER_COLLISIONS:
901 			atomic_add64((int64 *)&ifp->if_collisions, inc);
902 			break;
903 		case IFCOUNTER_IBYTES:
904 			atomic_add64((int64 *)&ifp->if_ibytes, inc);
905 			break;
906 		case IFCOUNTER_OBYTES:
907 			atomic_add64((int64 *)&ifp->if_obytes, inc);
908 			break;
909 		case IFCOUNTER_IMCASTS:
910 			atomic_add64((int64 *)&ifp->if_imcasts, inc);
911 			break;
912 		case IFCOUNTER_OMCASTS:
913 			atomic_add64((int64 *)&ifp->if_omcasts, inc);
914 			break;
915 		case IFCOUNTER_IQDROPS:
916 			atomic_add64((int64 *)&ifp->if_iqdrops, inc);
917 			break;
918 		case IFCOUNTER_OQDROPS:
919 			atomic_add64((int64 *)&ifp->if_oqdrops, inc);
920 			break;
921 		case IFCOUNTER_NOPROTO:
922 			atomic_add64((int64 *)&ifp->if_noproto, inc);
923 			break;
924 		case IFCOUNTERS:
925 			KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
926 	}
927 }
928 
929 void
930 if_bpfmtap(if_t ifh, struct mbuf *m)
931 {
932 	struct ifnet *ifp = (struct ifnet *)ifh;
933 
934 	BPF_MTAP(ifp, m);
935 }
936 
937 void
938 if_etherbpfmtap(if_t ifh, struct mbuf *m)
939 {
940 	struct ifnet *ifp = (struct ifnet *)ifh;
941 
942 	ETHER_BPF_MTAP(ifp, m);
943 }
944