TCP: Fixed RTO update and dup ACKs generation.
[haiku.git] / src / libs / compat / freebsd_network / if.c
blobdc67514295074b1c9b3883880bc861783b173d1d
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.
7 * Distributed under the terms of the MIT License.
8 */
11 #include "device.h"
13 #include <stdio.h>
14 #include <net/if_types.h>
15 #include <sys/sockio.h>
17 #include <compat/sys/bus.h>
18 #include <compat/sys/kernel.h>
19 #include <compat/sys/taskqueue.h>
21 #include <compat/net/if.h>
22 #include <compat/net/if_arp.h>
23 #include <compat/net/if_media.h>
24 #include <compat/net/if_var.h>
25 #include <compat/sys/malloc.h>
27 #include <compat/net/ethernet.h>
30 int ifqmaxlen = IFQ_MAXLEN;
33 #define IFNET_HOLD (void *)(uintptr_t)(-1)
36 static void
37 insert_into_device_name_list(struct ifnet * ifp)
39 int i;
40 for (i = 0; i < MAX_DEVICES; i++) {
41 if (gDeviceNameList[i] == NULL) {
42 gDeviceNameList[i] = ifp->device_name;
43 return;
47 panic("too many devices");
51 static void
52 remove_from_device_name_list(struct ifnet * ifp)
54 int i;
55 for (i = 0; i < MAX_DEVICES; i++) {
56 if (ifp->device_name == gDeviceNameList[i]) {
57 int last;
58 for (last = i + 1; last < MAX_DEVICES; last++) {
59 if (gDeviceNameList[last] == NULL)
60 break;
62 last--;
64 if (i == last)
65 gDeviceNameList[i] = NULL;
66 else {
67 // switch positions with the last entry
68 gDeviceNameList[i] = gDeviceNameList[last];
69 gDeviceNameList[last] = NULL;
71 break;
77 struct ifnet *
78 ifnet_byindex(u_short idx)
80 struct ifnet *ifp;
82 IFNET_RLOCK_NOSLEEP();
83 ifp = ifnet_byindex_locked(idx);
84 IFNET_RUNLOCK_NOSLEEP();
86 return (ifp);
90 struct ifnet *
91 ifnet_byindex_locked(u_short idx)
93 struct ifnet *ifp;
95 ifp = gDevices[idx];
97 return (ifp);
101 static void
102 ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp)
104 gDevices[idx] = ifp;
108 static void
109 ifnet_setbyindex(u_short idx, struct ifnet *ifp)
111 IFNET_WLOCK();
112 ifnet_setbyindex_locked(idx, ifp);
113 IFNET_WUNLOCK();
117 static int
118 ifindex_alloc_locked(u_short *idxp)
120 u_short index;
122 for (index = 0; index < MAX_DEVICES; index++) {
123 if (gDevices[index] == NULL) {
124 break;
128 if (index == MAX_DEVICES)
129 return ENOSPC;
131 gDeviceCount++;
132 *idxp = index;
134 return ENOERR;
138 static void
139 ifindex_free_locked(u_short idx)
141 gDevices[idx] = NULL;
142 gDeviceCount--;
146 struct ifnet *
147 if_alloc(u_char type)
149 char semName[64];
150 u_short index;
152 struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO);
153 if (ifp == NULL)
154 return NULL;
156 snprintf(semName, sizeof(semName), "%s receive", gDriverName);
158 ifp->receive_sem = create_sem(0, semName);
159 if (ifp->receive_sem < B_OK)
160 goto err1;
162 switch (type) {
163 case IFT_ETHER:
165 ifp->if_l2com = _kernel_malloc(sizeof(struct arpcom), M_ZERO);
166 if (ifp->if_l2com == NULL)
167 goto err2;
168 IFP2AC(ifp)->ac_ifp = ifp;
169 break;
171 case IFT_IEEE80211:
173 if (wlan_if_l2com_alloc(ifp) != B_OK)
174 goto err2;
175 break;
179 ifp->link_state_sem = -1;
180 ifp->open_count = 0;
181 ifp->flags = 0;
182 ifp->if_type = type;
183 ifq_init(&ifp->receive_queue, semName);
185 ifp->scan_done_sem = -1;
186 // WLAN specific, doesn't hurt when initilized for other devices
188 // Search for the first free device slot, and use that one
189 IFNET_WLOCK();
190 if (ifindex_alloc_locked(&index) != ENOERR) {
191 IFNET_WUNLOCK();
192 panic("too many devices");
193 goto err3;
195 ifnet_setbyindex_locked(index, IFNET_HOLD);
196 IFNET_WUNLOCK();
198 ifp->if_index = index;
199 ifnet_setbyindex(ifp->if_index, ifp);
201 IF_ADDR_LOCK_INIT(ifp);
202 return ifp;
204 err3:
205 switch (type) {
206 case IFT_ETHER:
207 case IFT_IEEE80211:
208 _kernel_free(ifp->if_l2com);
209 break;
212 err2:
213 delete_sem(ifp->receive_sem);
215 err1:
216 _kernel_free(ifp);
217 return NULL;
221 void
222 if_free(struct ifnet *ifp)
224 // IEEE80211 devices won't be in this list,
225 // so don't try to remove them.
226 if (ifp->if_type == IFT_ETHER)
227 remove_from_device_name_list(ifp);
229 IFNET_WLOCK();
230 ifindex_free_locked(ifp->if_index);
231 IFNET_WUNLOCK();
233 IF_ADDR_LOCK_DESTROY(ifp);
234 switch (ifp->if_type) {
235 case IFT_ETHER:
236 case IFT_IEEE80211:
237 _kernel_free(ifp->if_l2com);
238 break;
241 delete_sem(ifp->receive_sem);
242 ifq_uninit(&ifp->receive_queue);
244 _kernel_free(ifp);
248 void
249 if_initname(struct ifnet *ifp, const char *name, int unit)
251 dprintf("if_initname(%p, %s, %d)\n", ifp, name, unit);
253 if (name == NULL || name[0] == '\0')
254 panic("interface goes unnamed");
256 ifp->if_dname = name;
257 ifp->if_dunit = unit;
259 strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname));
261 snprintf(ifp->device_name, sizeof(ifp->device_name), "net/%s/%i",
262 gDriverName, ifp->if_index);
264 driver_printf("%s: /dev/%s\n", gDriverName, ifp->device_name);
266 // For wlan devices we only want to see the cloned wlan device
267 // in the list.
268 // Remember: For each wlan device, there is a base device of type
269 // IFT_IEEE80211. On top of that a clone device is created of
270 // type IFT_ETHER.
271 // Haiku shall only see the cloned device as it is the one
272 // FreeBSD 8 uses for wireless i/o, too.
273 if (ifp->if_type == IFT_ETHER)
274 insert_into_device_name_list(ifp);
276 ifp->root_device = find_root_device(unit);
280 void
281 ifq_init(struct ifqueue *ifq, const char *name)
283 ifq->ifq_head = NULL;
284 ifq->ifq_tail = NULL;
285 ifq->ifq_len = 0;
286 ifq->ifq_maxlen = IFQ_MAXLEN;
287 ifq->ifq_drops = 0;
289 mtx_init(&ifq->ifq_mtx, name, NULL, MTX_DEF);
293 void
294 ifq_uninit(struct ifqueue *ifq)
296 mtx_destroy(&ifq->ifq_mtx);
300 static int
301 if_transmit(struct ifnet *ifp, struct mbuf *m)
303 int error;
305 IFQ_HANDOFF(ifp, m, error);
306 return (error);
310 void
311 if_attach(struct ifnet *ifp)
313 TAILQ_INIT(&ifp->if_addrhead);
314 TAILQ_INIT(&ifp->if_prefixhead);
315 TAILQ_INIT(&ifp->if_multiaddrs);
317 IF_ADDR_LOCK_INIT(ifp);
319 ifp->if_lladdr.sdl_family = AF_LINK;
321 ifq_init((struct ifqueue *) &ifp->if_snd, ifp->if_xname);
323 if (ifp->if_transmit == NULL) {
324 ifp->if_transmit = if_transmit;
329 void
330 if_detach(struct ifnet *ifp)
332 if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE))
333 taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
335 IF_ADDR_LOCK_DESTROY(ifp);
336 ifq_uninit((struct ifqueue *) &ifp->if_snd);
340 void
341 if_start(struct ifnet *ifp)
343 #ifdef IFF_NEEDSGIANT
344 if (ifp->if_flags & IFF_NEEDSGIANT)
345 panic("freebsd compat.: unsupported giant requirement");
346 #endif
347 ifp->if_start(ifp);
352 if_printf(struct ifnet *ifp, const char *format, ...)
354 char buf[256];
355 va_list vl;
356 va_start(vl, format);
357 vsnprintf(buf, sizeof(buf), format, vl);
358 va_end(vl);
360 dprintf("[%s] %s", ifp->device_name, buf);
361 return 0;
365 void
366 if_link_state_change(struct ifnet *ifp, int linkState)
368 if (ifp->if_link_state == linkState)
369 return;
371 ifp->if_link_state = linkState;
372 release_sem_etc(ifp->link_state_sem, 1, B_DO_NOT_RESCHEDULE);
376 static struct ifmultiaddr *
377 if_findmulti(struct ifnet *ifp, struct sockaddr *_address)
379 struct sockaddr_dl *address = (struct sockaddr_dl *) _address;
380 struct ifmultiaddr *ifma;
382 TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) {
383 if (memcmp(LLADDR(address),
384 LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETHER_ADDR_LEN) == 0)
385 return ifma;
388 return NULL;
393 * if_freemulti: free ifmultiaddr structure and possibly attached related
394 * addresses. The caller is responsible for implementing reference
395 * counting, notifying the driver, handling routing messages, and releasing
396 * any dependent link layer state.
398 static void
399 if_freemulti(struct ifmultiaddr *ifma)
402 KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d",
403 ifma->ifma_refcount));
404 KASSERT(ifma->ifma_protospec == NULL,
405 ("if_freemulti: protospec not NULL"));
407 if (ifma->ifma_lladdr != NULL)
408 free(ifma->ifma_lladdr);
410 // Haiku note: We use a field in the ifmultiaddr struct (ifma_addr_storage)
411 // to store the address and let ifma_addr point to that. We therefore do not
412 // free it here, as it will be freed as part of freeing the if_multiaddr.
413 //free(ifma->ifma_addr);
415 free(ifma);
419 static struct ifmultiaddr *
420 _if_addmulti(struct ifnet *ifp, struct sockaddr *address)
422 struct ifmultiaddr *addr = if_findmulti(ifp, address);
424 if (addr != NULL) {
425 addr->ifma_refcount++;
426 return addr;
429 addr = (struct ifmultiaddr *) malloc(sizeof(struct ifmultiaddr));
430 if (addr == NULL)
431 return NULL;
433 addr->ifma_lladdr = NULL;
434 addr->ifma_ifp = ifp;
435 addr->ifma_protospec = NULL;
437 memcpy(&addr->ifma_addr_storage, address, sizeof(struct sockaddr_dl));
438 addr->ifma_addr = (struct sockaddr *) &addr->ifma_addr_storage;
440 addr->ifma_refcount = 1;
442 TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, addr, ifma_link);
444 return addr;
449 if_addmulti(struct ifnet *ifp, struct sockaddr *address,
450 struct ifmultiaddr **out)
452 struct ifmultiaddr *result;
453 int refcount = 0;
455 IF_ADDR_LOCK(ifp);
456 result = _if_addmulti(ifp, address);
457 if (result)
458 refcount = result->ifma_refcount;
459 IF_ADDR_UNLOCK(ifp);
461 if (result == NULL)
462 return ENOBUFS;
464 if (refcount == 1 && ifp->if_ioctl != NULL)
465 ifp->if_ioctl(ifp, SIOCADDMULTI, NULL);
467 if (out)
468 (*out) = result;
470 return 0;
474 static int
475 if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
477 struct ifmultiaddr *ll_ifma;
479 if (ifp != NULL && ifma->ifma_ifp != NULL) {
480 KASSERT(ifma->ifma_ifp == ifp,
481 ("%s: inconsistent ifp %p", __func__, ifp));
482 IF_ADDR_LOCK_ASSERT(ifp);
485 ifp = ifma->ifma_ifp;
488 * If the ifnet is detaching, null out references to ifnet,
489 * so that upper protocol layers will notice, and not attempt
490 * to obtain locks for an ifnet which no longer exists. The
491 * routing socket announcement must happen before the ifnet
492 * instance is detached from the system.
494 if (detaching) {
495 #ifdef DIAGNOSTIC
496 printf("%s: detaching ifnet instance %p\n", __func__, ifp);
497 #endif
499 * ifp may already be nulled out if we are being reentered
500 * to delete the ll_ifma.
502 if (ifp != NULL) {
503 #ifndef __HAIKU__
504 rt_newmaddrmsg(RTM_DELMADDR, ifma);
505 #endif
506 ifma->ifma_ifp = NULL;
510 if (--ifma->ifma_refcount > 0)
511 return 0;
513 #ifndef __HAIKU__
515 * If this ifma is a network-layer ifma, a link-layer ifma may
516 * have been associated with it. Release it first if so.
518 ll_ifma = ifma->ifma_llifma;
519 if (ll_ifma != NULL) {
520 KASSERT(ifma->ifma_lladdr != NULL,
521 ("%s: llifma w/o lladdr", __func__));
522 if (detaching)
523 ll_ifma->ifma_ifp = NULL; /* XXX */
524 if (--ll_ifma->ifma_refcount == 0) {
525 if (ifp != NULL) {
526 TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma,
527 ifma_link);
529 if_freemulti(ll_ifma);
532 #endif
534 if (ifp != NULL)
535 TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
537 if_freemulti(ifma);
540 * The last reference to this instance of struct ifmultiaddr
541 * was released; the hardware should be notified of this change.
543 return 1;
548 * Delete all multicast group membership for an interface.
549 * Should be used to quickly flush all multicast filters.
551 void
552 if_delallmulti(struct ifnet *ifp)
554 struct ifmultiaddr *ifma;
555 struct ifmultiaddr *next;
557 IF_ADDR_LOCK(ifp);
558 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
559 if_delmulti_locked(ifp, ifma, 0);
560 IF_ADDR_UNLOCK(ifp);
564 static void
565 if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma)
567 TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
568 free(ifma);
573 if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
575 struct ifmultiaddr *ifma;
576 int lastref;
577 #ifdef INVARIANTS
578 struct ifnet *oifp;
580 IFNET_RLOCK_NOSLEEP();
581 TAILQ_FOREACH(oifp, &V_ifnet, if_link)
582 if (ifp == oifp)
583 break;
584 if (ifp != oifp)
585 ifp = NULL;
586 IFNET_RUNLOCK_NOSLEEP();
588 KASSERT(ifp != NULL, ("%s: ifnet went away", __func__));
589 #endif
590 if (ifp == NULL)
591 return (ENOENT);
593 IF_ADDR_LOCK(ifp);
594 lastref = 0;
595 ifma = if_findmulti(ifp, sa);
596 if (ifma != NULL)
597 lastref = if_delmulti_locked(ifp, ifma, 0);
598 IF_ADDR_UNLOCK(ifp);
600 if (ifma == NULL)
601 return (ENOENT);
603 if (lastref && ifp->if_ioctl != NULL) {
604 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
607 return (0);
611 void
612 if_purgemaddrs(struct ifnet *ifp)
614 struct ifmultiaddr *ifma;
615 struct ifmultiaddr *next;
617 IF_ADDR_LOCK(ifp);
618 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
619 if_delmulti_locked(ifp, ifma, 1);
620 IF_ADDR_UNLOCK(ifp);
624 void
625 if_addr_rlock(struct ifnet *ifp)
627 IF_ADDR_LOCK(ifp);
631 void
632 if_addr_runlock(struct ifnet *ifp)
634 IF_ADDR_UNLOCK(ifp);
638 void
639 if_maddr_rlock(struct ifnet *ifp)
641 IF_ADDR_LOCK(ifp);
645 void
646 if_maddr_runlock(struct ifnet *ifp)
648 IF_ADDR_UNLOCK(ifp);
653 ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
654 struct route *ro)
656 int error = 0;
657 IFQ_HANDOFF(ifp, m, error);
658 return error;
662 static void ether_input(struct ifnet *ifp, struct mbuf *m)
664 IF_ENQUEUE(&ifp->receive_queue, m);
665 release_sem_etc(ifp->receive_sem, 1, B_DO_NOT_RESCHEDULE);
669 void
670 ether_ifattach(struct ifnet *ifp, const uint8_t *macAddress)
672 ifp->if_addrlen = ETHER_ADDR_LEN;
673 ifp->if_hdrlen = ETHER_HDR_LEN;
674 if_attach(ifp);
675 ifp->if_mtu = ETHERMTU;
676 ifp->if_output = ether_output;
677 ifp->if_input = ether_input;
678 ifp->if_resolvemulti = NULL; // done in the stack
679 ifp->if_broadcastaddr = etherbroadcastaddr;
681 memcpy(IF_LLADDR(ifp), macAddress, ETHER_ADDR_LEN);
683 // TODO: according to FreeBSD's if_ethersubr.c, this should be removed
684 // once all drivers are cleaned up.
685 if (macAddress != IFP2ENADDR(ifp))
686 memcpy(IFP2ENADDR(ifp), macAddress, ETHER_ADDR_LEN);
690 void
691 ether_ifdetach(struct ifnet *ifp)
693 if_detach(ifp);
698 ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
700 struct ifreq *ifr = (struct ifreq *) data;
702 switch (command) {
703 case SIOCSIFMTU:
704 if (ifr->ifr_mtu > ETHERMTU)
705 return EINVAL;
706 else
708 // need to fix our ifreq to work with C...
709 // ifp->ifr_mtu = ifr->ifr_mtu;
710 break;
712 default:
713 return EINVAL;
716 return 0;
720 void
721 if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc)
723 switch (cnt) {
724 case IFCOUNTER_IPACKETS:
725 atomic_add(&ifp->if_ipackets, inc);
726 break;
727 case IFCOUNTER_IERRORS:
728 atomic_add(&ifp->if_ierrors, inc);
729 break;
730 case IFCOUNTER_OPACKETS:
731 atomic_add(&ifp->if_opackets, inc);
732 break;
733 case IFCOUNTER_OERRORS:
734 atomic_add(&ifp->if_oerrors, inc);
735 break;
736 case IFCOUNTER_COLLISIONS:
737 atomic_add(&ifp->if_collisions, inc);
738 break;
739 case IFCOUNTER_IBYTES:
740 atomic_add(&ifp->if_ibytes, inc);
741 break;
742 case IFCOUNTER_OBYTES:
743 atomic_add(&ifp->if_obytes, inc);
744 break;
745 case IFCOUNTER_IMCASTS:
746 atomic_add(&ifp->if_imcasts, inc);
747 break;
748 case IFCOUNTER_OMCASTS:
749 atomic_add(&ifp->if_omcasts, inc);
750 break;
751 case IFCOUNTER_IQDROPS:
752 atomic_add(&ifp->if_iqdrops, inc);
753 break;
754 case IFCOUNTER_OQDROPS:
755 atomic_add(&ifp->if_oqdrops, inc);
756 break;
757 case IFCOUNTER_NOPROTO:
758 atomic_add(&ifp->if_noproto, inc);
759 break;
760 case IFCOUNTERS:
761 KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));