summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_pptpgre.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/ng_pptpgre.c')
-rw-r--r--sys/netgraph/ng_pptpgre.c101
1 files changed, 55 insertions, 46 deletions
diff --git a/sys/netgraph/ng_pptpgre.c b/sys/netgraph/ng_pptpgre.c
index c5306b0..c126d9d 100644
--- a/sys/netgraph/ng_pptpgre.c
+++ b/sys/netgraph/ng_pptpgre.c
@@ -172,14 +172,14 @@ typedef struct ng_pptpgre_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_pptpgre_constructor;
static ng_rcvmsg_t ng_pptpgre_rcvmsg;
-static ng_shutdown_t ng_pptpgre_rmnode;
+static ng_shutdown_t ng_pptpgre_shutdown;
static ng_newhook_t ng_pptpgre_newhook;
static ng_rcvdata_t ng_pptpgre_rcvdata;
static ng_disconnect_t ng_pptpgre_disconnect;
/* Helper functions */
-static int ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta);
-static int ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta);
+static int ng_pptpgre_xmit(node_p node, item_p item);
+static int ng_pptpgre_recv(node_p node, item_p item);
static void ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout);
static void ng_pptpgre_start_recv_ack_timer(node_p node);
static void ng_pptpgre_recv_ack_timeout(void *arg);
@@ -250,7 +250,7 @@ static struct ng_type ng_pptpgre_typestruct = {
NULL,
ng_pptpgre_constructor,
ng_pptpgre_rcvmsg,
- ng_pptpgre_rmnode,
+ ng_pptpgre_shutdown,
ng_pptpgre_newhook,
NULL,
NULL,
@@ -270,22 +270,16 @@ NETGRAPH_INIT(pptpgre, &ng_pptpgre_typestruct);
* Node type constructor
*/
static int
-ng_pptpgre_constructor(node_p *nodep)
+ng_pptpgre_constructor(node_p node)
{
priv_p priv;
- int error;
/* Allocate private structure */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
- /* Call generic node constructor */
- if ((error = ng_make_node_common(&ng_pptpgre_typestruct, nodep))) {
- FREE(priv, M_NETGRAPH);
- return (error);
- }
- (*nodep)->private = priv;
+ node->private = priv;
/* Initialize state */
callout_handle_init(&priv->ackp.sackTimer);
@@ -325,13 +319,14 @@ ng_pptpgre_newhook(node_p node, hook_p hook, const char *name)
* Receive a control message.
*/
static int
-ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
- const char *raddr, struct ng_mesg **rptr, hook_p lasthook)
+ng_pptpgre_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
+ struct ng_mesg *msg;
+ NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_PPTPGRE_COOKIE:
switch (msg->header.cmd) {
@@ -379,12 +374,8 @@ ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
break;
}
done:
- if (rptr)
- *rptr = resp;
- else if (resp)
- FREE(resp, M_NETGRAPH);
-
- FREE(msg, M_NETGRAPH);
+ NG_RESPOND_MSG(error, node, item, resp);
+ NG_FREE_MSG(msg);
return (error);
}
@@ -392,23 +383,22 @@ done:
* Receive incoming data on a hook.
*/
static int
-ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
- struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
+ng_pptpgre_rcvdata(hook_p hook, item_p item)
{
const node_p node = hook->node;
const priv_p priv = node->private;
/* If not configured, reject */
if (!priv->conf.enabled) {
- NG_FREE_DATA(m, meta);
+ NG_FREE_ITEM(item);
return (ENXIO);
}
/* Treat as xmit or recv data */
if (hook == priv->upper)
- return ng_pptpgre_xmit(node, m, meta);
+ return ng_pptpgre_xmit(node, item);
if (hook == priv->lower)
- return ng_pptpgre_recv(node, m, meta);
+ return ng_pptpgre_recv(node, item);
panic("%s: weird hook", __FUNCTION__);
}
@@ -416,7 +406,7 @@ ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Destroy node
*/
static int
-ng_pptpgre_rmnode(node_p node)
+ng_pptpgre_shutdown(node_p node)
{
const priv_p priv = node->private;
@@ -425,8 +415,6 @@ ng_pptpgre_rmnode(node_p node)
/* Take down netgraph node */
node->flags |= NG_INVALID;
- ng_cutlinks(node);
- ng_unname(node);
bzero(priv, sizeof(*priv));
FREE(priv, M_NETGRAPH);
node->private = NULL;
@@ -452,8 +440,9 @@ ng_pptpgre_disconnect(hook_p hook)
panic("%s: unknown hook", __FUNCTION__);
/* Go away if no longer connected to anything */
- if (node->numhooks == 0)
- ng_rmnode(node);
+ if ((node->numhooks == 0)
+ && ((node->flags & NG_INVALID) == 0))
+ ng_rmnode_self(node);
return (0);
}
@@ -465,14 +454,20 @@ ng_pptpgre_disconnect(hook_p hook)
* Transmit an outgoing frame, or just an ack if m is NULL.
*/
static int
-ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
+ng_pptpgre_xmit(node_p node, item_p item)
{
const priv_p priv = node->private;
struct ng_pptpgre_ackp *const a = &priv->ackp;
u_char buf[sizeof(struct greheader) + 2 * sizeof(u_int32_t)];
struct greheader *const gre = (struct greheader *)buf;
int grelen, error;
+ struct mbuf *m;
+ if (item) {
+ NGI_GET_M(item, m);
+ } else {
+ m = NULL;
+ }
/* Check if there's data */
if (m != NULL) {
@@ -480,18 +475,21 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck)
>= a->xmitWin) {
priv->stats.xmitDrops++;
- NG_FREE_DATA(m, meta);
+ NG_FREE_M(m);
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
/* Sanity check frame length */
if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
priv->stats.xmitTooBig++;
- NG_FREE_DATA(m, meta);
+ NG_FREE_M(m);
+ NG_FREE_ITEM(item);
return (EMSGSIZE);
}
- } else
+ } else {
priv->stats.xmitLoneAcks++;
+ }
/* Build GRE header */
((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE);
@@ -521,7 +519,8 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
priv->stats.memoryFailures++;
- NG_FREE_META(meta);
+ if (item)
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
m->m_len = m->m_pkthdr.len = grelen;
@@ -531,7 +530,8 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
if (m == NULL || (m->m_len < grelen
&& (m = m_pullup(m, grelen)) == NULL)) {
priv->stats.memoryFailures++;
- NG_FREE_META(meta);
+ if (item)
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
}
@@ -542,7 +542,12 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
priv->stats.xmitOctets += m->m_pkthdr.len;
/* Deliver packet */
- NG_SEND_DATA(error, priv->lower, m, meta);
+ if (item) {
+ NG_FWD_NEW_DATA(error, item, priv->lower, m);
+ } else {
+ NG_SEND_DATA_ONLY(error, priv->lower, m);
+ }
+
/* Start receive ACK timer if data was sent and not already running */
if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1)
@@ -554,14 +559,16 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
* Handle an incoming packet. The packet includes the IP header.
*/
static int
-ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
+ng_pptpgre_recv(node_p node, item_p item)
{
const priv_p priv = node->private;
int iphlen, grelen, extralen;
struct greheader *gre;
struct ip *ip;
int error = 0;
+ struct mbuf *m;
+ NGI_GET_M(item, m);
/* Update stats */
priv->stats.recvPackets++;
priv->stats.recvOctets += m->m_pkthdr.len;
@@ -570,7 +577,8 @@ ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
priv->stats.recvRunts++;
bad:
- NG_FREE_DATA(m, meta);
+ NG_FREE_M(m);
+ NG_FREE_ITEM(item);
return (EINVAL);
}
@@ -578,7 +586,7 @@ bad:
if (m->m_len < sizeof(*ip) + sizeof(*gre)
&& (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
priv->stats.memoryFailures++;
- NG_FREE_META(meta);
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@@ -586,7 +594,7 @@ bad:
if (m->m_len < iphlen + sizeof(*gre)) {
if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
priv->stats.memoryFailures++;
- NG_FREE_META(meta);
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@@ -600,7 +608,7 @@ bad:
if (m->m_len < iphlen + grelen) {
if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
priv->stats.memoryFailures++;
- NG_FREE_META(meta);
+ NG_FREE_ITEM(item);
return (ENOBUFS);
}
ip = mtod(m, struct ip *);
@@ -695,7 +703,7 @@ badAck:
/* If delayed ACK is disabled, send it now */
if (!priv->conf.enableDelayedAck
|| maxWait < PPTP_MIN_ACK_DELAY)
- ng_pptpgre_xmit(node, NULL, NULL);
+ ng_pptpgre_xmit(node, NULL);
else { /* send the ack later */
if (maxWait > PPTP_MAX_ACK_DELAY)
maxWait = PPTP_MAX_ACK_DELAY;
@@ -709,10 +717,11 @@ badAck:
m_adj(m, -extralen);
/* Deliver frame to upper layers */
- NG_SEND_DATA(error, priv->upper, m, meta);
+ NG_FWD_NEW_DATA(error, item, priv->upper, m);
} else {
priv->stats.recvLoneAcks++;
- NG_FREE_DATA(m, meta); /* no data to deliver */
+ NG_FREE_ITEM(item);
+ NG_FREE_M(m); /* no data to deliver */
}
return (error);
}
@@ -868,7 +877,7 @@ ng_pptpgre_send_ack_timeout(void *arg)
a->sackTimerPtr = NULL;
/* Send a frame with an ack but no payload */
- ng_pptpgre_xmit(node, NULL, NULL);
+ ng_pptpgre_xmit(node, NULL);
splx(s);
}
OpenPOWER on IntegriCloud