152419Sjulian/* 252419Sjulian * ng_rfc1490.c 3139823Simp */ 4139823Simp 5139823Simp/*- 652419Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc. 752419Sjulian * All rights reserved. 852419Sjulian * 952419Sjulian * Subject to the following obligations and disclaimer of warranty, use and 1052419Sjulian * redistribution of this software, in source or object code forms, with or 1152419Sjulian * without modifications are expressly permitted by Whistle Communications; 1252419Sjulian * provided, however, that: 1352419Sjulian * 1. Any and all reproductions of the source or object code must include the 1452419Sjulian * copyright notice above and the following disclaimer of warranties; and 1552419Sjulian * 2. No rights are granted, in any manner or form, to use Whistle 1652419Sjulian * Communications, Inc. trademarks, including the mark "WHISTLE 1752419Sjulian * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1852419Sjulian * such appears in the above copyright notice or in the software. 1952419Sjulian * 2052419Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 2152419Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2252419Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2352419Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2452419Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2552419Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2652419Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2752419Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2852419Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2952419Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 3052419Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 3152419Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3252419Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3352419Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3452419Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3552419Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3652419Sjulian * OF SUCH DAMAGE. 3752419Sjulian * 3867506Sjulian * Author: Julian Elischer <julian@freebsd.org> 3952419Sjulian * 4052419Sjulian * $FreeBSD: releng/10.3/sys/netgraph/ng_rfc1490.c 243882 2012-12-05 08:04:20Z glebius $ 4152752Sjulian * $Whistle: ng_rfc1490.c,v 1.22 1999/11/01 09:24:52 julian Exp $ 4252419Sjulian */ 4352419Sjulian 4452419Sjulian/* 4552419Sjulian * This node does RFC 1490 multiplexing. 4652419Sjulian * 4752419Sjulian * NOTE: RFC 1490 is updated by RFC 2427. 4852419Sjulian */ 4952419Sjulian 5052419Sjulian#include <sys/param.h> 5152419Sjulian#include <sys/systm.h> 5252419Sjulian#include <sys/errno.h> 5352419Sjulian#include <sys/kernel.h> 5452419Sjulian#include <sys/malloc.h> 5552419Sjulian#include <sys/mbuf.h> 5652419Sjulian#include <sys/errno.h> 5752419Sjulian#include <sys/socket.h> 5852419Sjulian 5952419Sjulian#include <net/if.h> 6052419Sjulian#include <netinet/in.h> 6152419Sjulian#include <netinet/if_ether.h> 6252419Sjulian 6352419Sjulian#include <netgraph/ng_message.h> 6452419Sjulian#include <netgraph/netgraph.h> 65130413Sjulian#include <netgraph/ng_parse.h> 6652419Sjulian#include <netgraph/ng_rfc1490.h> 6752419Sjulian 6852419Sjulian/* 6952419Sjulian * DEFINITIONS 7052419Sjulian */ 7152419Sjulian 7252419Sjulian/* Q.922 stuff -- see RFC 1490 */ 7352419Sjulian#define HDLC_UI 0x03 7452419Sjulian 7552419Sjulian#define NLPID_IP 0xCC 7652419Sjulian#define NLPID_PPP 0xCF 7752419Sjulian#define NLPID_SNAP 0x80 7852419Sjulian#define NLPID_Q933 0x08 7952419Sjulian#define NLPID_CLNP 0x81 8052419Sjulian#define NLPID_ESIS 0x82 8152419Sjulian#define NLPID_ISIS 0x83 8252419Sjulian 83130413Sjulian#define ERROUT(x) do { error = (x); goto done; } while (0) 84130413Sjulian 85130413Sjulian/* Encapsulation methods we understand */ 86130413Sjulianenum { 87130413Sjulian NG_RFC1490_ENCAP_IETF_IP = 1, /* see RFC2427, chapter 7, table 1 */ 88130413Sjulian NG_RFC1490_ENCAP_IETF_SNAP, /* see RFC2427, chapter 7, table 2 */ 89130413Sjulian NG_RFC1490_ENCAP_CISCO, /* Cisco's proprietary encapsulation */ 90130413Sjulian}; 91130413Sjulian 92130413Sjulianstruct ng_rfc1490_encap_t { 93130413Sjulian u_int8_t method; 94130413Sjulian const char *name; 95130413Sjulian}; 96130413Sjulian 97130413Sjulianstatic const struct ng_rfc1490_encap_t ng_rfc1490_encaps[] = { 98130413Sjulian { NG_RFC1490_ENCAP_IETF_IP, "ietf-ip" }, 99130413Sjulian { NG_RFC1490_ENCAP_IETF_SNAP, "ietf-snap" }, 100130413Sjulian { NG_RFC1490_ENCAP_CISCO, "cisco" }, 101130413Sjulian { 0, NULL}, 102130413Sjulian}; 103130413Sjulian 10452419Sjulian/* Node private data */ 10553407Sarchiestruct ng_rfc1490_private { 10652419Sjulian hook_p downlink; 10752419Sjulian hook_p ppp; 10852419Sjulian hook_p inet; 109124506Sgreen hook_p ethernet; 110130413Sjulian const struct ng_rfc1490_encap_t *enc; 11152419Sjulian}; 11253407Sarchietypedef struct ng_rfc1490_private *priv_p; 11352419Sjulian 11452419Sjulian/* Netgraph node methods */ 11552752Sjulianstatic ng_constructor_t ng_rfc1490_constructor; 11652752Sjulianstatic ng_rcvmsg_t ng_rfc1490_rcvmsg; 11770700Sjulianstatic ng_shutdown_t ng_rfc1490_shutdown; 11852752Sjulianstatic ng_newhook_t ng_rfc1490_newhook; 11952752Sjulianstatic ng_rcvdata_t ng_rfc1490_rcvdata; 12052752Sjulianstatic ng_disconnect_t ng_rfc1490_disconnect; 12152419Sjulian 122130413Sjulian/* List of commands and how to convert arguments to/from ASCII */ 123130413Sjulianstatic const struct ng_cmdlist ng_rfc1490_cmds[] = { 124130413Sjulian { 125130413Sjulian NGM_RFC1490_COOKIE, 126130413Sjulian NGM_RFC1490_SET_ENCAP, 127130413Sjulian "setencap", 128130413Sjulian &ng_parse_string_type, 129130413Sjulian NULL 130130413Sjulian }, 131130413Sjulian { 132130413Sjulian NGM_RFC1490_COOKIE, 133130413Sjulian NGM_RFC1490_GET_ENCAP, 134130413Sjulian "getencap", 135130413Sjulian NULL, 136130413Sjulian &ng_parse_string_type 137130413Sjulian }, 138130413Sjulian { 0 } 139130413Sjulian}; 140130413Sjulian 14152419Sjulian/* Node type descriptor */ 14252419Sjulianstatic struct ng_type typestruct = { 143129823Sjulian .version = NG_ABI_VERSION, 144129823Sjulian .name = NG_RFC1490_NODE_TYPE, 145129823Sjulian .constructor = ng_rfc1490_constructor, 146129823Sjulian .rcvmsg = ng_rfc1490_rcvmsg, 147129823Sjulian .shutdown = ng_rfc1490_shutdown, 148129823Sjulian .newhook = ng_rfc1490_newhook, 149129823Sjulian .rcvdata = ng_rfc1490_rcvdata, 150129823Sjulian .disconnect = ng_rfc1490_disconnect, 151130413Sjulian .cmdlist = ng_rfc1490_cmds, 15252419Sjulian}; 15352419SjulianNETGRAPH_INIT(rfc1490, &typestruct); 15452419Sjulian 15552419Sjulian/************************************************************************ 15652419Sjulian NETGRAPH NODE STUFF 15752419Sjulian ************************************************************************/ 15852419Sjulian 15952419Sjulian/* 16052419Sjulian * Node constructor 16152419Sjulian */ 16252419Sjulianstatic int 16370700Sjulianng_rfc1490_constructor(node_p node) 16452419Sjulian{ 16552419Sjulian priv_p priv; 16652419Sjulian 16752419Sjulian /* Allocate private structure */ 168220768Sglebius priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO); 16952419Sjulian 170130413Sjulian /* Initialize to default encapsulation method - ietf-ip */ 171130413Sjulian priv->enc = ng_rfc1490_encaps; 172130413Sjulian 17370784Sjulian NG_NODE_SET_PRIVATE(node, priv); 17452419Sjulian 17552419Sjulian /* Done */ 17652419Sjulian return (0); 17752419Sjulian} 17852419Sjulian 17952419Sjulian/* 18052419Sjulian * Give our ok for a hook to be added 18152419Sjulian */ 18252419Sjulianstatic int 18352419Sjulianng_rfc1490_newhook(node_p node, hook_p hook, const char *name) 18452419Sjulian{ 18570784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 18652419Sjulian 18752419Sjulian if (!strcmp(name, NG_RFC1490_HOOK_DOWNSTREAM)) { 18852419Sjulian if (priv->downlink) 18952419Sjulian return (EISCONN); 19052419Sjulian priv->downlink = hook; 19152419Sjulian } else if (!strcmp(name, NG_RFC1490_HOOK_PPP)) { 19252419Sjulian if (priv->ppp) 19352419Sjulian return (EISCONN); 19452419Sjulian priv->ppp = hook; 19552419Sjulian } else if (!strcmp(name, NG_RFC1490_HOOK_INET)) { 19652419Sjulian if (priv->inet) 19752419Sjulian return (EISCONN); 19852419Sjulian priv->inet = hook; 199124506Sgreen } else if (!strcmp(name, NG_RFC1490_HOOK_ETHERNET)) { 200124506Sgreen if (priv->ethernet) 201124506Sgreen return (EISCONN); 202124506Sgreen priv->ethernet = hook; 20352419Sjulian } else 20452419Sjulian return (EINVAL); 20552419Sjulian return (0); 20652419Sjulian} 20752419Sjulian 20852419Sjulian/* 209130413Sjulian * Receive a control message. 21052419Sjulian */ 21152419Sjulianstatic int 21270700Sjulianng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook) 21352419Sjulian{ 214130413Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 215130413Sjulian struct ng_mesg *msg; 216130413Sjulian struct ng_mesg *resp = NULL; 217130413Sjulian int error = 0; 218130413Sjulian 219130413Sjulian NGI_GET_MSG(item, msg); 220130413Sjulian 221130413Sjulian if (msg->header.typecookie == NGM_RFC1490_COOKIE) { 222130413Sjulian switch (msg->header.cmd) { 223130413Sjulian case NGM_RFC1490_SET_ENCAP: 224130413Sjulian { 225130413Sjulian const struct ng_rfc1490_encap_t *enc; 226130413Sjulian char *s; 227130413Sjulian size_t len; 228130413Sjulian 229130413Sjulian if (msg->header.arglen == 0) 230130413Sjulian ERROUT(EINVAL); 231130413Sjulian 232130413Sjulian s = (char *)msg->data; 233130413Sjulian len = msg->header.arglen - 1; 234130413Sjulian 235130413Sjulian /* Search for matching encapsulation method */ 236130413Sjulian for (enc = ng_rfc1490_encaps; enc->method != 0; enc++ ) 237130413Sjulian if ((strlen(enc->name) == len) && 238130413Sjulian !strncmp(enc->name, s, len)) 239130413Sjulian break; /* found */ 240130413Sjulian 241130413Sjulian if (enc->method != 0) 242130413Sjulian priv->enc = enc; 243130413Sjulian else 244130413Sjulian error = EINVAL; 245130413Sjulian break; 246130413Sjulian } 247130413Sjulian case NGM_RFC1490_GET_ENCAP: 248130413Sjulian 249130413Sjulian NG_MKRESPONSE(resp, msg, strlen(priv->enc->name) + 1, M_NOWAIT); 250130413Sjulian if (resp == NULL) 251130413Sjulian ERROUT(ENOMEM); 252130413Sjulian 253130413Sjulian strlcpy((char *)resp->data, priv->enc->name, 254130413Sjulian strlen(priv->enc->name) + 1); 255130413Sjulian break; 256130413Sjulian 257130413Sjulian default: 258130413Sjulian error = EINVAL; 259130413Sjulian break; 260130413Sjulian } 261130413Sjulian } else 262130413Sjulian error = EINVAL; 263130413Sjulian 264130413Sjuliandone: 265130413Sjulian NG_RESPOND_MSG(error, node, item, resp); 266130413Sjulian NG_FREE_MSG(msg); 267130413Sjulian return (error); 26852419Sjulian} 26952419Sjulian 27052419Sjulian/* 27152419Sjulian * Receive data on a hook and encapsulate according to RFC 1490. 27252419Sjulian * Only those nodes marked (*) are supported by this routine so far. 27352419Sjulian * 27452419Sjulian * Q.922 control 27552419Sjulian * | 27652419Sjulian * | 277130413Sjulian * --------------------------------------------------------------------- 278130413Sjulian * | 0x03 | | 279130413Sjulian * UI I Frame Cisco 280130413Sjulian * | | Encapsulation 281130413Sjulian * --------------------------------- -------------- | 282130413Sjulian * | 0x08 | 0x81 |0xCC |0xCF | 0x00 |..01.... |..10.... -------------- 283130413Sjulian * | | | | | 0x80 | | |0x800 | 284130413Sjulian * Q.933 CLNP IP(*) PPP(*) SNAP ISO 8208 ISO 8208 | | 285130413Sjulian * | (rfc1973) | Modulo 8 Modulo 128 IP(*) Others 28652419Sjulian * | | 28752419Sjulian * -------------------- OUI 28852419Sjulian * | | | 28952419Sjulian * L2 ID L3 ID ------------------------- 29052419Sjulian * | User |00-80-C2 |00-00-00 29152419Sjulian * | specified | | 29252419Sjulian * | 0x70 PID Ethertype 29352419Sjulian * | | | 294124506Sgreen * ------------------- -----------------... ---------- 295124506Sgreen * |0x51 |0x4E | |0x4C |0x7 |0xB | |0x806 | 296124506Sgreen * | | | | | | | | | 297130413Sjulian * 7776 Q.922 Others 802.2 802.3(*) 802.6 Others IP(*) Others 29852419Sjulian * 29952419Sjulian * 30052419Sjulian */ 30152419Sjulian 30252419Sjulian#define MAX_ENCAPS_HDR 8 30352419Sjulian#define OUICMP(P,A,B,C) ((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C)) 30452419Sjulian 30552419Sjulianstatic int 30670700Sjulianng_rfc1490_rcvdata(hook_p hook, item_p item) 30752419Sjulian{ 30870784Sjulian const node_p node = NG_HOOK_NODE(hook); 30970784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 31052419Sjulian int error = 0; 31170700Sjulian struct mbuf *m; 31252419Sjulian 31370700Sjulian NGI_GET_M(item, m); 31452419Sjulian if (hook == priv->downlink) { 31597897Sarchie const u_char *start; 31697897Sarchie const u_char *ptr; 31752419Sjulian 318131112Sjulian if (m->m_len < MAX_ENCAPS_HDR 319131112Sjulian && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 32052419Sjulian ERROUT(ENOBUFS); 32197897Sarchie ptr = start = mtod(m, const u_char *); 32252419Sjulian 323130413Sjulian if (priv->enc->method == NG_RFC1490_ENCAP_CISCO) 324130413Sjulian goto switch_on_etype; 325130413Sjulian 32652419Sjulian /* Must be UI frame */ 32752419Sjulian if (*ptr++ != HDLC_UI) 32852419Sjulian ERROUT(0); 32952419Sjulian 33052419Sjulian /* Eat optional zero pad byte */ 33152419Sjulian if (*ptr == 0x00) 33252419Sjulian ptr++; 33352419Sjulian 33452419Sjulian /* Multiplex on NLPID */ 33552419Sjulian switch (*ptr++) { 33652419Sjulian case NLPID_SNAP: 33752419Sjulian if (OUICMP(ptr, 0, 0, 0)) { /* It's an ethertype */ 33852419Sjulian u_int16_t etype; 33952419Sjulian 34052419Sjulian ptr += 3; 341130413Sjulianswitch_on_etype: etype = ntohs(*((const u_int16_t *)ptr)); 34252419Sjulian ptr += 2; 34352419Sjulian m_adj(m, ptr - start); 34452419Sjulian switch (etype) { 34552419Sjulian case ETHERTYPE_IP: 34670700Sjulian NG_FWD_NEW_DATA(error, item, 34770700Sjulian priv->inet, m); 34852419Sjulian break; 34952419Sjulian case ETHERTYPE_ARP: 35052419Sjulian case ETHERTYPE_REVARP: 35152419Sjulian default: 35252419Sjulian ERROUT(0); 35352419Sjulian } 354124506Sgreen } else if (OUICMP(ptr, 0x00, 0x80, 0xc2)) { 355124506Sgreen /* 802.1 bridging */ 356124506Sgreen ptr += 3; 357124506Sgreen if (*ptr++ != 0x00) 358130413Sjulian ERROUT(0); /* unknown PID octet 0 */ 359124506Sgreen if (*ptr++ != 0x07) 360124506Sgreen ERROUT(0); /* not FCS-less 802.3 */ 361124506Sgreen m_adj(m, ptr - start); 362124506Sgreen NG_FWD_NEW_DATA(error, item, priv->ethernet, m); 363124506Sgreen } else /* Other weird stuff... */ 36452419Sjulian ERROUT(0); 36552419Sjulian break; 36652419Sjulian case NLPID_IP: 36752419Sjulian m_adj(m, ptr - start); 36870700Sjulian NG_FWD_NEW_DATA(error, item, priv->inet, m); 36952419Sjulian break; 37052419Sjulian case NLPID_PPP: 37152419Sjulian m_adj(m, ptr - start); 37270700Sjulian NG_FWD_NEW_DATA(error, item, priv->ppp, m); 37352419Sjulian break; 37452419Sjulian case NLPID_Q933: 37552419Sjulian case NLPID_CLNP: 37652419Sjulian case NLPID_ESIS: 37752419Sjulian case NLPID_ISIS: 37852419Sjulian ERROUT(0); 37952419Sjulian default: /* Try PPP (see RFC 1973) */ 38052419Sjulian ptr--; /* NLPID becomes PPP proto */ 38152419Sjulian if ((*ptr & 0x01) == 0x01) 38252419Sjulian ERROUT(0); 38352419Sjulian m_adj(m, ptr - start); 38470700Sjulian NG_FWD_NEW_DATA(error, item, priv->ppp, m); 38552419Sjulian break; 38652419Sjulian } 38752419Sjulian } else if (hook == priv->ppp) { 388243882Sglebius M_PREPEND(m, 2, M_NOWAIT); /* Prepend PPP NLPID */ 38952419Sjulian if (!m) 39052419Sjulian ERROUT(ENOBUFS); 39152419Sjulian mtod(m, u_char *)[0] = HDLC_UI; 39252419Sjulian mtod(m, u_char *)[1] = NLPID_PPP; 39370700Sjulian NG_FWD_NEW_DATA(error, item, priv->downlink, m); 39452419Sjulian } else if (hook == priv->inet) { 395130413Sjulian switch (priv->enc->method) { 396130413Sjulian case NG_RFC1490_ENCAP_IETF_IP: 397243882Sglebius M_PREPEND(m, 2, M_NOWAIT); /* Prepend IP NLPID */ 398130413Sjulian if (!m) 399130413Sjulian ERROUT(ENOBUFS); 400130413Sjulian mtod(m, u_char *)[0] = HDLC_UI; 401130413Sjulian mtod(m, u_char *)[1] = NLPID_IP; 402130413Sjulian break; 403130413Sjulian case NG_RFC1490_ENCAP_IETF_SNAP: 404130413Sjulian /* 405130413Sjulian * According to RFC2427 frame should begin with 406130413Sjulian * HDLC_UI PAD NLIPID OUI PID 407130413Sjulian * 03 00 80 00 00 00 08 00 408130413Sjulian */ 409243882Sglebius M_PREPEND(m, 8, M_NOWAIT); 410130413Sjulian if (!m) 411130413Sjulian ERROUT(ENOBUFS); 412130413Sjulian mtod(m, u_char *)[0] = HDLC_UI; 413130413Sjulian mtod(m, u_char *)[1] = 0x00; /* PAD */ 414130413Sjulian mtod(m, u_char *)[2] = NLPID_SNAP; 415130413Sjulian bzero((char *)(mtod(m, u_char *) + 3), 3); /* OUI 0-0-0 */ 416130413Sjulian *((u_int16_t *)mtod(m, u_int16_t *) + 6/sizeof(u_int16_t)) 417130413Sjulian = htons(ETHERTYPE_IP); /* PID */ 418130413Sjulian break; 419130413Sjulian case NG_RFC1490_ENCAP_CISCO: 420243882Sglebius M_PREPEND(m, 2, M_NOWAIT); /* Prepend IP ethertype */ 421130413Sjulian if (!m) 422130413Sjulian ERROUT(ENOBUFS); 423130413Sjulian *((u_int16_t *)mtod(m, u_int16_t *)) = htons(ETHERTYPE_IP); 424130413Sjulian break; 425130413Sjulian } 42670700Sjulian NG_FWD_NEW_DATA(error, item, priv->downlink, m); 427124506Sgreen } else if (hook == priv->ethernet) { 428243882Sglebius M_PREPEND(m, 8, M_NOWAIT); /* Prepend NLPID, OUI, PID */ 429124506Sgreen if (!m) 430124506Sgreen ERROUT(ENOBUFS); 431124506Sgreen mtod(m, u_char *)[0] = HDLC_UI; 432124506Sgreen mtod(m, u_char *)[1] = 0x00; /* pad */ 433124506Sgreen mtod(m, u_char *)[2] = NLPID_SNAP; 434124506Sgreen mtod(m, u_char *)[3] = 0x00; /* OUI */ 435124506Sgreen mtod(m, u_char *)[4] = 0x80; 436124506Sgreen mtod(m, u_char *)[5] = 0xc2; 437124506Sgreen mtod(m, u_char *)[6] = 0x00; /* PID */ 438124506Sgreen mtod(m, u_char *)[7] = 0x07; 439124506Sgreen NG_FWD_NEW_DATA(error, item, priv->downlink, m); 44052419Sjulian } else 441213794Srpaulo panic("%s", __func__); 44252419Sjulian 44352419Sjuliandone: 44470700Sjulian if (item) 44570700Sjulian NG_FREE_ITEM(item); 44670700Sjulian NG_FREE_M(m); 44752419Sjulian return (error); 44852419Sjulian} 44952419Sjulian 45052419Sjulian/* 45152419Sjulian * Nuke node 45252419Sjulian */ 45352419Sjulianstatic int 45470700Sjulianng_rfc1490_shutdown(node_p node) 45552419Sjulian{ 45670784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 45752419Sjulian 45852419Sjulian /* Take down netgraph node */ 45952419Sjulian bzero(priv, sizeof(*priv)); 460184205Sdes free(priv, M_NETGRAPH); 46170784Sjulian NG_NODE_SET_PRIVATE(node, NULL); 46270784Sjulian NG_NODE_UNREF(node); /* let the node escape */ 46352419Sjulian return (0); 46452419Sjulian} 46552419Sjulian 46652419Sjulian/* 46752419Sjulian * Hook disconnection 46852419Sjulian */ 46952419Sjulianstatic int 47052419Sjulianng_rfc1490_disconnect(hook_p hook) 47152419Sjulian{ 47270784Sjulian const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 47352419Sjulian 47470784Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 47570784Sjulian && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) 47670784Sjulian ng_rmnode_self(NG_HOOK_NODE(hook)); 47752419Sjulian else if (hook == priv->downlink) 47852419Sjulian priv->downlink = NULL; 47952419Sjulian else if (hook == priv->inet) 48052419Sjulian priv->inet = NULL; 48152419Sjulian else if (hook == priv->ppp) 48252419Sjulian priv->ppp = NULL; 483124506Sgreen else if (hook == priv->ethernet) 484124506Sgreen priv->ethernet = NULL; 48552419Sjulian else 486213794Srpaulo panic("%s", __func__); 48752419Sjulian return (0); 48852419Sjulian} 48952419Sjulian 490