ng_rfc1490.c revision 220768
150477Speter/*
233548Sjkh * ng_rfc1490.c
32893Sdfr */
42893Sdfr
533548Sjkh/*-
633548Sjkh * Copyright (c) 1996-1999 Whistle Communications, Inc.
72893Sdfr * All rights reserved.
82893Sdfr *
92893Sdfr * Subject to the following obligations and disclaimer of warranty, use and
102893Sdfr * redistribution of this software, in source or object code forms, with or
112893Sdfr * without modifications are expressly permitted by Whistle Communications;
122893Sdfr * provided, however, that:
132893Sdfr * 1. Any and all reproductions of the source or object code must include the
142893Sdfr *    copyright notice above and the following disclaimer of warranties; and
152893Sdfr * 2. No rights are granted, in any manner or form, to use Whistle
162893Sdfr *    Communications, Inc. trademarks, including the mark "WHISTLE
172893Sdfr *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
182893Sdfr *    such appears in the above copyright notice or in the software.
192893Sdfr *
202893Sdfr * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
212893Sdfr * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
222893Sdfr * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
232893Sdfr * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
242893Sdfr * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
252893Sdfr * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
262893Sdfr * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
272893Sdfr * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
282893Sdfr * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
292893Sdfr * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
302893Sdfr * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
312893Sdfr * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
322893Sdfr * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
332893Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342893Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35139776Simp * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
362893Sdfr * OF SUCH DAMAGE.
378876Srgrimes *
382893Sdfr * Author: Julian Elischer <julian@freebsd.org>
392893Sdfr *
408876Srgrimes * $FreeBSD: head/sys/netgraph/ng_rfc1490.c 220768 2011-04-18 09:12:27Z glebius $
412893Sdfr * $Whistle: ng_rfc1490.c,v 1.22 1999/11/01 09:24:52 julian Exp $
428876Srgrimes */
432893Sdfr
442893Sdfr/*
452893Sdfr * This node does RFC 1490 multiplexing.
462893Sdfr *
478876Srgrimes * NOTE: RFC 1490 is updated by RFC 2427.
482893Sdfr */
492893Sdfr
502893Sdfr#include <sys/param.h>
512893Sdfr#include <sys/systm.h>
522893Sdfr#include <sys/errno.h>
5340651Sbde#include <sys/kernel.h>
542893Sdfr#include <sys/malloc.h>
55164033Srwatson#include <sys/mbuf.h>
562893Sdfr#include <sys/errno.h>
572893Sdfr#include <sys/socket.h>
582893Sdfr
592893Sdfr#include <net/if.h>
6060041Sphk#include <netinet/in.h>
612893Sdfr#include <netinet/if_ether.h>
6224131Sbde
632893Sdfr#include <netgraph/ng_message.h>
6433548Sjkh#include <netgraph/netgraph.h>
65120492Sfjoe#include <netgraph/ng_parse.h>
66102391Sbde#include <netgraph/ng_rfc1490.h>
672893Sdfr
6877162Sru/*
6977162Sru * DEFINITIONS
70120492Sfjoe */
7177162Sru
7277162Sru/* Q.922 stuff -- see RFC 1490 */
7377162Sru#define HDLC_UI		0x03
742893Sdfr
75137036Sphk#define NLPID_IP	0xCC
76137036Sphk#define NLPID_PPP	0xCF
77137036Sphk#define NLPID_SNAP	0x80
78138471Sphk#define NLPID_Q933	0x08
79138471Sphk#define NLPID_CLNP	0x81
80138471Sphk#define NLPID_ESIS	0x82
81166559Srodrigc#define NLPID_ISIS	0x83
82138471Sphk
83152610Srodrigc#define ERROUT(x)	do { error = (x); goto done; } while (0)
84166340Srodrigc
85138471Sphk/* Encapsulation methods we understand */
86138471Sphkenum {
87138471Sphk	NG_RFC1490_ENCAP_IETF_IP = 1,	/* see RFC2427, chapter 7, table 1 */
8856674Snyan	NG_RFC1490_ENCAP_IETF_SNAP,	/* see RFC2427, chapter 7, table 2 */
8956674Snyan	NG_RFC1490_ENCAP_CISCO,		/* Cisco's proprietary encapsulation */
9056674Snyan};
9156674Snyan
9256674Snyanstruct ng_rfc1490_encap_t {
9356674Snyan	u_int8_t	method;
9456674Snyan	const char	*name;
9556674Snyan};
9656674Snyan
9756674Snyanstatic const struct ng_rfc1490_encap_t ng_rfc1490_encaps[] = {
9856674Snyan	{ NG_RFC1490_ENCAP_IETF_IP,	"ietf-ip" },
99151897Srwatson	{ NG_RFC1490_ENCAP_IETF_SNAP,	"ietf-snap" },
100151897Srwatson	{ NG_RFC1490_ENCAP_CISCO,	"cisco" },
10130309Sphk	{ 0, NULL},
102120492Sfjoe};
103120492Sfjoe
104138471Sphk/* Node private data */
105138471Sphkstruct ng_rfc1490_private {
106132023Salfred	hook_p  downlink;
107170188Strhodes	hook_p  ppp;
108138471Sphk	hook_p  inet;
109101777Sphk	hook_p  ethernet;
110101777Sphk	const struct ng_rfc1490_encap_t *enc;
111101777Sphk};
112101777Sphktypedef struct ng_rfc1490_private *priv_p;
11312338Sbde
114134345Stjr/* Netgraph node methods */
115134345Stjrstatic ng_constructor_t	ng_rfc1490_constructor;
116134345Stjrstatic ng_rcvmsg_t	ng_rfc1490_rcvmsg;
11733548Sjkhstatic ng_shutdown_t	ng_rfc1490_shutdown;
118166558Srodrigcstatic ng_newhook_t	ng_rfc1490_newhook;
11933548Sjkhstatic ng_rcvdata_t	ng_rfc1490_rcvdata;
12033548Sjkhstatic ng_disconnect_t	ng_rfc1490_disconnect;
121138471Sphk
122138471Sphk/* List of commands and how to convert arguments to/from ASCII */
12333548Sjkhstatic const struct ng_cmdlist ng_rfc1490_cmds[] = {
124138471Sphk	{
125138471Sphk	  NGM_RFC1490_COOKIE,
126138471Sphk	  NGM_RFC1490_SET_ENCAP,
127138471Sphk	  "setencap",
128138471Sphk	  &ng_parse_string_type,
129138471Sphk	  NULL
130138471Sphk	},
131138471Sphk	{
132138471Sphk	  NGM_RFC1490_COOKIE,
133138471Sphk	  NGM_RFC1490_GET_ENCAP,
134138471Sphk	  "getencap",
135138471Sphk	  NULL,
136138471Sphk	  &ng_parse_string_type
137138471Sphk	},
138138471Sphk	{ 0 }
139138471Sphk};
140134345Stjr
141134345Stjr/* Node type descriptor */
142134345Stjrstatic struct ng_type typestruct = {
143134345Stjr	.version =	NG_ABI_VERSION,
144134345Stjr	.name =		NG_RFC1490_NODE_TYPE,
145134345Stjr	.constructor =	ng_rfc1490_constructor,
146134345Stjr	.rcvmsg =	ng_rfc1490_rcvmsg,
147134345Stjr	.shutdown =	ng_rfc1490_shutdown,
148134345Stjr	.newhook =	ng_rfc1490_newhook,
149134345Stjr	.rcvdata =	ng_rfc1490_rcvdata,
150138471Sphk	.disconnect =	ng_rfc1490_disconnect,
151138471Sphk	.cmdlist =	ng_rfc1490_cmds,
152138471Sphk};
153138471SphkNETGRAPH_INIT(rfc1490, &typestruct);
154138471Sphk
155138471Sphk/************************************************************************
156138471Sphk			NETGRAPH NODE STUFF
157138471Sphk ************************************************************************/
158138471Sphk
159138471Sphk/*
160152595Srodrigc * Node constructor
161152595Srodrigc */
162138471Sphkstatic int
163138471Sphkng_rfc1490_constructor(node_p node)
164152595Srodrigc{
165152595Srodrigc	priv_p priv;
166138471Sphk
167138471Sphk	/* Allocate private structure */
16833548Sjkh	priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
169152610Srodrigc
170152610Srodrigc	/* Initialize to default encapsulation method - ietf-ip */
171152610Srodrigc	priv->enc = ng_rfc1490_encaps;
172138471Sphk
173138471Sphk	NG_NODE_SET_PRIVATE(node, priv);
17433548Sjkh
17533548Sjkh	/* Done */
17633548Sjkh	return (0);
17733548Sjkh}
17833548Sjkh
17933548Sjkh/*
18033548Sjkh * Give our ok for a hook to be added
18133548Sjkh */
18233548Sjkhstatic int
18333548Sjkhng_rfc1490_newhook(node_p node, hook_p hook, const char *name)
18433548Sjkh{
18533548Sjkh	const priv_p priv = NG_NODE_PRIVATE(node);
186144058Sjeff
187144058Sjeff	if (!strcmp(name, NG_RFC1490_HOOK_DOWNSTREAM)) {
18833548Sjkh		if (priv->downlink)
18933548Sjkh			return (EISCONN);
19033548Sjkh		priv->downlink = hook;
19133548Sjkh	} else if (!strcmp(name, NG_RFC1490_HOOK_PPP)) {
19233548Sjkh		if (priv->ppp)
19333548Sjkh			return (EISCONN);
19433548Sjkh		priv->ppp = hook;
19533548Sjkh	} else if (!strcmp(name, NG_RFC1490_HOOK_INET)) {
19633548Sjkh		if (priv->inet)
19733548Sjkh			return (EISCONN);
198138471Sphk		priv->inet = hook;
199138471Sphk	} else if (!strcmp(name, NG_RFC1490_HOOK_ETHERNET)) {
200138471Sphk		if (priv->ethernet)
201138471Sphk			return (EISCONN);
202138471Sphk		priv->ethernet = hook;
203138471Sphk	} else
204138471Sphk		return (EINVAL);
205138471Sphk	return (0);
206138471Sphk}
207138471Sphk
208138471Sphk/*
209138471Sphk * Receive a control message.
210138471Sphk */
211138471Sphkstatic int
212138471Sphkng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook)
213138471Sphk{
214138471Sphk	const priv_p priv = NG_NODE_PRIVATE(node);
215138471Sphk	struct ng_mesg *msg;
216138471Sphk	struct ng_mesg *resp = NULL;
217138471Sphk	int error = 0;
218138471Sphk
219138471Sphk	NGI_GET_MSG(item, msg);
220138471Sphk
221138471Sphk	if (msg->header.typecookie == NGM_RFC1490_COOKIE) {
222138471Sphk		switch (msg->header.cmd) {
223138471Sphk		case NGM_RFC1490_SET_ENCAP:
224138471Sphk		{
225138471Sphk			const struct ng_rfc1490_encap_t *enc;
226138471Sphk			char *s;
227138471Sphk			size_t len;
228138471Sphk
229138471Sphk			if (msg->header.arglen == 0)
230138471Sphk				ERROUT(EINVAL);
2312893Sdfr
2328876Srgrimes			s = (char *)msg->data;
2332893Sdfr			len = msg->header.arglen - 1;
2348876Srgrimes
2352893Sdfr			/* Search for matching encapsulation method */
23612144Sphk			for (enc = ng_rfc1490_encaps; enc->method != 0; enc++ )
237138471Sphk				if ((strlen(enc->name) == len) &&
2382893Sdfr				    !strncmp(enc->name, s, len))
2392893Sdfr					break;	/* found */
24033548Sjkh
24133548Sjkh			if (enc->method != 0)
242132902Sphk				priv->enc = enc;
243138689Sphk			else
24433548Sjkh				error = EINVAL;
245138471Sphk			break;
2462893Sdfr		}
247138471Sphk		case NGM_RFC1490_GET_ENCAP:
248138471Sphk
249138471Sphk			NG_MKRESPONSE(resp, msg, strlen(priv->enc->name) + 1, M_NOWAIT);
2502893Sdfr			if (resp == NULL)
25133548Sjkh				ERROUT(ENOMEM);
25233548Sjkh
2532893Sdfr			strlcpy((char *)resp->data, priv->enc->name,
2542893Sdfr			    strlen(priv->enc->name) + 1);
255165836Srodrigc			break;
25633548Sjkh
257138689Sphk		default:
258158924Srodrigc			error = EINVAL;
259165022Srodrigc			break;
260165022Srodrigc		}
261165022Srodrigc	} else
262165022Srodrigc		error = EINVAL;
263165022Srodrigc
264165022Srodrigcdone:
265165022Srodrigc	NG_RESPOND_MSG(error, node, item, resp);
266138689Sphk	NG_FREE_MSG(msg);
267165022Srodrigc	return (error);
268138689Sphk}
269137036Sphk
270138471Sphk/*
271140048Sphk * Receive data on a hook and encapsulate according to RFC 1490.
272133287Sphk * Only those nodes marked (*) are supported by this routine so far.
273133287Sphk *
2742893Sdfr *                            Q.922 control
2752893Sdfr *                                 |
2762893Sdfr *                                 |
277132023Salfred *            ---------------------------------------------------------------------
278138471Sphk *            | 0x03                                     |                        |
279138471Sphk *           UI                                       I Frame                   Cisco
280137036Sphk *            |                                          |                  Encapsulation
281137036Sphk *      ---------------------------------         --------------                  |
282137036Sphk *      | 0x08  | 0x81  |0xCC   |0xCF   | 0x00    |..01....    |..10....   --------------
283137036Sphk *      |       |       |       |       | 0x80    |            |           |0x800       |
284137036Sphk *     Q.933   CLNP    IP(*)   PPP(*)  SNAP     ISO 8208    ISO 8208       |            |
285160939Sdelphij *      |                    (rfc1973)  |       Modulo 8    Modulo 128     IP(*)     Others
286160939Sdelphij *      |                               |
287160939Sdelphij *      --------------------           OUI
288160939Sdelphij *      |                  |            |
289138471Sphk *     L2 ID              L3 ID      -------------------------
290138471Sphk *      |               User         |00-80-C2               |00-00-00
29133548Sjkh *      |               specified    |                       |
29233548Sjkh *      |               0x70        PID                     Ethertype
29333548Sjkh *      |                            |                       |
29433548Sjkh *      -------------------        -----------------...     ----------
295164033Srwatson *      |0x51 |0x4E |     |0x4C    |0x7      |0xB  |        |0x806   |
296164033Srwatson *      |     |     |     |        |         |     |        |        |
297164033Srwatson *     7776  Q.922 Others 802.2   802.3(*)  802.6 Others    IP(*)   Others
298164033Srwatson *
299164033Srwatson *
300164033Srwatson */
301164033Srwatson
30283366Sjulian#define MAX_ENCAPS_HDR	8
303164033Srwatson#define OUICMP(P,A,B,C)	((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C))
30433548Sjkh
305164033Srwatsonstatic int
306137036Sphkng_rfc1490_rcvdata(hook_p hook, item_p item)
307137036Sphk{
308137036Sphk	const node_p node = NG_HOOK_NODE(hook);
309137036Sphk	const priv_p priv = NG_NODE_PRIVATE(node);
310137036Sphk	int error = 0;
311137036Sphk	struct mbuf *m;
312137036Sphk
313123963Sbde	NGI_GET_M(item, m);
314165836Srodrigc	if (hook == priv->downlink) {
315165836Srodrigc		const u_char *start;
316165836Srodrigc		const u_char *ptr;
317165836Srodrigc
318165836Srodrigc		if (m->m_len < MAX_ENCAPS_HDR
319165836Srodrigc		    && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
320165836Srodrigc			ERROUT(ENOBUFS);
321165836Srodrigc		ptr = start = mtod(m, const u_char *);
322123963Sbde
323123873Strhodes		if (priv->enc->method == NG_RFC1490_ENCAP_CISCO)
324123873Strhodes			goto switch_on_etype;
325123963Sbde
32633548Sjkh		/* Must be UI frame */
3272893Sdfr		if (*ptr++ != HDLC_UI)
3282893Sdfr			ERROUT(0);
32933548Sjkh
330125796Sbde		/* Eat optional zero pad byte */
3312893Sdfr		if (*ptr == 0x00)
332138471Sphk			ptr++;
333138471Sphk
334149720Sssouhlal		/* Multiplex on NLPID */
335132902Sphk		switch (*ptr++) {
33633548Sjkh		case NLPID_SNAP:
33733548Sjkh			if (OUICMP(ptr, 0, 0, 0)) {	/* It's an ethertype */
338132902Sphk				u_int16_t etype;
339132902Sphk
3408876Srgrimes				ptr += 3;
34155756Sphkswitch_on_etype:		etype = ntohs(*((const u_int16_t *)ptr));
342149720Sssouhlal				ptr += 2;
34355756Sphk				m_adj(m, ptr - start);
3442893Sdfr				switch (etype) {
3452893Sdfr				case ETHERTYPE_IP:
34633548Sjkh					NG_FWD_NEW_DATA(error, item,
34733548Sjkh					    priv->inet, m);
3482893Sdfr					break;
349164033Srwatson				case ETHERTYPE_ARP:
350164033Srwatson				case ETHERTYPE_REVARP:
351164033Srwatson				default:
352164033Srwatson					ERROUT(0);
353164033Srwatson				}
354164033Srwatson			} else if (OUICMP(ptr, 0x00, 0x80, 0xc2)) {
355164033Srwatson				/* 802.1 bridging */
356164033Srwatson				ptr += 3;
357164033Srwatson				if (*ptr++ != 0x00)
35833548Sjkh					ERROUT(0);	/* unknown PID octet 0 */
35933548Sjkh				if (*ptr++ != 0x07)
360138471Sphk					ERROUT(0);	/* not FCS-less 802.3 */
36133548Sjkh				m_adj(m, ptr - start);
36233548Sjkh				NG_FWD_NEW_DATA(error, item, priv->ethernet, m);
36333548Sjkh			} else	/* Other weird stuff... */
36433548Sjkh				ERROUT(0);
3652893Sdfr			break;
36633548Sjkh		case NLPID_IP:
3672893Sdfr			m_adj(m, ptr - start);
368149720Sssouhlal			NG_FWD_NEW_DATA(error, item, priv->inet, m);
3692893Sdfr			break;
3702893Sdfr		case NLPID_PPP:
3712893Sdfr			m_adj(m, ptr - start);
37233548Sjkh			NG_FWD_NEW_DATA(error, item, priv->ppp, m);
37333548Sjkh			break;
37433548Sjkh		case NLPID_Q933:
375138471Sphk		case NLPID_CLNP:
37633548Sjkh		case NLPID_ESIS:
377134345Stjr		case NLPID_ISIS:
378134345Stjr			ERROUT(0);
3792893Sdfr		default:	/* Try PPP (see RFC 1973) */
3802893Sdfr			ptr--;	/* NLPID becomes PPP proto */
381138471Sphk			if ((*ptr & 0x01) == 0x01)
382138471Sphk				ERROUT(0);
3832893Sdfr			m_adj(m, ptr - start);
384138471Sphk			NG_FWD_NEW_DATA(error, item, priv->ppp, m);
3852893Sdfr			break;
38633548Sjkh		}
3872893Sdfr	} else if (hook == priv->ppp) {
3882893Sdfr		M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend PPP NLPID */
38912144Sphk		if (!m)
390166558Srodrigc			ERROUT(ENOBUFS);
3912893Sdfr		mtod(m, u_char *)[0] = HDLC_UI;
39233548Sjkh		mtod(m, u_char *)[1] = NLPID_PPP;
39333548Sjkh		NG_FWD_NEW_DATA(error, item, priv->downlink, m);
394130585Sphk	} else if (hook == priv->inet) {
3952893Sdfr		switch (priv->enc->method) {
3962893Sdfr		case NG_RFC1490_ENCAP_IETF_IP:
3972893Sdfr			M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend IP NLPID */
39833548Sjkh			if (!m)
39933548Sjkh				ERROUT(ENOBUFS);
40055188Sbp			mtod(m, u_char *)[0] = HDLC_UI;
40133548Sjkh			mtod(m, u_char *)[1] = NLPID_IP;
402137036Sphk			break;
403137036Sphk		case NG_RFC1490_ENCAP_IETF_SNAP:
4042893Sdfr			/*
405138471Sphk			 *  According to RFC2427 frame should begin with
406137036Sphk			 *  HDLC_UI  PAD  NLIPID  OUI      PID
407137036Sphk			 *  03      00   80      00 00 00  08 00
408137036Sphk			 */
409137036Sphk			M_PREPEND(m, 8, M_DONTWAIT);
410137036Sphk			if (!m)
411137036Sphk				ERROUT(ENOBUFS);
41283366Sjulian			mtod(m, u_char *)[0] = HDLC_UI;
4133152Sphk			mtod(m, u_char *)[1] = 0x00;			/* PAD */
41433548Sjkh			mtod(m, u_char *)[2] = NLPID_SNAP;
41533548Sjkh			bzero((char *)(mtod(m, u_char *) + 3), 3);	/* OUI 0-0-0 */
416137036Sphk			*((u_int16_t *)mtod(m, u_int16_t *) + 6/sizeof(u_int16_t))
41733548Sjkh			    = htons(ETHERTYPE_IP);  /* PID */
41833548Sjkh			break;
41933548Sjkh		case NG_RFC1490_ENCAP_CISCO:
4202893Sdfr			M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend IP ethertype */
42133548Sjkh			if (!m)
42233548Sjkh				ERROUT(ENOBUFS);
42356674Snyan			*((u_int16_t *)mtod(m, u_int16_t *)) = htons(ETHERTYPE_IP);
424171408Sbde			break;
4252893Sdfr		}
426171408Sbde		NG_FWD_NEW_DATA(error, item, priv->downlink, m);
4273152Sphk	} else if (hook == priv->ethernet) {
4282893Sdfr		M_PREPEND(m, 8, M_DONTWAIT);	/* Prepend NLPID, OUI, PID */
42933548Sjkh		if (!m)
43033548Sjkh			ERROUT(ENOBUFS);
43133548Sjkh		mtod(m, u_char *)[0] = HDLC_UI;
43233548Sjkh		mtod(m, u_char *)[1] = 0x00;		/* pad */
433105655Sjhb		mtod(m, u_char *)[2] = NLPID_SNAP;
43433548Sjkh		mtod(m, u_char *)[3] = 0x00;		/* OUI */
43556674Snyan		mtod(m, u_char *)[4] = 0x80;
43687068Sjhb		mtod(m, u_char *)[5] = 0xc2;
43787068Sjhb		mtod(m, u_char *)[6] = 0x00;		/* PID */
43887068Sjhb		mtod(m, u_char *)[7] = 0x07;
43987068Sjhb		NG_FWD_NEW_DATA(error, item, priv->downlink, m);
44087068Sjhb	} else
44156674Snyan		panic("%s", __func__);
4422893Sdfr
443111119Simpdone:
4442893Sdfr	if (item)
445137036Sphk		NG_FREE_ITEM(item);
446137036Sphk	NG_FREE_M(m);
4472893Sdfr	return (error);
4482893Sdfr}
449166340Srodrigc
450166340Srodrigc/*
451166340Srodrigc * Nuke node
452166340Srodrigc */
453166340Srodrigcstatic int
454166340Srodrigcng_rfc1490_shutdown(node_p node)
455166340Srodrigc{
456166340Srodrigc	const priv_p priv = NG_NODE_PRIVATE(node);
457166340Srodrigc
458166340Srodrigc	/* Take down netgraph node */
459166340Srodrigc	bzero(priv, sizeof(*priv));
460166340Srodrigc	free(priv, M_NETGRAPH);
461166340Srodrigc	NG_NODE_SET_PRIVATE(node, NULL);
462166340Srodrigc	NG_NODE_UNREF(node);		/* let the node escape */
463166340Srodrigc	return (0);
4642893Sdfr}
4652893Sdfr
4662893Sdfr/*
4672893Sdfr * Hook disconnection
46833548Sjkh */
4692893Sdfrstatic int
470113979Sjhbng_rfc1490_disconnect(hook_p hook)
471113979Sjhb{
472113979Sjhb	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
473113979Sjhb
4742893Sdfr	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
4752893Sdfr	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
4762893Sdfr		ng_rmnode_self(NG_HOOK_NODE(hook));
4772893Sdfr	else if (hook == priv->downlink)
4782893Sdfr		priv->downlink = NULL;
4792893Sdfr	else if (hook == priv->inet)
4802893Sdfr		priv->inet = NULL;
48133548Sjkh	else if (hook == priv->ppp)
4822893Sdfr		priv->ppp = NULL;
48356674Snyan	else if (hook == priv->ethernet)
48456674Snyan		priv->ethernet = NULL;
48556674Snyan	else
48687068Sjhb		panic("%s", __func__);
48787068Sjhb	return (0);
488126998Srwatson}
48916363Sasami
49087068Sjhb