ng_rfc1490.c revision 139823
138494Sobrien/* 2174294Sobrien * ng_rfc1490.c 338494Sobrien */ 438494Sobrien 538494Sobrien/*- 638494Sobrien * Copyright (c) 1996-1999 Whistle Communications, Inc. 738494Sobrien * All rights reserved. 838494Sobrien * 938494Sobrien * Subject to the following obligations and disclaimer of warranty, use and 1038494Sobrien * redistribution of this software, in source or object code forms, with or 1138494Sobrien * without modifications are expressly permitted by Whistle Communications; 1238494Sobrien * provided, however, that: 1338494Sobrien * 1. Any and all reproductions of the source or object code must include the 1438494Sobrien * copyright notice above and the following disclaimer of warranties; and 1538494Sobrien * 2. No rights are granted, in any manner or form, to use Whistle 1638494Sobrien * Communications, Inc. trademarks, including the mark "WHISTLE 1738494Sobrien * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1838494Sobrien * such appears in the above copyright notice or in the software. 1938494Sobrien * 2042629Sobrien * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 2138494Sobrien * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2238494Sobrien * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2338494Sobrien * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2438494Sobrien * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2538494Sobrien * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2638494Sobrien * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2738494Sobrien * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2838494Sobrien * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2938494Sobrien * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 3038494Sobrien * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 3138494Sobrien * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3238494Sobrien * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3338494Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3438494Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3538494Sobrien * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3638494Sobrien * OF SUCH DAMAGE. 3738494Sobrien * 3838494Sobrien * Author: Julian Elischer <julian@freebsd.org> 3938494Sobrien * 40174294Sobrien * $FreeBSD: head/sys/netgraph/ng_rfc1490.c 139823 2005-01-07 01:45:51Z imp $ 4138494Sobrien * $Whistle: ng_rfc1490.c,v 1.22 1999/11/01 09:24:52 julian Exp $ 4238494Sobrien */ 4338494Sobrien 4438494Sobrien/* 4538494Sobrien * This node does RFC 1490 multiplexing. 4638494Sobrien * 4738494Sobrien * NOTE: RFC 1490 is updated by RFC 2427. 4838494Sobrien */ 4938494Sobrien 5038494Sobrien#include <sys/param.h> 5138494Sobrien#include <sys/systm.h> 5238494Sobrien#include <sys/errno.h> 5338494Sobrien#include <sys/kernel.h> 5438494Sobrien#include <sys/malloc.h> 5538494Sobrien#include <sys/mbuf.h> 5638494Sobrien#include <sys/errno.h> 5738494Sobrien#include <sys/socket.h> 5838494Sobrien 5938494Sobrien#include <net/if.h> 6038494Sobrien#include <netinet/in.h> 6138494Sobrien#include <netinet/if_ether.h> 6238494Sobrien 6338494Sobrien#include <netgraph/ng_message.h> 6438494Sobrien#include <netgraph/netgraph.h> 6538494Sobrien#include <netgraph/ng_parse.h> 6638494Sobrien#include <netgraph/ng_rfc1490.h> 6738494Sobrien 6838494Sobrien/* 6938494Sobrien * DEFINITIONS 7038494Sobrien */ 7138494Sobrien 7238494Sobrien/* Q.922 stuff -- see RFC 1490 */ 7338494Sobrien#define HDLC_UI 0x03 7438494Sobrien 7538494Sobrien#define NLPID_IP 0xCC 7638494Sobrien#define NLPID_PPP 0xCF 7738494Sobrien#define NLPID_SNAP 0x80 7838494Sobrien#define NLPID_Q933 0x08 7938494Sobrien#define NLPID_CLNP 0x81 8038494Sobrien#define NLPID_ESIS 0x82 8138494Sobrien#define NLPID_ISIS 0x83 8238494Sobrien 8338494Sobrien#define ERROUT(x) do { error = (x); goto done; } while (0) 8438494Sobrien 8538494Sobrien/* Encapsulation methods we understand */ 8638494Sobrienenum { 8738494Sobrien NG_RFC1490_ENCAP_IETF_IP = 1, /* see RFC2427, chapter 7, table 1 */ 8838494Sobrien NG_RFC1490_ENCAP_IETF_SNAP, /* see RFC2427, chapter 7, table 2 */ 8938494Sobrien NG_RFC1490_ENCAP_CISCO, /* Cisco's proprietary encapsulation */ 9038494Sobrien}; 9138494Sobrien 9238494Sobrienstruct ng_rfc1490_encap_t { 9338494Sobrien u_int8_t method; 9438494Sobrien const char *name; 9538494Sobrien}; 9638494Sobrien 9738494Sobrienstatic const struct ng_rfc1490_encap_t ng_rfc1490_encaps[] = { 9838494Sobrien { NG_RFC1490_ENCAP_IETF_IP, "ietf-ip" }, 9938494Sobrien { NG_RFC1490_ENCAP_IETF_SNAP, "ietf-snap" }, 10038494Sobrien { NG_RFC1490_ENCAP_CISCO, "cisco" }, 10138494Sobrien { 0, NULL}, 10238494Sobrien}; 10338494Sobrien 10438494Sobrien/* Node private data */ 10538494Sobrienstruct ng_rfc1490_private { 10638494Sobrien hook_p downlink; 10738494Sobrien hook_p ppp; 10838494Sobrien hook_p inet; 10938494Sobrien hook_p ethernet; 11038494Sobrien const struct ng_rfc1490_encap_t *enc; 11138494Sobrien}; 11238494Sobrientypedef struct ng_rfc1490_private *priv_p; 11342629Sobrien 11438494Sobrien/* Netgraph node methods */ 11538494Sobrienstatic ng_constructor_t ng_rfc1490_constructor; 11638494Sobrienstatic ng_rcvmsg_t ng_rfc1490_rcvmsg; 11738494Sobrienstatic ng_shutdown_t ng_rfc1490_shutdown; 11838494Sobrienstatic ng_newhook_t ng_rfc1490_newhook; 11938494Sobrienstatic ng_rcvdata_t ng_rfc1490_rcvdata; 12038494Sobrienstatic ng_disconnect_t ng_rfc1490_disconnect; 12138494Sobrien 12238494Sobrien/* List of commands and how to convert arguments to/from ASCII */ 12338494Sobrienstatic const struct ng_cmdlist ng_rfc1490_cmds[] = { 12438494Sobrien { 12538494Sobrien NGM_RFC1490_COOKIE, 12638494Sobrien NGM_RFC1490_SET_ENCAP, 12738494Sobrien "setencap", 12838494Sobrien &ng_parse_string_type, 12938494Sobrien NULL 13038494Sobrien }, 13138494Sobrien { 13238494Sobrien NGM_RFC1490_COOKIE, 13338494Sobrien NGM_RFC1490_GET_ENCAP, 13438494Sobrien "getencap", 13538494Sobrien NULL, 13638494Sobrien &ng_parse_string_type 13738494Sobrien }, 13838494Sobrien { 0 } 13952894Sobrien}; 14038494Sobrien 14138494Sobrien/* Node type descriptor */ 14238494Sobrienstatic struct ng_type typestruct = { 14338494Sobrien .version = NG_ABI_VERSION, 14438494Sobrien .name = NG_RFC1490_NODE_TYPE, 14538494Sobrien .constructor = ng_rfc1490_constructor, 14638494Sobrien .rcvmsg = ng_rfc1490_rcvmsg, 14738494Sobrien .shutdown = ng_rfc1490_shutdown, 14838494Sobrien .newhook = ng_rfc1490_newhook, 14938494Sobrien .rcvdata = ng_rfc1490_rcvdata, 15038494Sobrien .disconnect = ng_rfc1490_disconnect, 15138494Sobrien .cmdlist = ng_rfc1490_cmds, 15238494Sobrien}; 15338494SobrienNETGRAPH_INIT(rfc1490, &typestruct); 15438494Sobrien 15538494Sobrien/************************************************************************ 15638494Sobrien NETGRAPH NODE STUFF 15738494Sobrien ************************************************************************/ 15838494Sobrien 15951292Sobrien/* 16038494Sobrien * Node constructor 16138494Sobrien */ 16238494Sobrienstatic int 16338494Sobrienng_rfc1490_constructor(node_p node) 16438494Sobrien{ 16538494Sobrien priv_p priv; 16638494Sobrien 16738494Sobrien /* Allocate private structure */ 16838494Sobrien MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 16938494Sobrien if (priv == NULL) 17038494Sobrien return (ENOMEM); 17138494Sobrien 17238494Sobrien /* Initialize to default encapsulation method - ietf-ip */ 17338494Sobrien priv->enc = ng_rfc1490_encaps; 17438494Sobrien 17538494Sobrien NG_NODE_SET_PRIVATE(node, priv); 17638494Sobrien 17738494Sobrien /* Done */ 17838494Sobrien return (0); 17938494Sobrien} 18038494Sobrien 18138494Sobrien/* 18238494Sobrien * Give our ok for a hook to be added 18338494Sobrien */ 18438494Sobrienstatic int 18538494Sobrienng_rfc1490_newhook(node_p node, hook_p hook, const char *name) 18638494Sobrien{ 18738494Sobrien const priv_p priv = NG_NODE_PRIVATE(node); 18838494Sobrien 18938494Sobrien if (!strcmp(name, NG_RFC1490_HOOK_DOWNSTREAM)) { 19038494Sobrien if (priv->downlink) 19138494Sobrien return (EISCONN); 19238494Sobrien priv->downlink = hook; 19338494Sobrien } else if (!strcmp(name, NG_RFC1490_HOOK_PPP)) { 19438494Sobrien if (priv->ppp) 19538494Sobrien return (EISCONN); 19638494Sobrien priv->ppp = hook; 19738494Sobrien } else if (!strcmp(name, NG_RFC1490_HOOK_INET)) { 19838494Sobrien if (priv->inet) 19938494Sobrien return (EISCONN); 20038494Sobrien priv->inet = hook; 201174294Sobrien } else if (!strcmp(name, NG_RFC1490_HOOK_ETHERNET)) { 202174294Sobrien if (priv->ethernet) 203174294Sobrien return (EISCONN); 204174294Sobrien priv->ethernet = hook; 205174294Sobrien } else 206174294Sobrien return (EINVAL); 20738494Sobrien return (0); 20838494Sobrien} 209174294Sobrien 21038494Sobrien/* 21138494Sobrien * Receive a control message. 21238494Sobrien */ 21338494Sobrienstatic int 21438494Sobrienng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook) 21538494Sobrien{ 21638494Sobrien const priv_p priv = NG_NODE_PRIVATE(node); 21738494Sobrien struct ng_mesg *msg; 21838494Sobrien struct ng_mesg *resp = NULL; 21938494Sobrien int error = 0; 22038494Sobrien 22138494Sobrien NGI_GET_MSG(item, msg); 22238494Sobrien 22338494Sobrien if (msg->header.typecookie == NGM_RFC1490_COOKIE) { 22438494Sobrien switch (msg->header.cmd) { 22538494Sobrien case NGM_RFC1490_SET_ENCAP: 22638494Sobrien { 22738494Sobrien const struct ng_rfc1490_encap_t *enc; 22838494Sobrien char *s; 22938494Sobrien size_t len; 23038494Sobrien 23138494Sobrien if (msg->header.arglen == 0) 23238494Sobrien ERROUT(EINVAL); 23338494Sobrien 23438494Sobrien s = (char *)msg->data; 23582794Sobrien len = msg->header.arglen - 1; 23638494Sobrien 23738494Sobrien /* Search for matching encapsulation method */ 23838494Sobrien for (enc = ng_rfc1490_encaps; enc->method != 0; enc++ ) 23938494Sobrien if ((strlen(enc->name) == len) && 24038494Sobrien !strncmp(enc->name, s, len)) 24138494Sobrien break; /* found */ 24238494Sobrien 24351292Sobrien if (enc->method != 0) 24438494Sobrien priv->enc = enc; 24538494Sobrien else 24682794Sobrien error = EINVAL; 24738494Sobrien break; 24838494Sobrien } 24938494Sobrien case NGM_RFC1490_GET_ENCAP: 25038494Sobrien 25138494Sobrien NG_MKRESPONSE(resp, msg, strlen(priv->enc->name) + 1, M_NOWAIT); 25238494Sobrien if (resp == NULL) 25338494Sobrien ERROUT(ENOMEM); 25438494Sobrien 25538494Sobrien strlcpy((char *)resp->data, priv->enc->name, 25638494Sobrien strlen(priv->enc->name) + 1); 25782794Sobrien break; 25838494Sobrien 25938494Sobrien default: 26038494Sobrien error = EINVAL; 26138494Sobrien break; 26238494Sobrien } 26338494Sobrien } else 26438494Sobrien error = EINVAL; 26538494Sobrien 26638494Sobriendone: 26738494Sobrien NG_RESPOND_MSG(error, node, item, resp); 26838494Sobrien NG_FREE_MSG(msg); 26938494Sobrien return (error); 27038494Sobrien} 27138494Sobrien 27238494Sobrien/* 27338494Sobrien * Receive data on a hook and encapsulate according to RFC 1490. 27438494Sobrien * Only those nodes marked (*) are supported by this routine so far. 27538494Sobrien * 27638494Sobrien * Q.922 control 27738494Sobrien * | 27838494Sobrien * | 27938494Sobrien * --------------------------------------------------------------------- 28038494Sobrien * | 0x03 | | 28138494Sobrien * UI I Frame Cisco 28238494Sobrien * | | Encapsulation 28338494Sobrien * --------------------------------- -------------- | 28438494Sobrien * | 0x08 | 0x81 |0xCC |0xCF | 0x00 |..01.... |..10.... -------------- 28538494Sobrien * | | | | | 0x80 | | |0x800 | 28638494Sobrien * Q.933 CLNP IP(*) PPP(*) SNAP ISO 8208 ISO 8208 | | 28738494Sobrien * | (rfc1973) | Modulo 8 Modulo 128 IP(*) Others 28838494Sobrien * | | 28938494Sobrien * -------------------- OUI 29038494Sobrien * | | | 29138494Sobrien * L2 ID L3 ID ------------------------- 29238494Sobrien * | User |00-80-C2 |00-00-00 29338494Sobrien * | specified | | 29438494Sobrien * | 0x70 PID Ethertype 29538494Sobrien * | | | 29638494Sobrien * ------------------- -----------------... ---------- 29738494Sobrien * |0x51 |0x4E | |0x4C |0x7 |0xB | |0x806 | 29838494Sobrien * | | | | | | | | | 29938494Sobrien * 7776 Q.922 Others 802.2 802.3(*) 802.6 Others IP(*) Others 30038494Sobrien * 30182794Sobrien * 30238494Sobrien */ 30338494Sobrien 30438494Sobrien#define MAX_ENCAPS_HDR 8 30538494Sobrien#define OUICMP(P,A,B,C) ((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C)) 30638494Sobrien 307174294Sobrienstatic int 30838494Sobrienng_rfc1490_rcvdata(hook_p hook, item_p item) 30938494Sobrien{ 31038494Sobrien const node_p node = NG_HOOK_NODE(hook); 311174294Sobrien const priv_p priv = NG_NODE_PRIVATE(node); 31238494Sobrien int error = 0; 31338494Sobrien struct mbuf *m; 31438494Sobrien 315174294Sobrien NGI_GET_M(item, m); 31638494Sobrien if (hook == priv->downlink) { 317174294Sobrien const u_char *start; 318174294Sobrien const u_char *ptr; 319174294Sobrien 320174294Sobrien if (m->m_len < MAX_ENCAPS_HDR 321174294Sobrien && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 322174294Sobrien ERROUT(ENOBUFS); 323174294Sobrien ptr = start = mtod(m, const u_char *); 324174294Sobrien 325174294Sobrien if (priv->enc->method == NG_RFC1490_ENCAP_CISCO) 326174294Sobrien goto switch_on_etype; 32738494Sobrien 32838494Sobrien /* Must be UI frame */ 32938494Sobrien if (*ptr++ != HDLC_UI) 33038494Sobrien ERROUT(0); 33138494Sobrien 33238494Sobrien /* Eat optional zero pad byte */ 33338494Sobrien if (*ptr == 0x00) 33438494Sobrien ptr++; 33538494Sobrien 33638494Sobrien /* Multiplex on NLPID */ 33738494Sobrien switch (*ptr++) { 33838494Sobrien case NLPID_SNAP: 33938494Sobrien if (OUICMP(ptr, 0, 0, 0)) { /* It's an ethertype */ 34038494Sobrien u_int16_t etype; 34138494Sobrien 34238494Sobrien ptr += 3; 34338494Sobrienswitch_on_etype: etype = ntohs(*((const u_int16_t *)ptr)); 34438494Sobrien ptr += 2; 34538494Sobrien m_adj(m, ptr - start); 34638494Sobrien switch (etype) { 34738494Sobrien case ETHERTYPE_IP: 34838494Sobrien NG_FWD_NEW_DATA(error, item, 34938494Sobrien priv->inet, m); 35038494Sobrien break; 35138494Sobrien case ETHERTYPE_ARP: 35238494Sobrien case ETHERTYPE_REVARP: 353174294Sobrien default: 35438494Sobrien ERROUT(0); 355174294Sobrien } 356174294Sobrien } else if (OUICMP(ptr, 0x00, 0x80, 0xc2)) { 35738494Sobrien /* 802.1 bridging */ 358174294Sobrien ptr += 3; 359174294Sobrien if (*ptr++ != 0x00) 36038494Sobrien ERROUT(0); /* unknown PID octet 0 */ 361174294Sobrien if (*ptr++ != 0x07) 362174294Sobrien ERROUT(0); /* not FCS-less 802.3 */ 363174294Sobrien m_adj(m, ptr - start); 364174294Sobrien NG_FWD_NEW_DATA(error, item, priv->ethernet, m); 365174294Sobrien } else /* Other weird stuff... */ 366174294Sobrien ERROUT(0); 367174294Sobrien break; 368174294Sobrien case NLPID_IP: 369174294Sobrien m_adj(m, ptr - start); 370174294Sobrien NG_FWD_NEW_DATA(error, item, priv->inet, m); 371174294Sobrien break; 372174294Sobrien case NLPID_PPP: 373174294Sobrien m_adj(m, ptr - start); 37438494Sobrien NG_FWD_NEW_DATA(error, item, priv->ppp, m); 37538494Sobrien break; 37638494Sobrien case NLPID_Q933: 37738494Sobrien case NLPID_CLNP: 37838494Sobrien case NLPID_ESIS: 37941142Sobrien case NLPID_ISIS: 38041142Sobrien ERROUT(0); 38141142Sobrien default: /* Try PPP (see RFC 1973) */ 38241142Sobrien ptr--; /* NLPID becomes PPP proto */ 38341142Sobrien if ((*ptr & 0x01) == 0x01) 38441142Sobrien ERROUT(0); 38541142Sobrien m_adj(m, ptr - start); 38641142Sobrien NG_FWD_NEW_DATA(error, item, priv->ppp, m); 38741142Sobrien break; 38841142Sobrien } 38941142Sobrien } else if (hook == priv->ppp) { 39041142Sobrien M_PREPEND(m, 2, M_DONTWAIT); /* Prepend PPP NLPID */ 39141142Sobrien if (!m) 39241142Sobrien ERROUT(ENOBUFS); 39341142Sobrien mtod(m, u_char *)[0] = HDLC_UI; 39441142Sobrien mtod(m, u_char *)[1] = NLPID_PPP; 39541142Sobrien NG_FWD_NEW_DATA(error, item, priv->downlink, m); 39641142Sobrien } else if (hook == priv->inet) { 39741142Sobrien switch (priv->enc->method) { 39841142Sobrien case NG_RFC1490_ENCAP_IETF_IP: 39941142Sobrien M_PREPEND(m, 2, M_DONTWAIT); /* Prepend IP NLPID */ 40038494Sobrien if (!m) 40138494Sobrien ERROUT(ENOBUFS); 40238494Sobrien mtod(m, u_char *)[0] = HDLC_UI; 40341142Sobrien mtod(m, u_char *)[1] = NLPID_IP; 40441142Sobrien break; 40538494Sobrien case NG_RFC1490_ENCAP_IETF_SNAP: 40638494Sobrien /* 40738494Sobrien * According to RFC2427 frame should begin with 40838494Sobrien * HDLC_UI PAD NLIPID OUI PID 40938494Sobrien * 03 00 80 00 00 00 08 00 41038494Sobrien */ 41138494Sobrien M_PREPEND(m, 8, M_DONTWAIT); 41238494Sobrien if (!m) 41338494Sobrien ERROUT(ENOBUFS); 41438494Sobrien mtod(m, u_char *)[0] = HDLC_UI; 41538494Sobrien mtod(m, u_char *)[1] = 0x00; /* PAD */ 41638494Sobrien mtod(m, u_char *)[2] = NLPID_SNAP; 41738494Sobrien bzero((char *)(mtod(m, u_char *) + 3), 3); /* OUI 0-0-0 */ 41838494Sobrien *((u_int16_t *)mtod(m, u_int16_t *) + 6/sizeof(u_int16_t)) 41938494Sobrien = htons(ETHERTYPE_IP); /* PID */ 42038494Sobrien break; 42138494Sobrien case NG_RFC1490_ENCAP_CISCO: 42238494Sobrien M_PREPEND(m, 2, M_DONTWAIT); /* Prepend IP ethertype */ 423174294Sobrien if (!m) 42438494Sobrien ERROUT(ENOBUFS); 42538494Sobrien *((u_int16_t *)mtod(m, u_int16_t *)) = htons(ETHERTYPE_IP); 42638494Sobrien break; 42738494Sobrien } 42838494Sobrien NG_FWD_NEW_DATA(error, item, priv->downlink, m); 42938494Sobrien } else if (hook == priv->ethernet) { 43038494Sobrien M_PREPEND(m, 8, M_DONTWAIT); /* Prepend NLPID, OUI, PID */ 43138494Sobrien if (!m) 43238494Sobrien ERROUT(ENOBUFS); 43338494Sobrien mtod(m, u_char *)[0] = HDLC_UI; 43438494Sobrien mtod(m, u_char *)[1] = 0x00; /* pad */ 43538494Sobrien mtod(m, u_char *)[2] = NLPID_SNAP; 43638494Sobrien mtod(m, u_char *)[3] = 0x00; /* OUI */ 43738494Sobrien mtod(m, u_char *)[4] = 0x80; 43838494Sobrien mtod(m, u_char *)[5] = 0xc2; 43938494Sobrien mtod(m, u_char *)[6] = 0x00; /* PID */ 44038494Sobrien mtod(m, u_char *)[7] = 0x07; 44138494Sobrien NG_FWD_NEW_DATA(error, item, priv->downlink, m); 44238494Sobrien } else 44338494Sobrien panic(__func__); 44438494Sobrien 44538494Sobriendone: 44638494Sobrien if (item) 44738494Sobrien NG_FREE_ITEM(item); 44838494Sobrien NG_FREE_M(m); 44938494Sobrien return (error); 45038494Sobrien} 45138494Sobrien 45238494Sobrien/* 45338494Sobrien * Nuke node 45438494Sobrien */ 45538494Sobrienstatic int 45638494Sobrienng_rfc1490_shutdown(node_p node) 45738494Sobrien{ 45838494Sobrien const priv_p priv = NG_NODE_PRIVATE(node); 45938494Sobrien 46038494Sobrien /* Take down netgraph node */ 46138494Sobrien bzero(priv, sizeof(*priv)); 46238494Sobrien FREE(priv, M_NETGRAPH); 46338494Sobrien NG_NODE_SET_PRIVATE(node, NULL); 46438494Sobrien NG_NODE_UNREF(node); /* let the node escape */ 46538494Sobrien return (0); 46638494Sobrien} 46738494Sobrien 46838494Sobrien/* 46938494Sobrien * Hook disconnection 47038494Sobrien */ 47138494Sobrienstatic int 47238494Sobrienng_rfc1490_disconnect(hook_p hook) 47338494Sobrien{ 47438494Sobrien const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 47538494Sobrien 47638494Sobrien if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 47738494Sobrien && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) 47838494Sobrien ng_rmnode_self(NG_HOOK_NODE(hook)); 47938494Sobrien else if (hook == priv->downlink) 48038494Sobrien priv->downlink = NULL; 48138494Sobrien else if (hook == priv->inet) 48238494Sobrien priv->inet = NULL; 48338494Sobrien else if (hook == priv->ppp) 48438494Sobrien priv->ppp = NULL; 48538494Sobrien else if (hook == priv->ethernet) 48638494Sobrien priv->ethernet = NULL; 48738494Sobrien else 48838494Sobrien panic(__func__); 48938494Sobrien return (0); 49038494Sobrien} 49138494Sobrien 49238494Sobrien