ng_sscfu.c revision 123812
1121461Sharti/*
2121461Sharti * Copyright (c) 2001-2003
3121461Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121461Sharti * 	All rights reserved.
5121461Sharti *
6121461Sharti * Redistribution and use in source and binary forms, with or without
7121461Sharti * modification, are permitted provided that the following conditions
8121461Sharti * are met:
9121461Sharti * 1. Redistributions of source code must retain the above copyright
10121461Sharti *    notice, this list of conditions and the following disclaimer.
11121461Sharti * 2. Redistributions in binary form must reproduce the above copyright
12121461Sharti *    notice, this list of conditions and the following disclaimer in the
13121461Sharti *    documentation and/or other materials provided with the distribution.
14121461Sharti *
15121461Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121461Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121461Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121461Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121461Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121461Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121461Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121461Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121461Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121461Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121461Sharti * SUCH DAMAGE.
26121461Sharti *
27121461Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28121461Sharti *
29121461Sharti * Netgraph module for ITU-T Q.2120 UNI SSCF.
30121461Sharti */
31121461Sharti
32121461Sharti#include <sys/cdefs.h>
33121461Sharti__FBSDID("$FreeBSD: head/sys/netgraph/atm/sscfu/ng_sscfu.c 123812 2003-12-24 18:51:01Z alfred $");
34121461Sharti
35121461Sharti#include <sys/param.h>
36121461Sharti#include <sys/systm.h>
37121461Sharti#include <sys/kernel.h>
38121461Sharti#include <sys/malloc.h>
39121461Sharti#include <sys/mbuf.h>
40121461Sharti#include <sys/errno.h>
41121461Sharti#include <sys/syslog.h>
42121461Sharti#include <sys/socket.h>
43121461Sharti#include <sys/socketvar.h>
44121461Sharti#include <sys/sbuf.h>
45121461Sharti#include <machine/stdarg.h>
46121461Sharti
47121461Sharti#include <netgraph/ng_message.h>
48121461Sharti#include <netgraph/netgraph.h>
49121461Sharti#include <netgraph/ng_parse.h>
50121461Sharti#include <netnatm/saal/sscopdef.h>
51121461Sharti#include <netnatm/saal/sscfudef.h>
52121461Sharti#include <netgraph/atm/ng_sscop.h>
53121461Sharti#include <netgraph/atm/ng_sscfu.h>
54121461Sharti#include <netgraph/atm/sscfu/ng_sscfu_cust.h>
55121461Sharti#include <netnatm/saal/sscfu.h>
56121461Sharti
57121461ShartiMALLOC_DEFINE(M_NG_SSCFU, "netgraph_sscfu", "netgraph uni sscf node");
58121461Sharti
59121461ShartiMODULE_DEPEND(ng_sscfu, ngatmbase, 1, 1, 1);
60121461Sharti
61121461Sharti/*
62121461Sharti * Private data
63121461Sharti */
64121461Shartistruct priv {
65121461Sharti	hook_p		upper;	/* SAAL interface */
66121461Sharti	hook_p		lower;	/* SSCOP interface */
67121461Sharti	struct sscfu	*sscf;	/* the instance */
68121461Sharti	int		enabled;
69121461Sharti};
70121461Sharti
71121461Sharti/*
72121461Sharti * PARSING
73121461Sharti */
74121461Sharti/*
75121461Sharti * Parse PARAM type
76121461Sharti */
77121461Shartistatic const struct ng_parse_struct_field ng_sscop_param_type_info[] =
78121461Sharti    NG_SSCOP_PARAM_INFO;
79121461Sharti
80121461Shartistatic const struct ng_parse_type ng_sscop_param_type = {
81121461Sharti	&ng_parse_struct_type,
82121461Sharti	ng_sscop_param_type_info
83121461Sharti};
84121461Sharti
85121461Shartistatic const struct ng_parse_struct_field ng_sscfu_getdefparam_type_info[] =
86121461Sharti    NG_SSCFU_GETDEFPARAM_INFO;
87121461Sharti
88121461Shartistatic const struct ng_parse_type ng_sscfu_getdefparam_type = {
89121461Sharti	&ng_parse_struct_type,
90121461Sharti	ng_sscfu_getdefparam_type_info
91121461Sharti};
92121461Sharti
93121461Sharti
94121461Shartistatic const struct ng_cmdlist ng_sscfu_cmdlist[] = {
95121461Sharti	{
96121461Sharti	  NGM_SSCFU_COOKIE,
97121461Sharti	  NGM_SSCFU_GETDEFPARAM,
98121461Sharti	  "getdefparam",
99121461Sharti	  NULL,
100121461Sharti	  &ng_sscfu_getdefparam_type
101121461Sharti	},
102121461Sharti	{
103121461Sharti	  NGM_SSCFU_COOKIE,
104121461Sharti	  NGM_SSCFU_ENABLE,
105121461Sharti	  "enable",
106121461Sharti	  NULL,
107121461Sharti	  NULL
108121461Sharti	},
109121461Sharti	{
110121461Sharti	  NGM_SSCFU_COOKIE,
111121461Sharti	  NGM_SSCFU_DISABLE,
112121461Sharti	  "disable",
113121461Sharti	  NULL,
114121461Sharti	  NULL
115121461Sharti	},
116121461Sharti	{
117121461Sharti	  NGM_SSCFU_COOKIE,
118121461Sharti	  NGM_SSCFU_GETDEBUG,
119121461Sharti	  "getdebug",
120121461Sharti	  NULL,
121121461Sharti	  &ng_parse_hint32_type
122121461Sharti	},
123121461Sharti	{
124121461Sharti	  NGM_SSCFU_COOKIE,
125121461Sharti	  NGM_SSCFU_SETDEBUG,
126121461Sharti	  "setdebug",
127121461Sharti	  &ng_parse_hint32_type,
128121461Sharti	  NULL
129121461Sharti	},
130121461Sharti	{
131121461Sharti	  NGM_SSCFU_COOKIE,
132121461Sharti	  NGM_SSCFU_GETSTATE,
133121461Sharti	  "getstate",
134121461Sharti	  NULL,
135121461Sharti	  &ng_parse_uint32_type
136121461Sharti	},
137121461Sharti	{ 0 }
138121461Sharti};
139121461Sharti
140121461Shartistatic ng_constructor_t ng_sscfu_constructor;
141121461Shartistatic ng_shutdown_t	ng_sscfu_shutdown;
142121461Shartistatic ng_rcvmsg_t	ng_sscfu_rcvmsg;
143121461Shartistatic ng_newhook_t	ng_sscfu_newhook;
144121461Shartistatic ng_disconnect_t	ng_sscfu_disconnect;
145121461Shartistatic ng_rcvdata_t	ng_sscfu_rcvupper;
146121461Shartistatic ng_rcvdata_t	ng_sscfu_rcvlower;
147121461Sharti
148121461Shartistatic int ng_sscfu_mod_event(module_t, int, void *);
149121461Sharti
150121461Shartistatic struct ng_type ng_sscfu_typestruct = {
151121461Sharti	NG_ABI_VERSION,
152121461Sharti	NG_SSCFU_NODE_TYPE,
153121461Sharti	ng_sscfu_mod_event,	/* Module event handler (optional) */
154121461Sharti	ng_sscfu_constructor,	/* Node constructor */
155121461Sharti	ng_sscfu_rcvmsg,	/* control messages come here */
156121461Sharti	ng_sscfu_shutdown,	/* reset, and free resources */
157121461Sharti	ng_sscfu_newhook,	/* first notification of new hook */
158121461Sharti	NULL,			/* findhook */
159121461Sharti	NULL,			/* connect */
160121461Sharti	ng_sscfu_rcvupper,	/* rcvdata */
161121461Sharti	ng_sscfu_disconnect,	/* notify on disconnect */
162121461Sharti	ng_sscfu_cmdlist,
163121461Sharti};
164121461ShartiNETGRAPH_INIT(sscfu, &ng_sscfu_typestruct);
165121461Sharti
166121461Shartistatic void sscfu_send_upper(struct sscfu *, void *, enum saal_sig,
167121461Sharti	struct mbuf *);
168121461Shartistatic void sscfu_send_lower(struct sscfu *, void *, enum sscop_aasig,
169121461Sharti	struct mbuf *, u_int);
170121461Shartistatic void sscfu_window(struct sscfu *, void *, u_int);
171121461Shartistatic void sscfu_verbose(struct sscfu *, void *, const char *, ...)
172121461Sharti	__printflike(3, 4);
173121461Sharti
174121461Shartistatic const struct sscfu_funcs sscfu_funcs = {
175121461Sharti	sscfu_send_upper,
176121461Sharti	sscfu_send_lower,
177121461Sharti	sscfu_window,
178121461Sharti	sscfu_verbose
179121461Sharti};
180121461Sharti
181121461Sharti/************************************************************/
182121461Sharti/*
183121461Sharti * CONTROL MESSAGES
184121461Sharti */
185121461Shartistatic int
186121461Shartitext_status(node_p node, struct priv *priv, char *arg, u_int len)
187121461Sharti{
188121461Sharti	struct sbuf sbuf;
189121461Sharti
190121461Sharti	sbuf_new(&sbuf, arg, len, 0);
191121461Sharti
192121461Sharti	if (priv->upper)
193121461Sharti		sbuf_printf(&sbuf, "upper hook: %s connected to %s:%s\n",
194121461Sharti		    NG_HOOK_NAME(priv->upper),
195121461Sharti		    NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))),
196121461Sharti		    NG_HOOK_NAME(NG_HOOK_PEER(priv->upper)));
197121461Sharti	else
198121461Sharti		sbuf_printf(&sbuf, "upper hook: <not connected>\n");
199121461Sharti
200121461Sharti	if (priv->lower)
201121461Sharti		sbuf_printf(&sbuf, "lower hook: %s connected to %s:%s\n",
202121461Sharti		    NG_HOOK_NAME(priv->lower),
203121461Sharti		    NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))),
204121461Sharti		    NG_HOOK_NAME(NG_HOOK_PEER(priv->lower)));
205121461Sharti	else
206121461Sharti		sbuf_printf(&sbuf, "lower hook: <not connected>\n");
207121461Sharti
208121461Sharti	sbuf_printf(&sbuf, "sscf state: %s\n",
209123812Salfred	    priv->enabled == 0 ? "<disabled>" :
210121461Sharti	    sscfu_statename(sscfu_getstate(priv->sscf)));
211121461Sharti
212121461Sharti	sbuf_finish(&sbuf);
213121461Sharti	return (sbuf_len(&sbuf));
214121461Sharti}
215121461Sharti
216121461Shartistatic int
217121461Sharting_sscfu_rcvmsg(node_p node, item_p item, hook_p lasthook)
218121461Sharti{
219121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
220121461Sharti	struct ng_mesg *resp = NULL;
221121461Sharti	struct ng_mesg *msg;
222121461Sharti	int error = 0;
223121461Sharti
224121461Sharti	NGI_GET_MSG(item, msg);
225121461Sharti
226121461Sharti	switch (msg->header.typecookie) {
227121461Sharti
228121461Sharti	  case NGM_GENERIC_COOKIE:
229121461Sharti		switch (msg->header.cmd) {
230121461Sharti
231121461Sharti		  case NGM_TEXT_STATUS:
232121461Sharti			NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT);
233121461Sharti			if (resp == NULL) {
234121461Sharti				error = ENOMEM;
235121461Sharti				break;
236121461Sharti			}
237121461Sharti			resp->header.arglen = text_status(node, priv,
238121461Sharti			    (char *)resp->data, resp->header.arglen) + 1;
239121461Sharti			break;
240121461Sharti
241121461Sharti		  default:
242121461Sharti			error = EINVAL;
243121461Sharti			break;
244121461Sharti		}
245121461Sharti		break;
246121461Sharti
247121461Sharti	  case NGM_SSCFU_COOKIE:
248121461Sharti		switch (msg->header.cmd) {
249121461Sharti
250121461Sharti		  case NGM_SSCFU_GETDEFPARAM:
251121461Sharti		    {
252121461Sharti			struct ng_sscfu_getdefparam *p;
253121461Sharti
254121461Sharti			if (msg->header.arglen != 0) {
255121461Sharti				error = EINVAL;
256121461Sharti				break;
257121461Sharti			}
258121461Sharti			NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT);
259121461Sharti			if (resp == NULL) {
260121461Sharti				error = ENOMEM;
261121461Sharti				break;
262121461Sharti			}
263121461Sharti			p = (struct ng_sscfu_getdefparam *)resp->data;
264121461Sharti			p->mask = sscfu_getdefparam(&p->param);
265121461Sharti			break;
266121461Sharti		    }
267121461Sharti
268121461Sharti		  case NGM_SSCFU_ENABLE:
269121461Sharti			if (msg->header.arglen != 0) {
270121461Sharti				error = EINVAL;
271121461Sharti				break;
272121461Sharti			}
273121461Sharti			if (priv->enabled) {
274121461Sharti				error = EISCONN;
275121461Sharti				break;
276121461Sharti			}
277121461Sharti			priv->enabled = 1;
278121461Sharti			break;
279121461Sharti
280121461Sharti		  case NGM_SSCFU_DISABLE:
281121461Sharti			if (msg->header.arglen != 0) {
282121461Sharti				error = EINVAL;
283121461Sharti				break;
284121461Sharti			}
285121461Sharti			if (!priv->enabled) {
286121461Sharti				error = ENOTCONN;
287121461Sharti				break;
288121461Sharti			}
289121461Sharti			priv->enabled = 0;
290121461Sharti			sscfu_reset(priv->sscf);
291121461Sharti			break;
292121461Sharti
293121461Sharti		  case NGM_SSCFU_GETSTATE:
294121461Sharti			if (msg->header.arglen != 0) {
295121461Sharti				error = EINVAL;
296121461Sharti				break;
297121461Sharti			}
298121461Sharti			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
299121461Sharti			if(resp == NULL) {
300121461Sharti				error = ENOMEM;
301121461Sharti				break;
302121461Sharti			}
303121461Sharti			*(uint32_t *)resp->data =
304121461Sharti			    priv->enabled ? (sscfu_getstate(priv->sscf) + 1)
305121461Sharti			                  : 0;
306121461Sharti			break;
307121461Sharti
308121461Sharti		  case NGM_SSCFU_GETDEBUG:
309121461Sharti			if (msg->header.arglen != 0) {
310121461Sharti				error = EINVAL;
311121461Sharti				break;
312121461Sharti			}
313121461Sharti			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
314121461Sharti			if(resp == NULL) {
315121461Sharti				error = ENOMEM;
316121461Sharti				break;
317121461Sharti			}
318121461Sharti			*(uint32_t *)resp->data = sscfu_getdebug(priv->sscf);
319121461Sharti			break;
320121461Sharti
321121461Sharti		  case NGM_SSCFU_SETDEBUG:
322121461Sharti			if (msg->header.arglen != sizeof(uint32_t)) {
323121461Sharti				error = EINVAL;
324121461Sharti				break;
325121461Sharti			}
326121461Sharti			sscfu_setdebug(priv->sscf, *(uint32_t *)msg->data);
327121461Sharti			break;
328121461Sharti
329121461Sharti		  default:
330121461Sharti			error = EINVAL;
331121461Sharti			break;
332121461Sharti		}
333121461Sharti		break;
334121461Sharti
335121461Sharti	  default:
336121461Sharti		error = EINVAL;
337121461Sharti		break;
338121461Sharti	}
339121461Sharti
340121461Sharti	NG_RESPOND_MSG(error, node, item, resp);
341121461Sharti	NG_FREE_MSG(msg);
342121461Sharti
343121461Sharti	return (error);
344121461Sharti}
345121461Sharti
346121461Sharti/************************************************************/
347121461Sharti/*
348121461Sharti * HOOK MANAGEMENT
349121461Sharti */
350121461Shartistatic int
351121461Sharting_sscfu_newhook(node_p node, hook_p hook, const char *name)
352121461Sharti{
353121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
354121461Sharti
355121461Sharti	if (strcmp(name, "upper") == 0)
356121461Sharti		priv->upper = hook;
357121461Sharti	else if (strcmp(name, "lower") == 0) {
358121461Sharti		priv->lower = hook;
359121461Sharti		NG_HOOK_SET_RCVDATA(hook, ng_sscfu_rcvlower);
360121461Sharti	} else
361121461Sharti		return (EINVAL);
362121461Sharti	return (0);
363121461Sharti}
364121461Sharti
365121461Shartistatic int
366121461Sharting_sscfu_disconnect(hook_p hook)
367121461Sharti{
368121461Sharti	node_p node = NG_HOOK_NODE(hook);
369121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
370121461Sharti
371121461Sharti	if (hook == priv->upper)
372121461Sharti		priv->upper = NULL;
373121461Sharti	else if (hook == priv->lower)
374121461Sharti		priv->lower = NULL;
375121461Sharti	else {
376121461Sharti		log(LOG_ERR, "bogus hook");
377121461Sharti		return (EINVAL);
378121461Sharti	}
379121461Sharti
380121461Sharti	if (NG_NODE_NUMHOOKS(node) == 0) {
381121461Sharti		if (NG_NODE_IS_VALID(node))
382121461Sharti			ng_rmnode_self(node);
383121461Sharti	} else {
384121461Sharti		/*
385121461Sharti		 * Because there are no timeouts reset the protocol
386121461Sharti		 * if the lower layer is disconnected.
387121461Sharti		 */
388121461Sharti		if (priv->lower == NULL &&
389121461Sharti		    priv->enabled &&
390121461Sharti		    sscfu_getstate(priv->sscf) != SSCFU_RELEASED)
391121461Sharti			sscfu_reset(priv->sscf);
392121461Sharti	}
393121461Sharti	return (0);
394121461Sharti}
395121461Sharti
396121461Sharti/************************************************************/
397121461Sharti/*
398121461Sharti * DATA
399121461Sharti */
400121461Shartistatic int
401121461Sharting_sscfu_rcvupper(hook_p hook, item_p item)
402121461Sharti{
403121461Sharti	node_p node = NG_HOOK_NODE(hook);
404121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
405121461Sharti	struct mbuf *m;
406121461Sharti	struct sscfu_arg a;
407121461Sharti
408121461Sharti	if (!priv->enabled || priv->lower == NULL) {
409121461Sharti		NG_FREE_ITEM(item);
410121461Sharti		return (0);
411121461Sharti	}
412121461Sharti
413121461Sharti	NGI_GET_M(item, m);
414121461Sharti	NG_FREE_ITEM(item);
415121461Sharti
416121461Sharti	if (!(m->m_flags & M_PKTHDR)) {
417121461Sharti		printf("no pkthdr\n");
418121461Sharti		m_freem(m);
419121461Sharti		return (EINVAL);
420121461Sharti	}
421121461Sharti	if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
422121461Sharti		return (ENOMEM);
423121461Sharti	bcopy((caddr_t)mtod(m, struct sscfu_arg *), &a, sizeof(a));
424121461Sharti	m_adj(m, sizeof(a));
425121461Sharti
426121461Sharti	return (sscfu_saalsig(priv->sscf, a.sig, m));
427121461Sharti}
428121461Sharti
429121461Shartistatic void
430121461Shartisscfu_send_upper(struct sscfu *sscf, void *p, enum saal_sig sig, struct mbuf *m)
431121461Sharti{
432121461Sharti	node_p node = (node_p)p;
433121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
434121461Sharti	int error;
435121461Sharti	struct sscfu_arg *a;
436121461Sharti
437121461Sharti	if (priv->upper == NULL) {
438121461Sharti		if (m != NULL)
439121461Sharti			m_freem(m);
440121461Sharti		return;
441121461Sharti	}
442121461Sharti	if (m == NULL) {
443121461Sharti		MGETHDR(m, M_NOWAIT, MT_DATA);
444121461Sharti		if (m == NULL)
445121461Sharti			return;
446121461Sharti		m->m_len = sizeof(struct sscfu_arg);
447121461Sharti		m->m_pkthdr.len = m->m_len;
448121461Sharti	} else {
449121461Sharti		M_PREPEND(m, sizeof(struct sscfu_arg), M_NOWAIT);
450121461Sharti		if (m == NULL)
451121461Sharti			return;
452121461Sharti	}
453121461Sharti	a = mtod(m, struct sscfu_arg *);
454121461Sharti	a->sig = sig;
455121461Sharti
456121461Sharti	NG_SEND_DATA_ONLY(error, priv->upper, m);
457121461Sharti}
458121461Sharti
459121461Shartistatic int
460121461Sharting_sscfu_rcvlower(hook_p hook, item_p item)
461121461Sharti{
462121461Sharti	node_p node = NG_HOOK_NODE(hook);
463121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
464121461Sharti	struct mbuf *m;
465121461Sharti	struct sscop_arg a;
466121461Sharti
467121461Sharti	if (!priv->enabled || priv->upper == NULL) {
468121461Sharti		NG_FREE_ITEM(item);
469121461Sharti		return (0);
470121461Sharti	}
471121461Sharti
472121461Sharti	NGI_GET_M(item, m);
473121461Sharti	NG_FREE_ITEM(item);
474121461Sharti
475121461Sharti	if (!(m->m_flags & M_PKTHDR)) {
476121461Sharti		printf("no pkthdr\n");
477121461Sharti		m_freem(m);
478121461Sharti		return (EINVAL);
479121461Sharti	}
480121461Sharti
481121461Sharti	/*
482121461Sharti	 * Strip of the SSCOP header.
483121461Sharti	 */
484121461Sharti	if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
485121461Sharti		return (ENOMEM);
486121461Sharti	bcopy((caddr_t)mtod(m, struct sscop_arg *), &a, sizeof(a));
487121461Sharti	m_adj(m, sizeof(a));
488121461Sharti
489121461Sharti	sscfu_input(priv->sscf, a.sig, m, a.arg);
490121461Sharti
491121461Sharti	return (0);
492121461Sharti}
493121461Sharti
494121461Shartistatic void
495121461Shartisscfu_send_lower(struct sscfu *sscf, void *p, enum sscop_aasig sig,
496121461Sharti    struct mbuf *m, u_int arg)
497121461Sharti{
498121461Sharti	node_p node = (node_p)p;
499121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
500121461Sharti	int error;
501121461Sharti	struct sscop_arg *a;
502121461Sharti
503121461Sharti	if (priv->lower == NULL) {
504121461Sharti		if (m != NULL)
505121461Sharti			m_freem(m);
506121461Sharti		return;
507121461Sharti	}
508121461Sharti	if (m == NULL) {
509121461Sharti		MGETHDR(m, M_NOWAIT, MT_DATA);
510121461Sharti		if (m == NULL)
511121461Sharti			return;
512121461Sharti		m->m_len = sizeof(struct sscop_arg);
513121461Sharti		m->m_pkthdr.len = m->m_len;
514121461Sharti	} else {
515121461Sharti		M_PREPEND(m, sizeof(struct sscop_arg), M_NOWAIT);
516121461Sharti		if (m == NULL)
517121461Sharti			return;
518121461Sharti	}
519121461Sharti	a = mtod(m, struct sscop_arg *);
520121461Sharti	a->sig = sig;
521121461Sharti	a->arg = arg;
522121461Sharti
523121461Sharti	NG_SEND_DATA_ONLY(error, priv->lower, m);
524121461Sharti}
525121461Sharti
526121461Sharti/*
527121461Sharti * Window is handled by ng_sscop so make this a NOP.
528121461Sharti */
529121461Shartistatic void
530121461Shartisscfu_window(struct sscfu *sscfu, void *arg, u_int w)
531121461Sharti{
532121461Sharti}
533121461Sharti
534121461Sharti/************************************************************/
535121461Sharti/*
536121461Sharti * NODE MANAGEMENT
537121461Sharti */
538121461Shartistatic int
539121461Sharting_sscfu_constructor(node_p node)
540121461Sharti{
541121461Sharti	struct priv *priv;
542121461Sharti
543121461Sharti	if ((priv = malloc(sizeof(*priv), M_NG_SSCFU, M_NOWAIT|M_ZERO)) == NULL)
544121461Sharti		return (ENOMEM);
545121461Sharti
546121461Sharti	if ((priv->sscf = sscfu_create(node, &sscfu_funcs)) == NULL) {
547121461Sharti		free(priv, M_NG_SSCFU);
548121461Sharti		return (ENOMEM);
549121461Sharti	}
550121461Sharti
551121461Sharti	NG_NODE_SET_PRIVATE(node, priv);
552121461Sharti
553121461Sharti	return (0);
554121461Sharti}
555121461Sharti
556121461Shartistatic int
557121461Sharting_sscfu_shutdown(node_p node)
558121461Sharti{
559121461Sharti	struct priv *priv = NG_NODE_PRIVATE(node);
560121461Sharti
561121461Sharti	sscfu_destroy(priv->sscf);
562121461Sharti
563121461Sharti	free(priv, M_NG_SSCFU);
564121461Sharti	NG_NODE_SET_PRIVATE(node, NULL);
565121461Sharti
566121461Sharti	NG_NODE_UNREF(node);
567121461Sharti
568121461Sharti	return (0);
569121461Sharti}
570121461Sharti
571121461Shartistatic void
572121461Shartisscfu_verbose(struct sscfu *sscfu, void *arg, const char *fmt, ...)
573121461Sharti{
574121461Sharti	va_list ap;
575121461Sharti
576121461Sharti	va_start(ap, fmt);
577121461Sharti	printf("sscfu(%p): ", sscfu);
578121461Sharti	vprintf(fmt, ap);
579121461Sharti	va_end(ap);
580121461Sharti	printf("\n");
581121461Sharti}
582121461Sharti
583121461Sharti/************************************************************/
584121461Sharti/*
585121461Sharti * INITIALISATION
586121461Sharti */
587121461Sharti/*
588121461Sharti * Loading and unloading of node type
589121461Sharti */
590121461Shartistatic int
591121461Sharting_sscfu_mod_event(module_t mod, int event, void *data)
592121461Sharti{
593121461Sharti	int s;
594121461Sharti	int error = 0;
595121461Sharti
596121461Sharti	s = splnet();
597121461Sharti	switch (event) {
598121461Sharti
599121461Sharti	  case MOD_LOAD:
600121461Sharti		break;
601121461Sharti
602121461Sharti	  case MOD_UNLOAD:
603121461Sharti		break;
604121461Sharti
605121461Sharti	  default:
606121461Sharti		error = EOPNOTSUPP;
607121461Sharti		break;
608121461Sharti	}
609121461Sharti	splx(s);
610121461Sharti	return (error);
611121461Sharti}
612