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
insert_into_device_name_list(struct ifnet * ifp)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
remove_from_device_name_list(struct ifnet * ifp)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 *
ifnet_byindex_locked(u_int idx)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
ifnet_byindex(u_int idx)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
ifnet_setbyindex_locked(u_short idx,struct ifnet * ifp)108 ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp)
109 {
110 gDevices[idx] = ifp;
111 }
112
113
114 static void
ifnet_setbyindex(u_short idx,struct ifnet * ifp)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
ifindex_alloc_locked(u_short * idxp)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
ifindex_free_locked(u_short idx)145 ifindex_free_locked(u_short idx)
146 {
147 gDevices[idx] = NULL;
148 gDeviceCount--;
149 }
150
151
152 int
if_alloc_inplace(struct ifnet * ifp,u_char type)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 *
if_alloc(u_char type)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
if_free_inplace(struct ifnet * ifp)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
if_free(struct ifnet * ifp)232 if_free(struct ifnet *ifp)
233 {
234 if_free_inplace(ifp);
235
236 _kernel_free(ifp);
237 }
238
239
240 void
if_initname(struct ifnet * ifp,const char * name,int unit)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
ifq_init(struct ifqueue * ifq,const char * name)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
ifq_uninit(struct ifqueue * ifq)277 ifq_uninit(struct ifqueue *ifq)
278 {
279 mtx_destroy(&ifq->ifq_mtx);
280 }
281
282
283 static int
if_transmit_default(struct ifnet * ifp,struct mbuf * m)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
if_input_default(struct ifnet * ifp __unused,struct mbuf * m)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
if_qflush(struct ifnet * ifp)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
if_attach(struct ifnet * ifp)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
if_detach(struct ifnet * ifp)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
if_start(struct ifnet * ifp)403 if_start(struct ifnet *ifp)
404 {
405 ifp->if_start(ifp);
406 }
407
408
409 int
if_printf(struct ifnet * ifp,const char * format,...)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
if_requestencap_default(struct ifnet * ifp,struct if_encap_req * req)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
if_link_state_change(struct ifnet * ifp,int linkState)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 *
if_findmulti(struct ifnet * ifp,struct sockaddr * _address)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
if_freemulti(struct ifmultiaddr * ifma)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 *
_if_addmulti(struct ifnet * ifp,struct sockaddr * address)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
if_addmulti(struct ifnet * ifp,struct sockaddr * address,struct ifmultiaddr ** out)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
if_delmulti_locked(struct ifnet * ifp,struct ifmultiaddr * ifma,int detaching)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
if_delallmulti(struct ifnet * ifp)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
if_delete_multiaddr(struct ifnet * ifp,struct ifmultiaddr * ifma)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
if_delmulti(struct ifnet * ifp,struct sockaddr * sa)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
if_get_counter_default(struct ifnet * ifp,ift_counter cnt)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
if_addr_rlock(struct ifnet * ifp)747 if_addr_rlock(struct ifnet *ifp)
748 {
749 IF_ADDR_LOCK(ifp);
750 }
751
752
753 void
if_addr_runlock(struct ifnet * ifp)754 if_addr_runlock(struct ifnet *ifp)
755 {
756 IF_ADDR_UNLOCK(ifp);
757 }
758
759
760 void
if_maddr_rlock(struct ifnet * ifp)761 if_maddr_rlock(struct ifnet *ifp)
762 {
763 IF_ADDR_LOCK(ifp);
764 }
765
766
767 void
if_maddr_runlock(struct ifnet * ifp)768 if_maddr_runlock(struct ifnet *ifp)
769 {
770 IF_ADDR_UNLOCK(ifp);
771 }
772
773
774 int
ether_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct route * ro)775 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
776 struct route *ro)
777 {
778 return ifp->if_transmit(ifp, m);
779 }
780
781
782 static void
ether_input(struct ifnet * ifp,struct mbuf * m)783 ether_input(struct ifnet *ifp, struct mbuf *m)
784 {
785 int32 count = 0;
786
787 IF_LOCK(&ifp->receive_queue);
788 while (m != NULL) {
789 struct mbuf *mn = m->m_nextpkt;
790 m->m_nextpkt = NULL;
791
792 _IF_ENQUEUE(&ifp->receive_queue, m);
793 count++;
794
795 m = mn;
796 }
797 IF_UNLOCK(&ifp->receive_queue);
798
799 release_sem_etc(ifp->receive_sem, count, B_DO_NOT_RESCHEDULE);
800 }
801
802
803 void
ether_ifattach(struct ifnet * ifp,const uint8_t * lla)804 ether_ifattach(struct ifnet *ifp, const uint8_t *lla)
805 {
806 struct ifaddr *ifa;
807 struct sockaddr_dl *sdl;
808
809 ifp->if_addrlen = ETHER_ADDR_LEN;
810 ifp->if_hdrlen = ETHER_HDR_LEN;
811 if_attach(ifp);
812 ifp->if_mtu = ETHERMTU;
813 ifp->if_output = ether_output;
814 ifp->if_input = ether_input;
815 ifp->if_resolvemulti = NULL; // done in the stack
816 ifp->if_get_counter = NULL;
817 ifp->if_broadcastaddr = etherbroadcastaddr;
818
819 ifa = ifp->if_addr;
820 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
821 sdl->sdl_type = IFT_ETHER;
822 sdl->sdl_alen = ifp->if_addrlen;
823 bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
824 }
825
826
827 void
ether_ifdetach(struct ifnet * ifp)828 ether_ifdetach(struct ifnet *ifp)
829 {
830 if_detach(ifp);
831 }
832
833
834 int
ether_ioctl(struct ifnet * ifp,u_long command,caddr_t data)835 ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
836 {
837 struct ifreq *ifr = (struct ifreq *) data;
838
839 //dprintf("ether_ioctl: received %d\n", command);
840
841 switch (command) {
842 case SIOCSIFMTU:
843 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
844 return EINVAL;
845 ifp->if_mtu = ifr->ifr_mtu;
846 break;
847
848 default:
849 return EINVAL;
850 }
851
852 return 0;
853 }
854
855
856 /*
857 * Initialization, destruction and refcounting functions for ifaddrs.
858 */
859 struct ifaddr *
ifa_alloc(size_t size,int flags)860 ifa_alloc(size_t size, int flags)
861 {
862 struct ifaddr *ifa;
863
864 KASSERT(size >= sizeof(struct ifaddr),
865 ("%s: invalid size %zu", __func__, size));
866
867 ifa = _kernel_malloc(size, M_ZERO | flags);
868 if (ifa == NULL)
869 return (NULL);
870
871 //refcount_init(&ifa->ifa_refcnt, 1);
872
873 return (ifa);
874
875 fail:
876 /* free(NULL) is okay */
877 free(ifa);
878
879 return (NULL);
880 }
881
882 void
if_inc_counter(struct ifnet * ifp,ift_counter cnt,int64_t inc)883 if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc)
884 {
885 switch (cnt) {
886 case IFCOUNTER_IPACKETS:
887 atomic_add64((int64 *)&ifp->if_ipackets, inc);
888 break;
889 case IFCOUNTER_IERRORS:
890 atomic_add64((int64 *)&ifp->if_ierrors, inc);
891 break;
892 case IFCOUNTER_OPACKETS:
893 atomic_add64((int64 *)&ifp->if_opackets, inc);
894 break;
895 case IFCOUNTER_OERRORS:
896 atomic_add64((int64 *)&ifp->if_oerrors, inc);
897 break;
898 case IFCOUNTER_COLLISIONS:
899 atomic_add64((int64 *)&ifp->if_collisions, inc);
900 break;
901 case IFCOUNTER_IBYTES:
902 atomic_add64((int64 *)&ifp->if_ibytes, inc);
903 break;
904 case IFCOUNTER_OBYTES:
905 atomic_add64((int64 *)&ifp->if_obytes, inc);
906 break;
907 case IFCOUNTER_IMCASTS:
908 atomic_add64((int64 *)&ifp->if_imcasts, inc);
909 break;
910 case IFCOUNTER_OMCASTS:
911 atomic_add64((int64 *)&ifp->if_omcasts, inc);
912 break;
913 case IFCOUNTER_IQDROPS:
914 atomic_add64((int64 *)&ifp->if_iqdrops, inc);
915 break;
916 case IFCOUNTER_OQDROPS:
917 atomic_add64((int64 *)&ifp->if_oqdrops, inc);
918 break;
919 case IFCOUNTER_NOPROTO:
920 atomic_add64((int64 *)&ifp->if_noproto, inc);
921 break;
922 case IFCOUNTERS:
923 KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
924 }
925 }
926
927 void
if_bpfmtap(if_t ifh,struct mbuf * m)928 if_bpfmtap(if_t ifh, struct mbuf *m)
929 {
930 struct ifnet *ifp = (struct ifnet *)ifh;
931
932 BPF_MTAP(ifp, m);
933 }
934
935 void
if_etherbpfmtap(if_t ifh,struct mbuf * m)936 if_etherbpfmtap(if_t ifh, struct mbuf *m)
937 {
938 struct ifnet *ifp = (struct ifnet *)ifh;
939
940 ETHER_BPF_MTAP(ifp, m);
941 }
942