2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * Author: Hartmut Brandt <harti@freebsd.org>
29 * Netgraph module for ITU-T Q.2120 UNI SSCF.
31 * $FreeBSD: src/sys/netgraph/atm/sscfu/ng_sscfu.c,v 1.4 2005/01/07 01:45:41 imp Exp $
32 * $DragonFly: src/sys/netgraph7/atm/sscfu/ng_sscfu.c,v 1.2 2008/06/26 23:05:39 dillon Exp $
33 * $DragonFly: src/sys/netgraph7/atm/sscfu/ng_sscfu.c,v 1.2 2008/06/26 23:05:39 dillon Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
41 #include <sys/errno.h>
42 #include <sys/syslog.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
46 #include <machine/stdarg.h>
48 #include "ng_message.h"
51 #include <netnatm/saal/sscopdef.h>
52 #include <netnatm/saal/sscfudef.h>
53 #include "atm/ng_sscop.h"
54 #include "atm/ng_sscfu.h"
55 #include "atm/sscfu/ng_sscfu_cust.h"
56 #include <netnatm/saal/sscfu.h>
58 MALLOC_DEFINE(M_NG_SSCFU
, "netgraph_sscfu", "netgraph uni sscf node");
60 MODULE_DEPEND(ng_sscfu
, ngatmbase
, 1, 1, 1);
66 hook_p upper
; /* SAAL interface */
67 hook_p lower
; /* SSCOP interface */
68 struct sscfu
*sscf
; /* the instance */
78 static const struct ng_parse_struct_field ng_sscop_param_type_info
[] =
81 static const struct ng_parse_type ng_sscop_param_type
= {
82 &ng_parse_struct_type
,
83 ng_sscop_param_type_info
86 static const struct ng_parse_struct_field ng_sscfu_getdefparam_type_info
[] =
87 NG_SSCFU_GETDEFPARAM_INFO
;
89 static const struct ng_parse_type ng_sscfu_getdefparam_type
= {
90 &ng_parse_struct_type
,
91 ng_sscfu_getdefparam_type_info
95 static const struct ng_cmdlist ng_sscfu_cmdlist
[] = {
98 NGM_SSCFU_GETDEFPARAM
,
101 &ng_sscfu_getdefparam_type
122 &ng_parse_hint32_type
128 &ng_parse_hint32_type
,
136 &ng_parse_uint32_type
141 static ng_constructor_t ng_sscfu_constructor
;
142 static ng_shutdown_t ng_sscfu_shutdown
;
143 static ng_rcvmsg_t ng_sscfu_rcvmsg
;
144 static ng_newhook_t ng_sscfu_newhook
;
145 static ng_disconnect_t ng_sscfu_disconnect
;
146 static ng_rcvdata_t ng_sscfu_rcvupper
;
147 static ng_rcvdata_t ng_sscfu_rcvlower
;
149 static int ng_sscfu_mod_event(module_t
, int, void *);
151 static struct ng_type ng_sscfu_typestruct
= {
152 .version
= NG_ABI_VERSION
,
153 .name
= NG_SSCFU_NODE_TYPE
,
154 .mod_event
= ng_sscfu_mod_event
,
155 .constructor
= ng_sscfu_constructor
,
156 .rcvmsg
= ng_sscfu_rcvmsg
,
157 .shutdown
= ng_sscfu_shutdown
,
158 .newhook
= ng_sscfu_newhook
,
159 .rcvdata
= ng_sscfu_rcvupper
,
160 .disconnect
= ng_sscfu_disconnect
,
161 .cmdlist
= ng_sscfu_cmdlist
,
163 NETGRAPH_INIT(sscfu
, &ng_sscfu_typestruct
);
165 static void sscfu_send_upper(struct sscfu
*, void *, enum saal_sig
,
167 static void sscfu_send_lower(struct sscfu
*, void *, enum sscop_aasig
,
168 struct mbuf
*, u_int
);
169 static void sscfu_window(struct sscfu
*, void *, u_int
);
170 static void sscfu_verbose(struct sscfu
*, void *, const char *, ...)
173 static const struct sscfu_funcs sscfu_funcs
= {
180 /************************************************************/
185 text_status(node_p node
, struct priv
*priv
, char *arg
, u_int len
)
189 sbuf_new(&sbuf
, arg
, len
, 0);
192 sbuf_printf(&sbuf
, "upper hook: %s connected to %s:%s\n",
193 NG_HOOK_NAME(priv
->upper
),
194 NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv
->upper
))),
195 NG_HOOK_NAME(NG_HOOK_PEER(priv
->upper
)));
197 sbuf_printf(&sbuf
, "upper hook: <not connected>\n");
200 sbuf_printf(&sbuf
, "lower hook: %s connected to %s:%s\n",
201 NG_HOOK_NAME(priv
->lower
),
202 NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv
->lower
))),
203 NG_HOOK_NAME(NG_HOOK_PEER(priv
->lower
)));
205 sbuf_printf(&sbuf
, "lower hook: <not connected>\n");
207 sbuf_printf(&sbuf
, "sscf state: %s\n",
208 priv
->enabled
== 0 ? "<disabled>" :
209 sscfu_statename(sscfu_getstate(priv
->sscf
)));
212 return (sbuf_len(&sbuf
));
216 ng_sscfu_rcvmsg(node_p node
, item_p item
, hook_p lasthook
)
218 struct priv
*priv
= NG_NODE_PRIVATE(node
);
219 struct ng_mesg
*resp
= NULL
;
223 NGI_GET_MSG(item
, msg
);
225 switch (msg
->header
.typecookie
) {
227 case NGM_GENERIC_COOKIE
:
228 switch (msg
->header
.cmd
) {
230 case NGM_TEXT_STATUS
:
231 NG_MKRESPONSE(resp
, msg
, NG_TEXTRESPONSE
, M_WAITOK
| M_NULLOK
);
236 resp
->header
.arglen
= text_status(node
, priv
,
237 (char *)resp
->data
, resp
->header
.arglen
) + 1;
246 case NGM_SSCFU_COOKIE
:
247 switch (msg
->header
.cmd
) {
249 case NGM_SSCFU_GETDEFPARAM
:
251 struct ng_sscfu_getdefparam
*p
;
253 if (msg
->header
.arglen
!= 0) {
257 NG_MKRESPONSE(resp
, msg
, sizeof(*p
), M_WAITOK
| M_NULLOK
);
262 p
= (struct ng_sscfu_getdefparam
*)resp
->data
;
263 p
->mask
= sscfu_getdefparam(&p
->param
);
267 case NGM_SSCFU_ENABLE
:
268 if (msg
->header
.arglen
!= 0) {
279 case NGM_SSCFU_DISABLE
:
280 if (msg
->header
.arglen
!= 0) {
284 if (!priv
->enabled
) {
289 sscfu_reset(priv
->sscf
);
292 case NGM_SSCFU_GETSTATE
:
293 if (msg
->header
.arglen
!= 0) {
297 NG_MKRESPONSE(resp
, msg
, sizeof(uint32_t), M_WAITOK
| M_NULLOK
);
302 *(uint32_t *)resp
->data
=
303 priv
->enabled
? (sscfu_getstate(priv
->sscf
) + 1)
307 case NGM_SSCFU_GETDEBUG
:
308 if (msg
->header
.arglen
!= 0) {
312 NG_MKRESPONSE(resp
, msg
, sizeof(uint32_t), M_WAITOK
| M_NULLOK
);
317 *(uint32_t *)resp
->data
= sscfu_getdebug(priv
->sscf
);
320 case NGM_SSCFU_SETDEBUG
:
321 if (msg
->header
.arglen
!= sizeof(uint32_t)) {
325 sscfu_setdebug(priv
->sscf
, *(uint32_t *)msg
->data
);
339 NG_RESPOND_MSG(error
, node
, item
, resp
);
345 /************************************************************/
350 ng_sscfu_newhook(node_p node
, hook_p hook
, const char *name
)
352 struct priv
*priv
= NG_NODE_PRIVATE(node
);
354 if (strcmp(name
, "upper") == 0)
356 else if (strcmp(name
, "lower") == 0) {
358 NG_HOOK_SET_RCVDATA(hook
, ng_sscfu_rcvlower
);
365 ng_sscfu_disconnect(hook_p hook
)
367 node_p node
= NG_HOOK_NODE(hook
);
368 struct priv
*priv
= NG_NODE_PRIVATE(node
);
370 if (hook
== priv
->upper
)
372 else if (hook
== priv
->lower
)
375 log(LOG_ERR
, "bogus hook");
379 if (NG_NODE_NUMHOOKS(node
) == 0) {
380 if (NG_NODE_IS_VALID(node
))
381 ng_rmnode_self(node
);
384 * Because there are no timeouts reset the protocol
385 * if the lower layer is disconnected.
387 if (priv
->lower
== NULL
&&
389 sscfu_getstate(priv
->sscf
) != SSCFU_RELEASED
)
390 sscfu_reset(priv
->sscf
);
395 /************************************************************/
400 ng_sscfu_rcvupper(hook_p hook
, item_p item
)
402 node_p node
= NG_HOOK_NODE(hook
);
403 struct priv
*priv
= NG_NODE_PRIVATE(node
);
407 if (!priv
->enabled
|| priv
->lower
== NULL
) {
415 if (!(m
->m_flags
& M_PKTHDR
)) {
416 printf("no pkthdr\n");
420 if (m
->m_len
< (int)sizeof(a
) && (m
= m_pullup(m
, sizeof(a
))) == NULL
)
422 bcopy((caddr_t
)mtod(m
, struct sscfu_arg
*), &a
, sizeof(a
));
425 return (sscfu_saalsig(priv
->sscf
, a
.sig
, m
));
429 sscfu_send_upper(struct sscfu
*sscf
, void *p
, enum saal_sig sig
, struct mbuf
*m
)
431 node_p node
= (node_p
)p
;
432 struct priv
*priv
= NG_NODE_PRIVATE(node
);
436 if (priv
->upper
== NULL
) {
442 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
445 m
->m_len
= sizeof(struct sscfu_arg
);
446 m
->m_pkthdr
.len
= m
->m_len
;
448 M_PREPEND(m
, sizeof(struct sscfu_arg
), MB_DONTWAIT
);
452 a
= mtod(m
, struct sscfu_arg
*);
455 NG_SEND_DATA_ONLY(error
, priv
->upper
, m
);
459 ng_sscfu_rcvlower(hook_p hook
, item_p item
)
461 node_p node
= NG_HOOK_NODE(hook
);
462 struct priv
*priv
= NG_NODE_PRIVATE(node
);
466 if (!priv
->enabled
|| priv
->upper
== NULL
) {
474 if (!(m
->m_flags
& M_PKTHDR
)) {
475 printf("no pkthdr\n");
481 * Strip of the SSCOP header.
483 if (m
->m_len
< (int)sizeof(a
) && (m
= m_pullup(m
, sizeof(a
))) == NULL
)
485 bcopy((caddr_t
)mtod(m
, struct sscop_arg
*), &a
, sizeof(a
));
488 sscfu_input(priv
->sscf
, a
.sig
, m
, a
.arg
);
494 sscfu_send_lower(struct sscfu
*sscf
, void *p
, enum sscop_aasig sig
,
495 struct mbuf
*m
, u_int arg
)
497 node_p node
= (node_p
)p
;
498 struct priv
*priv
= NG_NODE_PRIVATE(node
);
502 if (priv
->lower
== NULL
) {
508 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
511 m
->m_len
= sizeof(struct sscop_arg
);
512 m
->m_pkthdr
.len
= m
->m_len
;
514 M_PREPEND(m
, sizeof(struct sscop_arg
), MB_DONTWAIT
);
518 a
= mtod(m
, struct sscop_arg
*);
522 NG_SEND_DATA_ONLY(error
, priv
->lower
, m
);
526 * Window is handled by ng_sscop so make this a NOP.
529 sscfu_window(struct sscfu
*sscfu
, void *arg
, u_int w
)
533 /************************************************************/
538 ng_sscfu_constructor(node_p node
)
542 if ((priv
= kmalloc(sizeof(*priv
), M_NG_SSCFU
, M_WAITOK
| M_NULLOK
| M_ZERO
)) == NULL
)
545 if ((priv
->sscf
= sscfu_create(node
, &sscfu_funcs
)) == NULL
) {
546 kfree(priv
, M_NG_SSCFU
);
550 NG_NODE_SET_PRIVATE(node
, priv
);
556 ng_sscfu_shutdown(node_p node
)
558 struct priv
*priv
= NG_NODE_PRIVATE(node
);
560 sscfu_destroy(priv
->sscf
);
562 kfree(priv
, M_NG_SSCFU
);
563 NG_NODE_SET_PRIVATE(node
, NULL
);
571 sscfu_verbose(struct sscfu
*sscfu
, void *arg
, const char *fmt
, ...)
576 printf("sscfu(%p): ", sscfu
);
582 /************************************************************/
587 * Loading and unloading of node type
590 ng_sscfu_mod_event(module_t mod
, int event
, void *data
)