diff options
Diffstat (limited to 'sys/netgraph')
| -rw-r--r-- | sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c | 3 | ||||
| -rw-r--r-- | sys/netgraph/ng_device.c | 126 | 
2 files changed, 123 insertions, 6 deletions
| diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c index 0181a67ac604..f35712cc8f69 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c @@ -81,9 +81,6 @@ const STRUCT_USB_HOST_ID ubt_rtl_devs[] =  	{ USB_VPI(0x0bda, 0xb00c, 0) },  	{ USB_VPI(0x0bda, 0xc822, 0) }, -	/* Realtek 8822CU Bluetooth devices */ -	{ USB_VPI(0x13d3, 0x3549, 0) }, -  	/* Realtek 8851BE Bluetooth devices */  	{ USB_VPI(0x13d3, 0x3600, 0) }, diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c index 582f877ff3ed..066e3be29694 100644 --- a/sys/netgraph/ng_device.c +++ b/sys/netgraph/ng_device.c @@ -3,6 +3,7 @@   *   * Copyright (c) 2002 Mark Santcroos <marks@ripe.net>   * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org> + * Copyright (c) 2025 Quentin Thébault <quentin.thebault@defenso.fr>   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -50,6 +51,7 @@  #include <sys/poll.h>  #include <sys/proc.h>  #include <sys/queue.h> +#include <sys/selinfo.h>  #include <sys/socket.h>  #include <sys/syslog.h>  #include <sys/uio.h> @@ -117,12 +119,15 @@ struct ngd_private {  	struct	ng_node	*node;  	struct	ng_hook	*hook;  	struct	cdev	*ngddev; +	struct  selinfo rsel; +	struct  selinfo wsel;  	struct	mtx	ngd_mtx;  	int 		unit;  	int		ether_align;  	uint16_t	flags;  #define	NGDF_OPEN	0x0001  #define	NGDF_RWAIT	0x0002 +#define	NGDF_DYING	0x0004  };  typedef struct ngd_private *priv_p; @@ -138,6 +143,24 @@ static d_read_t ngdread;  static d_write_t ngdwrite;  static d_ioctl_t ngdioctl;  static d_poll_t ngdpoll; +static d_kqfilter_t ngdkqfilter; + +static int      ngd_kqread_event(struct knote *, long); +static int      ngd_kqwrite_event(struct knote *, long); +static void     ngd_kqread_detach(struct knote *); +static void     ngd_kqwrite_detach(struct knote *); + +static const struct filterops ngd_read_filterops = { +	.f_isfd =   1, +	.f_detach = ngd_kqread_detach, +	.f_event =  ngd_kqread_event +}; + +static const struct filterops ngd_write_filterops = { +	.f_isfd =   1, +	.f_detach = ngd_kqwrite_detach, +	.f_event =  ngd_kqwrite_event +};  static struct cdevsw ngd_cdevsw = {  	.d_version =	D_VERSION, @@ -146,6 +169,7 @@ static struct cdevsw ngd_cdevsw = {  	.d_read =	ngdread,  	.d_write =	ngdwrite,  	.d_ioctl =	ngdioctl, +	.d_kqfilter =   ngdkqfilter,  	.d_poll =	ngdpoll,  	.d_name =	NG_DEVICE_DEVNAME,  }; @@ -198,6 +222,9 @@ ng_device_constructor(node_p node)  	mtx_init(&priv->readq.ifq_mtx, "ng_device queue", NULL, MTX_DEF);  	IFQ_SET_MAXLEN(&priv->readq, ifqmaxlen); +	knlist_init_mtx(&priv->rsel.si_note, &priv->ngd_mtx); +	knlist_init_mtx(&priv->wsel.si_note, &priv->ngd_mtx); +  	/* Link everything together */  	NG_NODE_SET_PRIVATE(node, priv);  	priv->node = node; @@ -206,6 +233,8 @@ ng_device_constructor(node_p node)  	    GID_WHEEL, 0600, NG_DEVICE_DEVNAME "%d", priv->unit);  	if (priv->ngddev == NULL) {  		printf("%s(): make_dev() failed\n", __func__); +		knlist_destroy(&priv->rsel.si_note); +		knlist_destroy(&priv->wsel.si_note);  		mtx_destroy(&priv->ngd_mtx);  		mtx_destroy(&priv->readq.ifq_mtx);  		free_unr(ngd_unit, priv->unit); @@ -319,6 +348,8 @@ ng_device_rcvdata(hook_p hook, item_p item)  		priv->flags &= ~NGDF_RWAIT;  		wakeup(priv);  	} +	selwakeup(&priv->rsel); +	KNOTE_LOCKED(&priv->rsel.si_note, 0);  	mtx_unlock(&priv->ngd_mtx);  	return (0); @@ -334,9 +365,22 @@ ng_device_disconnect(hook_p hook)  	DBG; +	mtx_lock(&priv->ngd_mtx); +	priv->flags |= NGDF_DYING; +	wakeup(priv); +	mtx_unlock(&priv->ngd_mtx); +  	destroy_dev(priv->ngddev); + +	knlist_clear(&priv->rsel.si_note, 0); +	knlist_clear(&priv->wsel.si_note, 0); +	knlist_destroy(&priv->rsel.si_note); +	knlist_destroy(&priv->wsel.si_note);  	mtx_destroy(&priv->ngd_mtx); +	seldrain(&priv->rsel); +	seldrain(&priv->wsel); +  	IF_DRAIN(&priv->readq);  	mtx_destroy(&(priv)->readq.ifq_mtx); @@ -493,9 +537,13 @@ ngdread(struct cdev *dev, struct uio *uio, int flag)  				return (EWOULDBLOCK);  			mtx_lock(&priv->ngd_mtx);  			priv->flags |= NGDF_RWAIT; -			if ((error = msleep(priv, &priv->ngd_mtx, -			    PDROP | PCATCH | PZERO, -			    "ngdread", 0)) != 0) +			if (priv->flags & NGDF_DYING) { +				mtx_unlock(&priv->ngd_mtx); +				error = ENXIO; +			} else +				error = mtx_sleep(priv, &priv->ngd_mtx, +				    PDROP | PCATCH, "ngdread", 0); +			if (error != 0)  				return (error);  		}  	} while (m == NULL); @@ -538,9 +586,12 @@ ngdwrite(struct cdev *dev, struct uio *uio, int flag)  	if (m == NULL)  		return (ENOBUFS); +	/* Setting VNET is required if connecting to a ng_bridge. */ +	CURVNET_SET(priv->node->nd_vnet);  	NET_EPOCH_ENTER(et);  	NG_SEND_DATA_ONLY(error, priv->hook, m);  	NET_EPOCH_EXIT(et); +	CURVNET_RESTORE();  	return (error);  } @@ -561,3 +612,72 @@ ngdpoll(struct cdev *dev, int events, struct thread *td)  	return (revents);  } + +static void +ngd_kqread_detach(struct knote *kn) +{ +	priv_p  priv = (priv_p)kn->kn_hook; + +	knlist_remove(&priv->rsel.si_note, kn, 0); +} + +static int +ngd_kqread_event(struct knote *kn, long hint) +{ +	priv_p priv = (priv_p)kn->kn_hook; +	struct mbuf *m; + +	IFQ_LOCK(&priv->readq); +	if (IFQ_IS_EMPTY(&priv->readq)) { +		kn->kn_data = 0; +	} else { +		/* +		 * Since the queue does not store the total number of bytes that +		 * could be read across all packets and we do not want to +		 * traverse the whole queue, we only report the number of bytes +		 * for the first packet in the queue. +		 */ +		IF_POLL(&priv->readq, m); +		kn->kn_data = m->m_len; +	} +	IFQ_UNLOCK(&priv->readq); + +	return (kn->kn_data > 0); +} + +static void +ngd_kqwrite_detach(struct knote *kn) +{ +	priv_p  priv = (priv_p)kn->kn_hook; + +	knlist_remove(&priv->wsel.si_note, kn, 0); +} + +static int +ngd_kqwrite_event(struct knote *kn, long hint) +{ +	kn->kn_data = IP_MAXPACKET; + +	return (1); +} + +static int +ngdkqfilter(struct cdev *dev, struct knote *kn) +{ +	priv_p priv = (priv_p)dev->si_drv1; + +	switch (kn->kn_filter) { +	case EVFILT_READ: +		kn->kn_fop = &ngd_read_filterops; +		kn->kn_hook = priv; +		knlist_add(&priv->rsel.si_note, kn, 0); +		return (0); +	case EVFILT_WRITE: +		kn->kn_fop = &ngd_write_filterops; +		kn->kn_hook = priv; +		knlist_add(&priv->wsel.si_note, kn, 0); +		return (0); +	default: +		return (EINVAL); +	} +} | 
