ng_rfc1490.c revision 139823
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: head/sys/netgraph/ng_rfc1490.c 139823 2005-01-07 01:45:51Z imp $ 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 */ 16868876Sdwmalone MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 16952419Sjulian if (priv == NULL) 17052419Sjulian return (ENOMEM); 17152419Sjulian 172130413Sjulian /* Initialize to default encapsulation method - ietf-ip */ 173130413Sjulian priv->enc = ng_rfc1490_encaps; 174130413Sjulian 17570784Sjulian NG_NODE_SET_PRIVATE(node, priv); 17652419Sjulian 17752419Sjulian /* Done */ 17852419Sjulian return (0); 17952419Sjulian} 18052419Sjulian 18152419Sjulian/* 18252419Sjulian * Give our ok for a hook to be added 18352419Sjulian */ 18452419Sjulianstatic int 18552419Sjulianng_rfc1490_newhook(node_p node, hook_p hook, const char *name) 18652419Sjulian{ 18770784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 18852419Sjulian 18952419Sjulian if (!strcmp(name, NG_RFC1490_HOOK_DOWNSTREAM)) { 19052419Sjulian if (priv->downlink) 19152419Sjulian return (EISCONN); 19252419Sjulian priv->downlink = hook; 19352419Sjulian } else if (!strcmp(name, NG_RFC1490_HOOK_PPP)) { 19452419Sjulian if (priv->ppp) 19552419Sjulian return (EISCONN); 19652419Sjulian priv->ppp = hook; 19752419Sjulian } else if (!strcmp(name, NG_RFC1490_HOOK_INET)) { 19852419Sjulian if (priv->inet) 19952419Sjulian return (EISCONN); 20052419Sjulian priv->inet = hook; 201124506Sgreen } else if (!strcmp(name, NG_RFC1490_HOOK_ETHERNET)) { 202124506Sgreen if (priv->ethernet) 203124506Sgreen return (EISCONN); 204124506Sgreen priv->ethernet = hook; 20552419Sjulian } else 20652419Sjulian return (EINVAL); 20752419Sjulian return (0); 20852419Sjulian} 20952419Sjulian 21052419Sjulian/* 211130413Sjulian * Receive a control message. 21252419Sjulian */ 21352419Sjulianstatic int 21470700Sjulianng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook) 21552419Sjulian{ 216130413Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 217130413Sjulian struct ng_mesg *msg; 218130413Sjulian struct ng_mesg *resp = NULL; 219130413Sjulian int error = 0; 220130413Sjulian 221130413Sjulian NGI_GET_MSG(item, msg); 222130413Sjulian 223130413Sjulian if (msg->header.typecookie == NGM_RFC1490_COOKIE) { 224130413Sjulian switch (msg->header.cmd) { 225130413Sjulian case NGM_RFC1490_SET_ENCAP: 226130413Sjulian { 227130413Sjulian const struct ng_rfc1490_encap_t *enc; 228130413Sjulian char *s; 229130413Sjulian size_t len; 230130413Sjulian 231130413Sjulian if (msg->header.arglen == 0) 232130413Sjulian ERROUT(EINVAL); 233130413Sjulian 234130413Sjulian s = (char *)msg->data; 235130413Sjulian len = msg->header.arglen - 1; 236130413Sjulian 237130413Sjulian /* Search for matching encapsulation method */ 238130413Sjulian for (enc = ng_rfc1490_encaps; enc->method != 0; enc++ ) 239130413Sjulian if ((strlen(enc->name) == len) && 240130413Sjulian !strncmp(enc->name, s, len)) 241130413Sjulian break; /* found */ 242130413Sjulian 243130413Sjulian if (enc->method != 0) 244130413Sjulian priv->enc = enc; 245130413Sjulian else 246130413Sjulian error = EINVAL; 247130413Sjulian break; 248130413Sjulian } 249130413Sjulian case NGM_RFC1490_GET_ENCAP: 250130413Sjulian 251130413Sjulian NG_MKRESPONSE(resp, msg, strlen(priv->enc->name) + 1, M_NOWAIT); 252130413Sjulian if (resp == NULL) 253130413Sjulian ERROUT(ENOMEM); 254130413Sjulian 255130413Sjulian strlcpy((char *)resp->data, priv->enc->name, 256130413Sjulian strlen(priv->enc->name) + 1); 257130413Sjulian break; 258130413Sjulian 259130413Sjulian default: 260130413Sjulian error = EINVAL; 261130413Sjulian break; 262130413Sjulian } 263130413Sjulian } else 264130413Sjulian error = EINVAL; 265130413Sjulian 266130413Sjuliandone: 267130413Sjulian NG_RESPOND_MSG(error, node, item, resp); 268130413Sjulian NG_FREE_MSG(msg); 269130413Sjulian return (error); 27052419Sjulian} 27152419Sjulian 27252419Sjulian/* 27352419Sjulian * Receive data on a hook and encapsulate according to RFC 1490. 27452419Sjulian * Only those nodes marked (*) are supported by this routine so far. 27552419Sjulian * 27652419Sjulian * Q.922 control 27752419Sjulian * | 27852419Sjulian * | 279130413Sjulian * --------------------------------------------------------------------- 280130413Sjulian * | 0x03 | | 281130413Sjulian * UI I Frame Cisco 282130413Sjulian * | | Encapsulation 283130413Sjulian * --------------------------------- -------------- | 284130413Sjulian * | 0x08 | 0x81 |0xCC |0xCF | 0x00 |..01.... |..10.... -------------- 285130413Sjulian * | | | | | 0x80 | | |0x800 | 286130413Sjulian * Q.933 CLNP IP(*) PPP(*) SNAP ISO 8208 ISO 8208 | | 287130413Sjulian * | (rfc1973) | Modulo 8 Modulo 128 IP(*) Others 28852419Sjulian * | | 28952419Sjulian * -------------------- OUI 29052419Sjulian * | | | 29152419Sjulian * L2 ID L3 ID ------------------------- 29252419Sjulian * | User |00-80-C2 |00-00-00 29352419Sjulian * | specified | | 29452419Sjulian * | 0x70 PID Ethertype 29552419Sjulian * | | | 296124506Sgreen * ------------------- -----------------... ---------- 297124506Sgreen * |0x51 |0x4E | |0x4C |0x7 |0xB | |0x806 | 298124506Sgreen * | | | | | | | | | 299130413Sjulian * 7776 Q.922 Others 802.2 802.3(*) 802.6 Others IP(*) Others 30052419Sjulian * 30152419Sjulian * 30252419Sjulian */ 30352419Sjulian 30452419Sjulian#define MAX_ENCAPS_HDR 8 30552419Sjulian#define OUICMP(P,A,B,C) ((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C)) 30652419Sjulian 30752419Sjulianstatic int 30870700Sjulianng_rfc1490_rcvdata(hook_p hook, item_p item) 30952419Sjulian{ 31070784Sjulian const node_p node = NG_HOOK_NODE(hook); 31170784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 31252419Sjulian int error = 0; 31370700Sjulian struct mbuf *m; 31452419Sjulian 31570700Sjulian NGI_GET_M(item, m); 31652419Sjulian if (hook == priv->downlink) { 31797897Sarchie const u_char *start; 31897897Sarchie const u_char *ptr; 31952419Sjulian 320131112Sjulian if (m->m_len < MAX_ENCAPS_HDR 321131112Sjulian && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 32252419Sjulian ERROUT(ENOBUFS); 32397897Sarchie ptr = start = mtod(m, const u_char *); 32452419Sjulian 325130413Sjulian if (priv->enc->method == NG_RFC1490_ENCAP_CISCO) 326130413Sjulian goto switch_on_etype; 327130413Sjulian 32852419Sjulian /* Must be UI frame */ 32952419Sjulian if (*ptr++ != HDLC_UI) 33052419Sjulian ERROUT(0); 33152419Sjulian 33252419Sjulian /* Eat optional zero pad byte */ 33352419Sjulian if (*ptr == 0x00) 33452419Sjulian ptr++; 33552419Sjulian 33652419Sjulian /* Multiplex on NLPID */ 33752419Sjulian switch (*ptr++) { 33852419Sjulian case NLPID_SNAP: 33952419Sjulian if (OUICMP(ptr, 0, 0, 0)) { /* It's an ethertype */ 34052419Sjulian u_int16_t etype; 34152419Sjulian 34252419Sjulian ptr += 3; 343130413Sjulianswitch_on_etype: etype = ntohs(*((const u_int16_t *)ptr)); 34452419Sjulian ptr += 2; 34552419Sjulian m_adj(m, ptr - start); 34652419Sjulian switch (etype) { 34752419Sjulian case ETHERTYPE_IP: 34870700Sjulian NG_FWD_NEW_DATA(error, item, 34970700Sjulian priv->inet, m); 35052419Sjulian break; 35152419Sjulian case ETHERTYPE_ARP: 35252419Sjulian case ETHERTYPE_REVARP: 35352419Sjulian default: 35452419Sjulian ERROUT(0); 35552419Sjulian } 356124506Sgreen } else if (OUICMP(ptr, 0x00, 0x80, 0xc2)) { 357124506Sgreen /* 802.1 bridging */ 358124506Sgreen ptr += 3; 359124506Sgreen if (*ptr++ != 0x00) 360130413Sjulian ERROUT(0); /* unknown PID octet 0 */ 361124506Sgreen if (*ptr++ != 0x07) 362124506Sgreen ERROUT(0); /* not FCS-less 802.3 */ 363124506Sgreen m_adj(m, ptr - start); 364124506Sgreen NG_FWD_NEW_DATA(error, item, priv->ethernet, m); 365124506Sgreen } else /* Other weird stuff... */ 36652419Sjulian ERROUT(0); 36752419Sjulian break; 36852419Sjulian case NLPID_IP: 36952419Sjulian m_adj(m, ptr - start); 37070700Sjulian NG_FWD_NEW_DATA(error, item, priv->inet, m); 37152419Sjulian break; 37252419Sjulian case NLPID_PPP: 37352419Sjulian m_adj(m, ptr - start); 37470700Sjulian NG_FWD_NEW_DATA(error, item, priv->ppp, m); 37552419Sjulian break; 37652419Sjulian case NLPID_Q933: 37752419Sjulian case NLPID_CLNP: 37852419Sjulian case NLPID_ESIS: 37952419Sjulian case NLPID_ISIS: 38052419Sjulian ERROUT(0); 38152419Sjulian default: /* Try PPP (see RFC 1973) */ 38252419Sjulian ptr--; /* NLPID becomes PPP proto */ 38352419Sjulian if ((*ptr & 0x01) == 0x01) 38452419Sjulian ERROUT(0); 38552419Sjulian m_adj(m, ptr - start); 38670700Sjulian NG_FWD_NEW_DATA(error, item, priv->ppp, m); 38752419Sjulian break; 38852419Sjulian } 38952419Sjulian } else if (hook == priv->ppp) { 390111119Simp M_PREPEND(m, 2, M_DONTWAIT); /* Prepend PPP NLPID */ 39152419Sjulian if (!m) 39252419Sjulian ERROUT(ENOBUFS); 39352419Sjulian mtod(m, u_char *)[0] = HDLC_UI; 39452419Sjulian mtod(m, u_char *)[1] = NLPID_PPP; 39570700Sjulian NG_FWD_NEW_DATA(error, item, priv->downlink, m); 39652419Sjulian } else if (hook == priv->inet) { 397130413Sjulian switch (priv->enc->method) { 398130413Sjulian case NG_RFC1490_ENCAP_IETF_IP: 399130413Sjulian M_PREPEND(m, 2, M_DONTWAIT); /* Prepend IP NLPID */ 400130413Sjulian if (!m) 401130413Sjulian ERROUT(ENOBUFS); 402130413Sjulian mtod(m, u_char *)[0] = HDLC_UI; 403130413Sjulian mtod(m, u_char *)[1] = NLPID_IP; 404130413Sjulian break; 405130413Sjulian case NG_RFC1490_ENCAP_IETF_SNAP: 406130413Sjulian /* 407130413Sjulian * According to RFC2427 frame should begin with 408130413Sjulian * HDLC_UI PAD NLIPID OUI PID 409130413Sjulian * 03 00 80 00 00 00 08 00 410130413Sjulian */ 411130413Sjulian M_PREPEND(m, 8, M_DONTWAIT); 412130413Sjulian if (!m) 413130413Sjulian ERROUT(ENOBUFS); 414130413Sjulian mtod(m, u_char *)[0] = HDLC_UI; 415130413Sjulian mtod(m, u_char *)[1] = 0x00; /* PAD */ 416130413Sjulian mtod(m, u_char *)[2] = NLPID_SNAP; 417130413Sjulian bzero((char *)(mtod(m, u_char *) + 3), 3); /* OUI 0-0-0 */ 418130413Sjulian *((u_int16_t *)mtod(m, u_int16_t *) + 6/sizeof(u_int16_t)) 419130413Sjulian = htons(ETHERTYPE_IP); /* PID */ 420130413Sjulian break; 421130413Sjulian case NG_RFC1490_ENCAP_CISCO: 422130413Sjulian M_PREPEND(m, 2, M_DONTWAIT); /* Prepend IP ethertype */ 423130413Sjulian if (!m) 424130413Sjulian ERROUT(ENOBUFS); 425130413Sjulian *((u_int16_t *)mtod(m, u_int16_t *)) = htons(ETHERTYPE_IP); 426130413Sjulian break; 427130413Sjulian } 42870700Sjulian NG_FWD_NEW_DATA(error, item, priv->downlink, m); 429124506Sgreen } else if (hook == priv->ethernet) { 430124506Sgreen M_PREPEND(m, 8, M_DONTWAIT); /* Prepend NLPID, OUI, PID */ 431124506Sgreen if (!m) 432124506Sgreen ERROUT(ENOBUFS); 433124506Sgreen mtod(m, u_char *)[0] = HDLC_UI; 434124506Sgreen mtod(m, u_char *)[1] = 0x00; /* pad */ 435124506Sgreen mtod(m, u_char *)[2] = NLPID_SNAP; 436124506Sgreen mtod(m, u_char *)[3] = 0x00; /* OUI */ 437124506Sgreen mtod(m, u_char *)[4] = 0x80; 438124506Sgreen mtod(m, u_char *)[5] = 0xc2; 439124506Sgreen mtod(m, u_char *)[6] = 0x00; /* PID */ 440124506Sgreen mtod(m, u_char *)[7] = 0x07; 441124506Sgreen NG_FWD_NEW_DATA(error, item, priv->downlink, m); 44252419Sjulian } else 44387599Sobrien panic(__func__); 44452419Sjulian 44552419Sjuliandone: 44670700Sjulian if (item) 44770700Sjulian NG_FREE_ITEM(item); 44870700Sjulian NG_FREE_M(m); 44952419Sjulian return (error); 45052419Sjulian} 45152419Sjulian 45252419Sjulian/* 45352419Sjulian * Nuke node 45452419Sjulian */ 45552419Sjulianstatic int 45670700Sjulianng_rfc1490_shutdown(node_p node) 45752419Sjulian{ 45870784Sjulian const priv_p priv = NG_NODE_PRIVATE(node); 45952419Sjulian 46052419Sjulian /* Take down netgraph node */ 46152419Sjulian bzero(priv, sizeof(*priv)); 46270810Sjulian FREE(priv, M_NETGRAPH); 46370784Sjulian NG_NODE_SET_PRIVATE(node, NULL); 46470784Sjulian NG_NODE_UNREF(node); /* let the node escape */ 46552419Sjulian return (0); 46652419Sjulian} 46752419Sjulian 46852419Sjulian/* 46952419Sjulian * Hook disconnection 47052419Sjulian */ 47152419Sjulianstatic int 47252419Sjulianng_rfc1490_disconnect(hook_p hook) 47352419Sjulian{ 47470784Sjulian const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 47552419Sjulian 47670784Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 47770784Sjulian && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) 47870784Sjulian ng_rmnode_self(NG_HOOK_NODE(hook)); 47952419Sjulian else if (hook == priv->downlink) 48052419Sjulian priv->downlink = NULL; 48152419Sjulian else if (hook == priv->inet) 48252419Sjulian priv->inet = NULL; 48352419Sjulian else if (hook == priv->ppp) 48452419Sjulian priv->ppp = NULL; 485124506Sgreen else if (hook == priv->ethernet) 486124506Sgreen priv->ethernet = NULL; 48752419Sjulian else 48887599Sobrien panic(__func__); 48952419Sjulian return (0); 49052419Sjulian} 49152419Sjulian 492