aboutsummaryrefslogtreecommitdiff
path: root/sys/netgraph
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c3
-rw-r--r--sys/netgraph/bluetooth/include/ng_hci.h2
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c4
-rw-r--r--sys/netgraph/netflow/netflow.c6
-rw-r--r--sys/netgraph/ng_device.c232
-rw-r--r--sys/netgraph/ng_nat.c95
-rw-r--r--sys/netgraph/ng_parse.c4
-rw-r--r--sys/netgraph/ng_tty.c6
8 files changed, 259 insertions, 93 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/bluetooth/include/ng_hci.h b/sys/netgraph/bluetooth/include/ng_hci.h
index 44a14e62f4ed..ce3291770740 100644
--- a/sys/netgraph/bluetooth/include/ng_hci.h
+++ b/sys/netgraph/bluetooth/include/ng_hci.h
@@ -448,7 +448,7 @@ typedef struct {
typedef bdaddr_t * bdaddr_p;
/* Any BD_ADDR. Note: This is actually 7 bytes (count '\0' terminator) */
-#define NG_HCI_BDADDR_ANY ((bdaddr_p) "\000\000\000\000\000\000")
+#define NG_HCI_BDADDR_ANY (&(const bdaddr_t){"\000\000\000\000\000\000"})
/* HCI status return parameter */
typedef struct {
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
index 6c0a6fda1fb1..73a0897857b2 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
@@ -113,7 +113,7 @@ static void ng_btsocket_rfcomm_connect_cfm
static int ng_btsocket_rfcomm_session_create
(ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
- bdaddr_p src, bdaddr_p dst, struct thread *td);
+ const bdaddr_t *src, const bdaddr_t *dst, struct thread *td);
static int ng_btsocket_rfcomm_session_accept
(ng_btsocket_rfcomm_session_p s0);
static int ng_btsocket_rfcomm_session_connect
@@ -1250,7 +1250,7 @@ ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
static int
ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
- struct socket *l2so, bdaddr_p src, bdaddr_p dst,
+ struct socket *l2so, const bdaddr_t *src, const bdaddr_t *dst,
struct thread *td)
{
ng_btsocket_rfcomm_session_p s = NULL;
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 978d6fd0b54d..05c6062463be 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -960,7 +960,7 @@ struct ngnf_show_header *resp)
list_id = 0;
TAILQ_FOREACH(fle, &hsh->head, fle_hash) {
- if (hsh->mtx.mtx_lock & MTX_CONTESTED) {
+ if (hsh->mtx.mtx_lock & MTX_WAITERS) {
resp->hash_id = i;
resp->list_id = list_id;
mtx_unlock(&hsh->mtx);
@@ -1111,7 +1111,7 @@ ng_netflow_expire(void *arg)
* Interrupt thread wants this entry!
* Quick! Quick! Bail out!
*/
- if (hsh->mtx.mtx_lock & MTX_CONTESTED)
+ if (hsh->mtx.mtx_lock & MTX_WAITERS)
break;
/*
@@ -1150,7 +1150,7 @@ ng_netflow_expire(void *arg)
* Interrupt thread wants this entry!
* Quick! Quick! Bail out!
*/
- if (hsh->mtx.mtx_lock & MTX_CONTESTED)
+ if (hsh->mtx.mtx_lock & MTX_WAITERS)
break;
/*
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c
index e4fcdfc635cb..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
@@ -32,26 +33,28 @@
*/
#if 0
-#define DBG do { printf("ng_device: %s\n", __func__ ); } while (0)
+#define DBG do { printf("ng_device: %s\n", __func__); } while (0)
#else
#define DBG do {} while (0)
#endif
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/conf.h>
+#include <sys/epoch.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
#include <sys/ioccom.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/poll.h>
#include <sys/proc.h>
-#include <sys/epoch.h>
#include <sys/queue.h>
+#include <sys/selinfo.h>
#include <sys/socket.h>
#include <sys/syslog.h>
-#include <sys/systm.h>
#include <sys/uio.h>
-#include <sys/vnode.h>
#include <net/ethernet.h>
#include <net/if.h>
@@ -116,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;
@@ -135,10 +141,26 @@ static d_close_t ngdclose;
static d_open_t ngdopen;
static d_read_t ngdread;
static d_write_t ngdwrite;
-#if 0
static d_ioctl_t ngdioctl;
-#endif
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,16 +168,17 @@ static struct cdevsw ngd_cdevsw = {
.d_close = ngdclose,
.d_read = ngdread,
.d_write = ngdwrite,
-#if 0
.d_ioctl = ngdioctl,
-#endif
+ .d_kqfilter = ngdkqfilter,
.d_poll = ngdpoll,
.d_name = NG_DEVICE_DEVNAME,
};
-/******************************************************************************
+/*
+ *****************************************************************************
* Netgraph methods
- ******************************************************************************/
+ *****************************************************************************
+ */
/*
* Handle loading and unloading for this node type.
@@ -199,19 +222,24 @@ 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;
priv->ngddev = make_dev(&ngd_cdevsw, priv->unit, UID_ROOT,
GID_WHEEL, 0600, NG_DEVICE_DEVNAME "%d", priv->unit);
- if(priv->ngddev == NULL) {
- printf("%s(): make_dev() failed\n",__func__);
+ 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);
free(priv, M_NETGRAPH);
- return(EINVAL);
+ return (EINVAL);
}
/* XXX: race here? */
priv->ngddev->si_drv1 = priv;
@@ -221,7 +249,7 @@ ng_device_constructor(node_p node)
log(LOG_WARNING, "%s: can't acquire netgraph name\n",
devtoname(priv->ngddev));
- return(0);
+ return (0);
}
/*
@@ -289,7 +317,7 @@ ng_device_newhook(node_p node, hook_p hook, const char *name)
priv->hook = hook;
- return(0);
+ return (0);
}
/*
@@ -320,9 +348,11 @@ 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);
+ return (0);
}
/*
@@ -335,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);
@@ -347,7 +390,7 @@ ng_device_disconnect(hook_p hook)
ng_rmnode_self(NG_HOOK_NODE(hook));
- return(0);
+ return (0);
}
/*
@@ -360,9 +403,11 @@ ng_device_shutdown(node_p node)
return (0);
}
-/******************************************************************************
+/*
+ *****************************************************************************
* Device methods
- ******************************************************************************/
+ *****************************************************************************
+ */
/*
* the device is opened
@@ -370,7 +415,7 @@ ng_device_shutdown(node_p node)
static int
ngdopen(struct cdev *dev, int flag, int mode, struct thread *td)
{
- priv_p priv = (priv_p )dev->si_drv1;
+ priv_p priv = (priv_p)dev->si_drv1;
DBG;
@@ -378,7 +423,7 @@ ngdopen(struct cdev *dev, int flag, int mode, struct thread *td)
priv->flags |= NGDF_OPEN;
mtx_unlock(&priv->ngd_mtx);
- return(0);
+ return (0);
}
/*
@@ -387,14 +432,44 @@ ngdopen(struct cdev *dev, int flag, int mode, struct thread *td)
static int
ngdclose(struct cdev *dev, int flag, int mode, struct thread *td)
{
- priv_p priv = (priv_p )dev->si_drv1;
+ priv_p priv = (priv_p)dev->si_drv1;
DBG;
mtx_lock(&priv->ngd_mtx);
priv->flags &= ~NGDF_OPEN;
mtx_unlock(&priv->ngd_mtx);
- return(0);
+ return (0);
+}
+
+/*
+ * Process IOCTLs
+ *
+ * At this stage we only return success on FIONBIO to allow setting the device
+ * as non-blocking.
+ *
+ */
+static int
+ngdioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+ struct thread *td)
+{
+ int error;
+
+ switch (cmd) {
+ case FIONBIO:
+ error = 0;
+ break;
+ case FIOASYNC:
+ if (*(int *)data != 0)
+ error = EINVAL;
+ else
+ error = 0;
+ break;
+ default:
+ error = ENOTTY;
+ }
+
+ return (error);
}
#if 0 /*
@@ -408,21 +483,22 @@ ngdclose(struct cdev *dev, int flag, int mode, struct thread *td)
*
*/
static int
-ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
+ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
+ struct thread *td)
{
struct ngd_softc *sc = &ngd_softc;
- struct ngd_connection * connection = NULL;
- struct ngd_connection * tmp;
+ struct ngd_connection *connection = NULL;
+ struct ngd_connection *tmp;
int error = 0;
struct ng_mesg *msg;
- struct ngd_param_s * datap;
+ struct ngd_param_s *datap;
DBG;
NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s),
M_NOWAIT);
if (msg == NULL) {
- printf("%s(): msg == NULL\n",__func__);
+ printf("%s(): msg == NULL\n", __func__);
goto nomsg;
}
@@ -431,12 +507,12 @@ ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
datap->p = addr;
NG_SEND_MSG_HOOK(error, sc->node, msg, connection->active_hook, 0);
- if(error)
- printf("%s(): NG_SEND_MSG_HOOK error: %d\n",__func__,error);
+ if (error)
+ printf("%s(): NG_SEND_MSG_HOOK error: %d\n", __func__, error);
nomsg:
- return(0);
+ return (0);
}
#endif /* if 0 */
@@ -447,7 +523,7 @@ nomsg:
static int
ngdread(struct cdev *dev, struct uio *uio, int flag)
{
- priv_p priv = (priv_p )dev->si_drv1;
+ priv_p priv = (priv_p)dev->si_drv1;
struct mbuf *m;
int len, error = 0;
@@ -457,13 +533,17 @@ ngdread(struct cdev *dev, struct uio *uio, int flag)
do {
IF_DEQUEUE(&priv->readq, m);
if (m == NULL) {
- if (flag & IO_NDELAY)
+ if (flag & O_NONBLOCK)
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);
@@ -483,14 +563,14 @@ ngdread(struct cdev *dev, struct uio *uio, int flag)
/*
* This function is called when our device is written to.
- * We read the data from userland into mbuf chain and pass it to the remote hook.
- *
+ * We read the data from userland into mbuf chain and pass it to the remote
+ * hook.
*/
static int
ngdwrite(struct cdev *dev, struct uio *uio, int flag)
{
struct epoch_tracker et;
- priv_p priv = (priv_p )dev->si_drv1;
+ priv_p priv = (priv_p)dev->si_drv1;
struct mbuf *m;
int error = 0;
@@ -506,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);
}
@@ -520,7 +603,7 @@ ngdwrite(struct cdev *dev, struct uio *uio, int flag)
static int
ngdpoll(struct cdev *dev, int events, struct thread *td)
{
- priv_p priv = (priv_p )dev->si_drv1;
+ priv_p priv = (priv_p)dev->si_drv1;
int revents = 0;
if (events & (POLLIN | POLLRDNORM) &&
@@ -529,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);
+ }
+}
diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c
index defbe817becd..8b82d777caeb 100644
--- a/sys/netgraph/ng_nat.c
+++ b/sys/netgraph/ng_nat.c
@@ -818,7 +818,8 @@ ng_nat_rcvdata(hook_p hook, item_p item )
if (ip->ip_v != IPVERSION)
goto send; /* other IP version, let it pass */
- if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len))
+ uint16_t ip_len = ntohs(ip->ip_len);
+ if (m->m_pkthdr.len < (ipofs + ip_len))
goto send; /* packet too short (i.e. fragmented or broken) */
/*
@@ -852,50 +853,68 @@ ng_nat_rcvdata(hook_p hook, item_p item )
if (rval == PKT_ALIAS_RESPOND)
m->m_flags |= M_SKIP_FIREWALL;
- m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs;
- if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
- ip->ip_p == IPPROTO_TCP) {
- struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
- (ip->ip_hl << 2));
+ /* Re-read just in case it has been updated */
+ ip_len = ntohs(ip->ip_len);
+ int new_m_len = ip_len + ipofs;
+ if (new_m_len > (m->m_len + M_TRAILINGSPACE(m))) {
/*
- * Here is our terrible HACK.
- *
- * Sometimes LibAlias edits contents of TCP packet.
- * In this case it needs to recompute full TCP
- * checksum. However, the problem is that LibAlias
- * doesn't have any idea about checksum offloading
- * in kernel. To workaround this, we do not do
- * checksumming in LibAlias, but only mark the
- * packets with TH_RES1 in the th_x2 field. If we
- * receive a marked packet, we calculate correct
- * checksum for it aware of offloading.
- *
- * Why do I do such a terrible hack instead of
- * recalculating checksum for each packet?
- * Because the previous checksum was not checked!
- * Recalculating checksums for EVERY packet will
- * hide ALL transmission errors. Yes, marked packets
- * still suffer from this problem. But, sigh, natd(8)
- * has this problem, too.
+ * This is just a safety railguard to make sure LibAlias has not
+ * screwed the IP packet up somehow, should probably be KASSERT()
+ * at some point. Calling in_delayed_cksum() will parse IP packet
+ * again and reliably panic if there is less data than the IP
+ * header declares, there might be some other places too.
*/
+ log(LOG_ERR, "ng_nat_rcvdata: outgoing packet corrupted, "
+ "not enough data: expected %d, available (%d - %d)\n",
+ ip_len, m->m_len + (int)M_TRAILINGSPACE(m), ipofs);
+ NG_FREE_ITEM(item);
+ return (ENXIO);
+ }
+
+ m->m_pkthdr.len = m->m_len = new_m_len;
- if (tcp_get_flags(th) & TH_RES1) {
- uint16_t ip_len = ntohs(ip->ip_len);
+ if ((ip->ip_off & htons(IP_OFFMASK)) != 0 || ip->ip_p != IPPROTO_TCP)
+ goto send;
- tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1);
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP +
- ip_len - (ip->ip_hl << 2)));
+ uint16_t pl_offset = ip->ip_hl << 2;
+ struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + pl_offset);
- if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) {
- m->m_pkthdr.csum_data = offsetof(struct tcphdr,
- th_sum);
- in_delayed_cksum(m);
- }
- }
- }
+ /*
+ * Here is our terrible HACK.
+ *
+ * Sometimes LibAlias edits contents of TCP packet.
+ * In this case it needs to recompute full TCP
+ * checksum. However, the problem is that LibAlias
+ * doesn't have any idea about checksum offloading
+ * in kernel. To workaround this, we do not do
+ * checksumming in LibAlias, but only mark the
+ * packets with TH_RES1 in the th_x2 field. If we
+ * receive a marked packet, we calculate correct
+ * checksum for it aware of offloading.
+ *
+ * Why do I do such a terrible hack instead of
+ * recalculating checksum for each packet?
+ * Because the previous checksum was not checked!
+ * Recalculating checksums for EVERY packet will
+ * hide ALL transmission errors. Yes, marked packets
+ * still suffer from this problem. But, sigh, natd(8)
+ * has this problem, too.
+ */
+
+ if (!(tcp_get_flags(th) & TH_RES1))
+ goto send;
+
+ tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1);
+ th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+ htons(IPPROTO_TCP + ip_len - pl_offset));
+
+ if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
+ goto send;
+
+ m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+ in_delayed_cksum_o(m, ipofs);
send:
if (hook == priv->in)
diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c
index 448ecc92f075..5e1a1bb47ac0 100644
--- a/sys/netgraph/ng_parse.c
+++ b/sys/netgraph/ng_parse.c
@@ -1199,14 +1199,14 @@ ng_parse_composite(const struct ng_parse_type *type, const char *s,
int *off, const u_char *const start, u_char *const buf, int *buflen,
const enum comptype ctype)
{
- const int num = ng_get_composite_len(type, start, buf, ctype);
int nextIndex = 0; /* next implicit array index */
u_int index; /* field or element index */
int *foff; /* field value offsets in string */
int align, len, blen, error = 0;
/* Initialize */
- if (num < 0)
+ const int num = ng_get_composite_len(type, start, buf, ctype);
+ if (num < 0 || num > INT_MAX / sizeof(*foff))
return (EINVAL);
foff = malloc(num * sizeof(*foff), M_NETGRAPH_PARSE, M_NOWAIT | M_ZERO);
if (foff == NULL) {
diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c
index 6f8667c664bb..0e3230a66f66 100644
--- a/sys/netgraph/ng_tty.c
+++ b/sys/netgraph/ng_tty.c
@@ -427,7 +427,7 @@ ngt_rint_bypass(struct tty *tp, const void *buf, size_t len)
for (mb = m; mb != NULL; mb = mb->m_next) {
length = min(M_TRAILINGSPACE(mb), len - total);
- memcpy(mtod(m, char *), (const char *)buf + total, length);
+ memcpy(mtod(mb, char *), (const char *)buf + total, length);
mb->m_len = length;
total += length;
m->m_pkthdr.len += length;
@@ -485,9 +485,7 @@ ngt_rint(struct tty *tp, char c, int flags)
}
/* Add char to mbuf */
- *mtod(m, u_char *) = c;
- m->m_data++;
- m->m_len++;
+ *(u_char *)mtodo(m, m->m_len++) = c;
m->m_pkthdr.len++;
/* Ship off mbuf if it's time */