diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 3686985433..af4b17df51 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -25,6 +25,7 @@ KernelStaticLibrary libfreebsd_network.a : fbsd_subr_bufring.c fbsd_subr_sbuf.c fbsd_time.c + fbsd_timingsafe.c fbsd_usb_error.c fbsd_usb_util.c fbsd_usb_lookup.c diff --git a/src/libs/compat/freebsd_network/bus.cpp b/src/libs/compat/freebsd_network/bus.cpp index e6553eb468..08dfa926ec 100644 --- a/src/libs/compat/freebsd_network/bus.cpp +++ b/src/libs/compat/freebsd_network/bus.cpp @@ -297,6 +297,23 @@ rman_get_virtual(struct resource *res) } +bus_addr_t +rman_get_start(struct resource *res) +{ + return res->r_bushandle; +} + + +bus_size_t +rman_get_size(struct resource *res) +{ + area_info info; + if (get_area_info(res->r_mapped_area, &info) != B_OK) + return 0; + return info.size; +} + + // #pragma mark - Interrupt handling @@ -329,7 +346,13 @@ intr_handler(void *data) //device_printf(intr->dev, "in soft interrupt handler.\n"); atomic_or(&intr->handling, 1); + if ((intr->flags & INTR_MPSAFE) == 0) + mtx_lock(&Giant); + intr->handler(intr->arg); + + if ((intr->flags & INTR_MPSAFE) == 0) + mtx_unlock(&Giant); atomic_and(&intr->handling, 0); HAIKU_REENABLE_INTERRUPTS(intr->dev); } @@ -355,8 +378,6 @@ int bus_setup_intr(device_t dev, struct resource *res, int flags, driver_filter_t* filter, driver_intr_t handler, void *arg, void **_cookie) { - /* TODO check MPSAFE etc */ - struct internal_intr *intr = (struct internal_intr *)malloc( sizeof(struct internal_intr)); char semName[64]; diff --git a/src/libs/compat/freebsd_network/clock.c b/src/libs/compat/freebsd_network/clock.c index 29ae4107da..0ad0301692 100644 --- a/src/libs/compat/freebsd_network/clock.c +++ b/src/libs/compat/freebsd_network/clock.c @@ -5,6 +5,7 @@ #include #include +#include int32_t @@ -12,3 +13,12 @@ _get_ticks() { return USEC_2_TICKS(system_time()); } + + +void +getmicrouptime(struct timeval *tvp) +{ + bigtime_t usecs = system_time(); + tvp->tv_sec = usecs / 1000000; + tvp->tv_usec = usecs % 1000000; +} diff --git a/src/libs/compat/freebsd_network/compat/net/if.h b/src/libs/compat/freebsd_network/compat/net/if.h index a495512ec8..7f5aba8508 100644 --- a/src/libs/compat/freebsd_network/compat/net/if.h +++ b/src/libs/compat/freebsd_network/compat/net/if.h @@ -70,6 +70,7 @@ #define IFF_MONITOR 0x00400000 /* (n) user-requested monitor mode */ #define IFF_PPROMISC 0x00800000 /* (n) user-requested promisc mode */ #define IFF_NOGROUP 0x01000000 /* (n) interface is not part of any groups */ +#define IFF_NEEDSGIANT 0x02000000 /* (i) hold Giant over hook calls (OpenBSD compatibility) */ #define LINK_STATE_UNKNOWN 0 #define LINK_STATE_DOWN 1 diff --git a/src/libs/compat/freebsd_network/compat/net/if_var.h b/src/libs/compat/freebsd_network/compat/net/if_var.h index fe1a0dcffa..5d880e7f6e 100644 --- a/src/libs/compat/freebsd_network/compat/net/if_var.h +++ b/src/libs/compat/freebsd_network/compat/net/if_var.h @@ -258,7 +258,6 @@ struct ifnet { void *if_afdata[AF_MAX]; int if_afdata_initialized; struct mtx if_afdata_mtx; - struct task if_starttask; /* task for IFF_NEEDSGIANT */ struct task if_linktask; /* task for link change events */ struct mtx if_addr_mtx; /* mutex to protect address lists */ @@ -752,6 +751,10 @@ int ifioctl(struct socket *, u_long, caddr_t, struct thread *); int ifpromisc(struct ifnet *, int); struct ifnet *ifunit(const char *); +/* Haiku extension for OpenBSD compat */ +int if_alloc_inplace(struct ifnet *ifp, u_char type); +void if_free_inplace(struct ifnet *ifp); + struct ifaddr *ifa_ifwithaddr(struct sockaddr *); struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *); struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); diff --git a/src/libs/compat/freebsd_network/compat/sys/_task.h b/src/libs/compat/freebsd_network/compat/sys/_task.h index 6ce6c552ff..d50ee8a88f 100644 --- a/src/libs/compat/freebsd_network/compat/sys/_task.h +++ b/src/libs/compat/freebsd_network/compat/sys/_task.h @@ -13,12 +13,17 @@ typedef void (*task_fn_t)(void *context, int pending); struct task { + int ta_pending; int ta_priority; + int ta_flags; task_fn_t ta_handler; void *ta_argument; - int ta_pending; struct list_link ta_link; }; + +#define TASK_NEEDSGIANT (1 << 0) /* Haiku extension, OpenBSD compatibility */ + + #endif diff --git a/src/libs/compat/freebsd_network/compat/sys/buf_ring.h b/src/libs/compat/freebsd_network/compat/sys/buf_ring.h index b6c573fe67..bd58b96074 100644 --- a/src/libs/compat/freebsd_network/compat/sys/buf_ring.h +++ b/src/libs/compat/freebsd_network/compat/sys/buf_ring.h @@ -269,7 +269,7 @@ buf_ring_advance_sc(struct buf_ring *br) static __inline void buf_ring_putback_sc(struct buf_ring *br, void *_new) { - KASSERT(br->br_cons_head != br->br_prod_tail, + KASSERT_FREEBSD(br->br_cons_head != br->br_prod_tail, ("Buf-Ring has none in putback")) ; br->br_ring[br->br_cons_head] = _new; } diff --git a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h index 14f5a6bbeb..7f6164ebca 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -207,8 +207,11 @@ enum { FBSD_SWI_TASKQUEUE = 1 << 2, FBSD_THREAD_TASKQUEUE = 1 << 3, FBSD_WLAN_FEATURE = 1 << 4, + FBSD_WLAN = FBSD_WLAN_FEATURE | FBSD_TASKQUEUES | FBSD_THREAD_TASKQUEUE, + OBSD_WLAN = FBSD_WLAN_FEATURE | FBSD_TASKQUEUES + | FBSD_FAST_TASKQUEUE, }; #define HAIKU_DRIVER_REQUIREMENTS(flags) \ diff --git a/src/libs/compat/freebsd_network/compat/sys/libkern.h b/src/libs/compat/freebsd_network/compat/sys/libkern.h index 52aac7a2e3..9517aec378 100644 --- a/src/libs/compat/freebsd_network/compat/sys/libkern.h +++ b/src/libs/compat/freebsd_network/compat/sys/libkern.h @@ -16,6 +16,9 @@ extern int random(void); u_int read_random(void *, u_int); void arc4rand(void *ptr, u_int len, int reseed); uint32_t arc4random(void); +void arc4random_buf(void *ptr, size_t len); + +int timingsafe_bcmp(const void *, const void *, size_t); static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); } diff --git a/src/libs/compat/freebsd_network/compat/sys/malloc.h b/src/libs/compat/freebsd_network/compat/sys/malloc.h index 7d211a758a..c98bc25aa6 100644 --- a/src/libs/compat/freebsd_network/compat/sys/malloc.h +++ b/src/libs/compat/freebsd_network/compat/sys/malloc.h @@ -43,7 +43,7 @@ void _kernel_contigfree(void *addr, unsigned long size); #define kernel_malloc(size, base, flags) \ _kernel_malloc(size, flags) -#define kernel_free(ptr, base) \ +#define kernel_free(ptr, tag) \ _kernel_free(ptr) #define kernel_contigmalloc(size, type, flags, low, high, alignment, boundary) \ diff --git a/src/libs/compat/freebsd_network/compat/sys/mbuf-fbsd.h b/src/libs/compat/freebsd_network/compat/sys/mbuf-fbsd.h index c970bd3ed1..327bf45412 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mbuf-fbsd.h +++ b/src/libs/compat/freebsd_network/compat/sys/mbuf-fbsd.h @@ -212,6 +212,16 @@ m_cljset(struct mbuf *m, void *cl, int type) m->m_flags |= M_EXT; } +/* These are for OpenBSD compatibility. */ +#define MTAG_ABI_COMPAT 0 /* compatibility ABI */ + +static __inline struct m_tag * +m_tag_find(struct mbuf *m, uint16_t type, struct m_tag *start) +{ + return (SLIST_EMPTY(&m->m_pkthdr.tags) ? (struct m_tag *)NULL : + m_tag_locate(m, MTAG_ABI_COMPAT, type, start)); +} + /* mbufq */ struct mbufq { diff --git a/src/libs/compat/freebsd_network/compat/sys/mbuf.h b/src/libs/compat/freebsd_network/compat/sys/mbuf.h index 3397297228..0f8aa922d8 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mbuf.h +++ b/src/libs/compat/freebsd_network/compat/sys/mbuf.h @@ -215,6 +215,12 @@ struct pkthdr { uint8_t rsstype; /* hash type */ uint16_t tso_segsz; uint16_t ether_vtag; + + /* Layer specific non-persistent local storage for reassembly, etc. */ + union { + uintptr_t unintptr[1]; + void* ptr; + } PH_loc; }; struct m_tag { diff --git a/src/libs/compat/freebsd_network/compat/sys/rman.h b/src/libs/compat/freebsd_network/compat/sys/rman.h index b03dd57e67..46fc64293b 100644 --- a/src/libs/compat/freebsd_network/compat/sys/rman.h +++ b/src/libs/compat/freebsd_network/compat/sys/rman.h @@ -1,9 +1,3 @@ -/* - * Copyright 2007, Hugo Santos. All Rights Reserved. - * Distributed under the terms of the MIT License. - */ - - /*- * Copyright 1998 Massachusetts Institute of Technology * @@ -61,30 +55,7 @@ bus_space_handle_t rman_get_bushandle(struct resource *); bus_space_tag_t rman_get_bustag(struct resource *); int rman_get_rid(struct resource *); void* rman_get_virtual(struct resource *); +bus_addr_t rman_get_start(struct resource *); +bus_size_t rman_get_size(struct resource *); - -static inline u_long -rman_get_start(struct resource *resourcePointer) -{ - return resourcePointer->r_bushandle; -} - - -static inline uint32_t -rman_make_alignment_flags(uint32_t size) -{ - int i; - - /* - * Find the hightest bit set, and add one if more than one bit - * set. We're effectively computing the ceil(log2(size)) here. - */ - for (i = 31; i > 0; i--) - if ((1 << i) & size) - break; - if (~(1 << i) & size) - i++; - - return RF_ALIGNMENT_LOG2(i); -} #endif /* _FBSD_COMPAT_SYS_RMAN_H_ */ diff --git a/src/libs/compat/freebsd_network/compat/sys/syslog.h b/src/libs/compat/freebsd_network/compat/sys/syslog.h index f785d64b35..ec0ccfd7f4 100644 --- a/src/libs/compat/freebsd_network/compat/sys/syslog.h +++ b/src/libs/compat/freebsd_network/compat/sys/syslog.h @@ -1,5 +1,5 @@ /* - * Copyright 2009 Haiku Inc. All rights reserved. + * Copyright 2009-2022, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _FBSD_COMPAT_SYS_SYSLOG_H_ @@ -7,5 +7,7 @@ #define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ + #endif /* _FBSD_COMPAT_SYS_SYSLOG_H_ */ diff --git a/src/libs/compat/freebsd_network/compat/sys/systm.h b/src/libs/compat/freebsd_network/compat/sys/systm.h index b4d3b113a9..219db6d2ed 100644 --- a/src/libs/compat/freebsd_network/compat/sys/systm.h +++ b/src/libs/compat/freebsd_network/compat/sys/systm.h @@ -41,13 +41,14 @@ int printf(const char *format, ...) __printflike(1, 2); #endif #ifdef INVARIANTS -#define KASSERT(cond,msg) do { \ +#define KASSERT_FREEBSD(cond,msg) do { \ if (!(cond)) \ panic msg; \ } while (0) +#define KASSERT(cond,msg) KASSERT_FREEBSD(cond,msg) #else -#define KASSERT(exp,msg) do { \ -} while (0) +#define KASSERT_FREEBSD(exp,msg) do {} while (0) +#define KASSERT(cond,msg) KASSERT_FREEBSD(cond,msg) #endif #define DELAY(n) \ diff --git a/src/libs/compat/freebsd_network/compat/sys/time.h b/src/libs/compat/freebsd_network/compat/sys/time.h index 14265f44dd..869401926d 100644 --- a/src/libs/compat/freebsd_network/compat/sys/time.h +++ b/src/libs/compat/freebsd_network/compat/sys/time.h @@ -1,6 +1,39 @@ /* - * Copyright 2020, Haiku, Inc. All rights reserved. - * All rights reserved. Distributed under the terms of the MIT License. + * Copyright 2020-2022, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.5 (Berkeley) 5/4/95 + * $FreeBSD$ */ #ifndef _FBSD_COMPAT_SYS_TIME_H_ #define _FBSD_COMPAT_SYS_TIME_H_ @@ -21,7 +54,21 @@ #define time_uptime USEC_2_TICKS(system_time()) -int ppsratecheck(struct timeval*, int*, int); +/* Operations on timevals. */ +#define timevalclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) +#define timevalisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timevalcmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) + + +void getmicrouptime(struct timeval *tvp); + +int ppsratecheck(struct timeval *, int *, int); +int ratecheck(struct timeval *, const struct timeval *); +void timevaladd(struct timeval *t1, const struct timeval *t2); +void timevalsub(struct timeval *t1, const struct timeval *t2); #endif /* _FBSD_COMPAT_SYS_TIME_H_ */ diff --git a/src/libs/compat/freebsd_network/device_hooks.c b/src/libs/compat/freebsd_network/device_hooks.c index 37165fda42..d62097b127 100644 --- a/src/libs/compat/freebsd_network/device_hooks.c +++ b/src/libs/compat/freebsd_network/device_hooks.c @@ -49,6 +49,8 @@ compat_open(const char *name, uint32 flags, void **cookie) return B_BUSY; } + IFF_LOCKGIANT(ifp); + ifp->if_init(ifp->if_softc); if (!HAIKU_DRIVER_REQUIRES(FBSD_WLAN_FEATURE)) { @@ -68,6 +70,8 @@ compat_open(const char *name, uint32 flags, void **cookie) ifp->flags &= ~DEVICE_CLOSED; ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); + IFF_UNLOCKGIANT(ifp); + *cookie = ifp; return B_OK; } @@ -184,7 +188,11 @@ compat_write(void *cookie, off_t position, const void *buffer, memcpy(mtod(mb, void *), buffer, mb->m_len); *numBytes = length; - return ifp->if_output(ifp, mb, NULL, NULL); + IFF_LOCKGIANT(ifp); + int result = ifp->if_output(ifp, mb, NULL, NULL); + IFF_UNLOCKGIANT(ifp); + + return result; } @@ -192,6 +200,7 @@ static status_t compat_control(void *cookie, uint32 op, void *arg, size_t length) { struct ifnet *ifp = cookie; + status_t status; //if_printf(ifp, "compat_control(op %lu, %p, [%lu])\n", op, // arg, length); @@ -228,7 +237,11 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) ifp->if_flags |= IFF_PROMISC; else ifp->if_flags &= ~IFF_PROMISC; - return ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); + + IFF_LOCKGIANT(ifp); + status = ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); + IFF_UNLOCKGIANT(ifp); + return status; } case ETHER_GETFRAMESIZE: @@ -273,10 +286,13 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) if (user_memcpy(LLADDR(&address), arg, ETHER_ADDR_LEN) < B_OK) return B_BAD_ADDRESS; + IFF_LOCKGIANT(ifp); if (op == ETHER_ADDMULTI) - return if_addmulti(ifp, (struct sockaddr *)&address, NULL); - - return if_delmulti(ifp, (struct sockaddr *)&address); + status = if_addmulti(ifp, (struct sockaddr *)&address, NULL); + else + status = if_delmulti(ifp, (struct sockaddr *)&address); + IFF_UNLOCKGIANT(ifp); + return status; } case ETHER_GET_LINK_STATE: @@ -289,7 +305,9 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) return EINVAL; memset(&mediareq, 0, sizeof(mediareq)); + IFF_LOCKGIANT(ifp); status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, (caddr_t)&mediareq); + IFF_UNLOCKGIANT(ifp); if (status < B_OK) return status; @@ -313,7 +331,12 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) case SIOCSIFMEDIA: case SIOCGIFMEDIA: case SIOCSIFMTU: - return ifp->if_ioctl(ifp, op, (caddr_t)arg); + { + IFF_LOCKGIANT(ifp); + status = ifp->if_ioctl(ifp, op, (caddr_t)arg); + IFF_UNLOCKGIANT(ifp); + return status; + } } return wlan_control(cookie, op, arg, length); diff --git a/src/libs/compat/freebsd_network/fbsd_time.c b/src/libs/compat/freebsd_network/fbsd_time.c index 7ab8fcae72..2c61e96b0d 100644 --- a/src/libs/compat/freebsd_network/fbsd_time.c +++ b/src/libs/compat/freebsd_network/fbsd_time.c @@ -31,6 +31,46 @@ #include #include +/* + * ratecheck(): simple time-based rate-limit checking. + */ +int +ratecheck(struct timeval *lasttime, const struct timeval *mininterval) +{ + struct timeval tv, delta; + int rv = 0; + + getmicrouptime(&tv); /* NB: 10ms precision */ + delta = tv; + timevalsub(&delta, lasttime); + + /* + * check for 0,0 is so that the message will be seen at least once, + * even if interval is huge. + */ + if (timevalcmp(&delta, mininterval, >=) || + (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { + *lasttime = tv; + rv = 1; + } + + return (rv); +} + +/* + * ppsratecheck(): packets (or events) per second limitation. + * + * Return 0 if the limit is to be enforced (e.g. the caller + * should drop a packet because of the rate limitation). + * + * maxpps of 0 always causes zero to be returned. maxpps of -1 + * always causes 1 to be returned; this effectively defeats rate + * limiting. + * + * Note that we maintain the struct timeval for compatibility + * with other bsd systems. We reuse the storage and just monitor + * clock ticks for minimal overhead. + */ int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) { @@ -48,6 +88,45 @@ ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) return (maxpps != 0); } else { (*curpps)++; /* NB: ignore potential overflow */ - return (maxpps < 0 || *curpps < maxpps); + return (maxpps < 0 || *curpps <= maxpps); } } + +static void +timevalfix(struct timeval *t1) +{ + + if (t1->tv_usec < 0) { + t1->tv_sec--; + t1->tv_usec += 1000000; + } + if (t1->tv_usec >= 1000000) { + t1->tv_sec++; + t1->tv_usec -= 1000000; + } +} + +/* + * Add and subtract routines for timevals. + * N.B.: subtract routine doesn't deal with + * results which are before the beginning, + * it just gets very confused in this case. + * Caveat emptor. + */ +void +timevaladd(struct timeval *t1, const struct timeval *t2) +{ + + t1->tv_sec += t2->tv_sec; + t1->tv_usec += t2->tv_usec; + timevalfix(t1); +} + +void +timevalsub(struct timeval *t1, const struct timeval *t2) +{ + + t1->tv_sec -= t2->tv_sec; + t1->tv_usec -= t2->tv_usec; + timevalfix(t1); +} diff --git a/src/libs/compat/freebsd_network/fbsd_timingsafe.c b/src/libs/compat/freebsd_network/fbsd_timingsafe.c new file mode 100644 index 0000000000..fd724157f2 --- /dev/null +++ b/src/libs/compat/freebsd_network/fbsd_timingsafe.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +int +timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ + const unsigned char *p1 = b1, *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +} diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index 3778c3b0a3..b9f347189f 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -149,21 +149,17 @@ ifindex_free_locked(u_short idx) } -struct ifnet * -if_alloc(u_char type) +int +if_alloc_inplace(struct ifnet *ifp, u_char type) { char semName[64]; u_short index; - struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO); - if (ifp == NULL) - return NULL; - snprintf(semName, sizeof(semName), "%s receive", gDriverName); ifp->receive_sem = create_sem(0, semName); if (ifp->receive_sem < B_OK) - goto err1; + return ifp->receive_sem; ifp->link_state_sem = -1; ifp->open_count = 0; @@ -188,7 +184,7 @@ if_alloc(u_char type) ifnet_setbyindex(ifp->if_index, ifp); IF_ADDR_LOCK_INIT(ifp); - return ifp; + return 0; err3: switch (type) { @@ -200,14 +196,28 @@ err3: err2: delete_sem(ifp->receive_sem); -err1: - _kernel_free(ifp); - return NULL; + return -1; +} + + +struct ifnet * +if_alloc(u_char type) +{ + struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO); + if (ifp == NULL) + return NULL; + + if (if_alloc_inplace(ifp, type) != 0) { + _kernel_free(ifp); + return NULL; + } + + return ifp; } void -if_free(struct ifnet *ifp) +if_free_inplace(struct ifnet *ifp) { // IEEE80211 devices won't be in this list, // so don't try to remove them. @@ -227,6 +237,13 @@ if_free(struct ifnet *ifp) delete_sem(ifp->receive_sem); ifq_uninit(&ifp->receive_queue); +} + + +void +if_free(struct ifnet *ifp) +{ + if_free_inplace(ifp); _kernel_free(ifp); } @@ -397,10 +414,6 @@ if_detach(struct ifnet *ifp) void if_start(struct ifnet *ifp) { -#ifdef IFF_NEEDSGIANT - if (ifp->if_flags & IFF_NEEDSGIANT) - panic("freebsd compat.: unsupported giant requirement"); -#endif ifp->if_start(ifp); } diff --git a/src/libs/compat/freebsd_network/libkern.cpp b/src/libs/compat/freebsd_network/libkern.cpp index adeb122a05..1d6afe8a2e 100644 --- a/src/libs/compat/freebsd_network/libkern.cpp +++ b/src/libs/compat/freebsd_network/libkern.cpp @@ -1,6 +1,5 @@ /* - * Copyright 2009, Colin Günther, coling@gmx.de. All rights reserved. - * Copyright 2018, Haiku, Inc. All rights reserved. + * Copyright 2018-2022, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -36,3 +35,10 @@ arc4random(void) arc4rand(&ret, sizeof ret, 0); return ret; } + + +void +arc4random_buf(void *ptr, size_t len) +{ + arc4rand(ptr, len, 0); +} diff --git a/src/libs/compat/freebsd_network/taskqueue.c b/src/libs/compat/freebsd_network/taskqueue.c index b6cb0e11cd..7ed80a2b78 100644 --- a/src/libs/compat/freebsd_network/taskqueue.c +++ b/src/libs/compat/freebsd_network/taskqueue.c @@ -127,7 +127,13 @@ tq_handle_thread(void *data) pending = t->ta_pending; t->ta_pending = 0; + if ((t->ta_flags & TASK_NEEDSGIANT) != 0) + mtx_lock(&Giant); + t->ta_handler(t->ta_argument, pending); + + if ((t->ta_flags & TASK_NEEDSGIANT) != 0) + mtx_unlock(&Giant); } return 0; @@ -489,6 +495,7 @@ void task_init(struct task *task, int prio, task_fn_t handler, void *context) { task->ta_priority = prio; + task->ta_flags = 0; task->ta_handler = handler; task->ta_argument = context; task->ta_pending = 0;