From 3e9b338ea7240c7e7cba1edc46584050d2d7634d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 18 Mar 2009 16:36:51 +0000 Subject: [PATCH] * Applied cleaned patch by Adrian: the gDevices[] can now have empty entries, the gDeviceNameList[] entries are no longer in the same order. * This fixes bug #3124. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29593 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/libs/compat/freebsd_network/device.c | 12 ++-- src/libs/compat/freebsd_network/if.c | 77 +++++++++++++++++++++--- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c index cb9e761865..b01aa591bb 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -1,6 +1,6 @@ /* + * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de. * Copyright 2007, Hugo Santos. All Rights Reserved. - * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2004, Marcus Overhagen. All Rights Reserved. * * Distributed under the terms of the MIT License. @@ -28,12 +28,12 @@ compat_open(const char *name, uint32 flags, void **cookie) struct ifreq ifr; int i; - for (i = 0; gDeviceNameList[i] != NULL; i++) { - if (strcmp(gDeviceNameList[i], name) == 0) + for (i = 0; i < MAX_DEVICES; i++) { + if (gDevices[i] != NULL && !strcmp(gDevices[i]->device_name, name)) break; } - if (gDeviceNameList[i] == NULL) + if (i == MAX_DEVICES) return B_ERROR; if (get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack) != B_OK) @@ -85,7 +85,7 @@ compat_free(void *cookie) if_printf(ifp, "compat_free()\n"); - /* TODO: empty out the send queue */ + // TODO: empty out the send queue atomic_and(&ifp->open_count, 0); put_module(NET_STACK_MODULE_NAME); @@ -161,7 +161,7 @@ compat_write(void *cookie, off_t position, const void *buffer, if (mb == NULL) return ENOBUFS; - /* if we waited, check after if the ifp is still valid */ + // if we waited, check after if the ifp is still valid mb->m_pkthdr.len = mb->m_len = min_c(*numBytes, (size_t)MCLBYTES); memcpy(mtod(mb, void *), buffer, mb->m_len); diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index 757524cfc5..b2f88a0166 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -1,6 +1,6 @@ /* + * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de. * Copyright 2007, Hugo Santos. All Rights Reserved. - * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2004, Marcus Overhagen. All Rights Reserved. * * Distributed under the terms of the MIT License. @@ -24,10 +24,52 @@ #include +static void +insert_into_device_name_list(struct ifnet* ifp) +{ + int i; + for (i = 0; i < MAX_DEVICES; i++) { + if (gDeviceNameList[i] == NULL) { + gDeviceNameList[i] = ifp->device_name; + return; + } + } + + panic("too many devices"); +} + + +static void +remove_from_device_name_list(struct ifnet* ifp) +{ + int i; + for (i = 0; i < MAX_DEVICES; i++) { + if (ifp->device_name == gDeviceNameList[i]) { + int last; + for (last = i + 1; last < MAX_DEVICES; last++) { + if (gDeviceNameList[last] == NULL) + break; + } + last--; + + if (i == last) + gDeviceNameList[i] = NULL; + else { + // switch positions with the last entry + gDeviceNameList[i] = gDeviceNameList[last]; + gDeviceNameList[last] = NULL; + } + break; + } + } +} + + struct ifnet * if_alloc(u_char type) { char semName[64]; + int i; struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO); if (ifp == NULL) @@ -50,9 +92,24 @@ if_alloc(u_char type) ifp->link_state_sem = -1; ifp->open_count = 0; ifp->flags = 0; + ifp->if_type = type; ifq_init(&ifp->receive_queue, semName); - ifp->if_type = type; + // Search for the first free device slot, and use that one + for (i = 0; i < MAX_DEVICES; i++) { + if (gDevices[i] == NULL) { + ifp->if_index = i; + gDevices[i] = ifp; + gDeviceCount++; + break; + } + } + + if (i == MAX_DEVICES) { + panic("too many devices"); + return NULL; + } + IF_ADDR_LOCK_INIT(ifp); return ifp; @@ -67,6 +124,11 @@ err1: void if_free(struct ifnet *ifp) { + remove_from_device_name_list(ifp); + + gDevices[ifp->if_index] = NULL; + gDeviceCount--; + IF_ADDR_LOCK_DESTROY(ifp); if (ifp->if_type == IFT_ETHER) _kernel_free(ifp->if_l2com); @@ -83,15 +145,11 @@ if_initname(struct ifnet *ifp, const char *name, int unit) { dprintf("if_initname(%p, %s, %d)\n", ifp, name, unit); - if (name == NULL) - panic("interface goes unamed"); - - if (gDeviceCount >= MAX_DEVICES) - panic("unit too large"); + if (name == NULL || name[0] == '\0') + panic("interface goes unnamed"); ifp->if_dname = name; ifp->if_dunit = unit; - ifp->if_index = gDeviceCount++; strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname)); @@ -100,8 +158,7 @@ if_initname(struct ifnet *ifp, const char *name, int unit) driver_printf("%s: /dev/%s\n", gDriverName, ifp->device_name); - gDeviceNameList[ifp->if_index] = ifp->device_name; - gDevices[ifp->if_index] = ifp; + insert_into_device_name_list(ifp); ifp->root_device = find_root_device(unit); }