FreeBSD kernel netgraph code
ng_ccatm.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2001-2002
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 * Copyright (c) 2003-2004
6 * Hartmut Brandt
7 * All rights reserved.
8 *
9 * Author: Harti Brandt <harti@freebsd.org>
10 *
11 * Redistribution of this software and documentation and use in source and
12 * binary forms, with or without modification, are permitted provided that
13 * the following conditions are met:
14 *
15 * 1. Redistributions of source code or documentation must retain the above
16 * copyright notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $FreeBSD$
34 *
35 * ATM call control and API
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD$");
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/malloc.h>
45#include <sys/mbuf.h>
46#include <sys/errno.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/sbuf.h>
50#include <machine/stdarg.h>
51
52#include <netgraph/ng_message.h>
53#include <netgraph/netgraph.h>
54#include <netgraph/ng_parse.h>
55#include <netnatm/unimsg.h>
56#include <netnatm/msg/unistruct.h>
57#include <netnatm/api/unisap.h>
58#include <netnatm/sig/unidef.h>
60#include <netgraph/atm/ng_uni.h>
61#include <netnatm/api/atmapi.h>
63#include <netnatm/api/ccatm.h>
64
65MODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1);
66
67MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node");
68
69/*
70 * Command structure parsing
71 */
72
73/* ESI */
76static const struct ng_parse_type ng_ccatm_esi_type = {
79};
80
81/* PORT PARAMETERS */
87};
88
89/* PORT structure */
92static const struct ng_parse_type ng_ccatm_port_type = {
95};
96
97/* the ADDRESS array itself */
103};
104
105/* one ADDRESS */
111};
112
113/* ADDRESS request */
119};
120
121/* ADDRESS var-array */
122static int
124 const u_char *start, const u_char *buf)
125{
126 const struct ngm_ccatm_get_addresses *p;
127
128 p = (const struct ngm_ccatm_get_addresses *)
129 (buf - offsetof(struct ngm_ccatm_get_addresses, addr));
130 return (p->count);
131}
137};
138
139/* Outer get_ADDRESSes structure */
145};
146
147/* Port array */
148static int
150 const u_char *start, const u_char *buf)
151{
152 const struct ngm_ccatm_portlist *p;
153
154 p = (const struct ngm_ccatm_portlist *)
155 (buf - offsetof(struct ngm_ccatm_portlist, ports));
156 return (p->nports);
157}
163};
164
165/* Portlist structure */
171};
172
173/*
174 * Command list
175 */
176static const struct ng_cmdlist ng_ccatm_cmdlist[] = {
177 {
180 "dump",
181 NULL,
182 NULL
183 },
184 {
187 "stop",
189 NULL
190 },
191 {
194 "start",
196 NULL
197 },
198 {
201 "getstate",
204 },
205 {
208 "get_addresses",
211 },
212 {
215 "clear",
217 NULL
218 },
219 {
222 "address_reg",
224 NULL
225 },
226 {
229 "address_unreg",
231 NULL
232 },
233 {
236 "set_port_param",
238 NULL
239 },
240 {
243 "get_port_param",
246 },
247 {
250 "get_portlist",
251 NULL,
253 },
254 {
257 "setlog",
260 },
261 {
264 "reset",
265 NULL,
266 NULL,
267 },
268 { 0 }
269};
270
271/*
272 * Module data
273 */
280static int ng_ccatm_mod_event(module_t, int, void *);
281
284 .name = NG_CCATM_NODE_TYPE,
285 .mod_event = ng_ccatm_mod_event,
286 .constructor = ng_ccatm_constructor, /* Node constructor */
287 .rcvmsg = ng_ccatm_rcvmsg, /* Control messages */
288 .shutdown = ng_ccatm_shutdown, /* Node destructor */
289 .newhook = ng_ccatm_newhook, /* Arrival of new hook */
290 .rcvdata = ng_ccatm_rcvdata, /* receive data */
291 .disconnect = ng_ccatm_disconnect, /* disconnect a hook */
292 .cmdlist = ng_ccatm_cmdlist,
293};
295
299
300/*
301 * Private node data.
302 */
303struct ccnode {
304 node_p node; /* the owning node */
305 hook_p dump; /* dump hook */
306 hook_p manage; /* hook to ILMI */
307
308 struct ccdata *data;
309 struct mbuf *dump_first;
310 struct mbuf *dump_last; /* first and last mbuf when dumping */
311
312 u_int hook_cnt; /* count user and port hooks */
313};
314
315/*
316 * Private UNI hook data
317 */
318struct cchook {
319 int is_uni; /* true if uni hook, user otherwise */
320 struct ccnode *node; /* the owning node */
322 void *inst; /* port or user */
323};
324
325static void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t);
326static void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int,
327 void *, size_t);
328static void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int,
329 struct uni_msg *);
330static void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int,
331 struct uni_msg *);
332static void ng_ccatm_log(const char *, ...) __printflike(1, 2);
333
334static const struct cc_funcs cc_funcs = {
335 .send_user = ng_ccatm_send_user,
336 .respond_user = ng_ccatm_respond_user,
337 .send_uni = ng_ccatm_send_uni,
338 .send_uni_glob = ng_ccatm_send_uni_glob,
339 .log = ng_ccatm_log,
340};
341
342/************************************************************
343 *
344 * Create a new node
345 */
346static int
348{
349 struct ccnode *priv;
350
351 priv = malloc(sizeof(*priv), M_NG_CCATM, M_WAITOK | M_ZERO);
352
353 priv->node = node;
354 priv->data = cc_create(&cc_funcs);
355 if (priv->data == NULL) {
356 free(priv, M_NG_CCATM);
357 return (ENOMEM);
358 }
359
361
362 return (0);
363}
364
365/*
366 * Destroy a node. The user list is empty here, because all hooks are
367 * previously disconnected. The connection lists may not be empty, because
368 * connections may be waiting for responses from the stack. This also means,
369 * that no orphaned connections will be made by the port_destroy routine.
370 */
371static int
373{
374 struct ccnode *priv = NG_NODE_PRIVATE(node);
375
376 cc_destroy(priv->data);
377
378 free(priv, M_NG_CCATM);
380
382
383 return (0);
384}
385
386/*
387 * Retrieve the registered addresses for one port or all ports.
388 * Returns an error code or 0 on success.
389 */
390static int
391ng_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg,
392 struct ng_mesg **resp)
393{
394 struct ccnode *priv = NG_NODE_PRIVATE(node);
395 struct uni_addr *addrs;
396 u_int *ports;
397 struct ngm_ccatm_get_addresses *list;
398 u_int count, i;
399 size_t len;
400 int err;
401
402 err = cc_get_addrs(priv->data, portno, &addrs, &ports, &count);
403 if (err != 0)
404 return (err);
405
406 len = sizeof(*list) + count * sizeof(list->addr[0]);
407 NG_MKRESPONSE(*resp, msg, len, M_NOWAIT);
408 if (*resp == NULL) {
409 free(addrs, M_NG_CCATM);
410 free(ports, M_NG_CCATM);
411 return (ENOMEM);
412 }
413 list = (struct ngm_ccatm_get_addresses *)(*resp)->data;
414
415 list->count = count;
416 for (i = 0; i < count; i++) {
417 list->addr[i].port = ports[i];
418 list->addr[i].addr = addrs[i];
419 }
420
421 free(addrs, M_NG_CCATM);
422 free(ports, M_NG_CCATM);
423
424 return (0);
425}
426
427/*
428 * Dumper function. Pack the data into an mbuf chain.
429 */
430static int
431send_dump(struct ccdata *data, void *uarg, const char *buf)
432{
433 struct mbuf *m;
434 struct ccnode *priv = uarg;
435
436 if (priv->dump == NULL) {
437 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
438 if (m == NULL)
439 return (ENOBUFS);
440 priv->dump_first = priv->dump_last = m;
441 m->m_pkthdr.len = 0;
442 } else {
443 m = m_getcl(M_NOWAIT, MT_DATA, 0);
444 if (m == NULL) {
445 m_freem(priv->dump_first);
446 return (ENOBUFS);
447 }
448 priv->dump_last->m_next = m;
449 priv->dump_last = m;
450 }
451
452 strcpy(m->m_data, buf);
453 priv->dump_first->m_pkthdr.len += (m->m_len = strlen(buf));
454
455 return (0);
456}
457
458/*
459 * Dump current status to dump hook
460 */
461static int
463{
464 struct ccnode *priv = NG_NODE_PRIVATE(node);
465 struct mbuf *m;
466 int error;
467
468 priv->dump_first = priv->dump_last = NULL;
469 error = cc_dump(priv->data, MCLBYTES, send_dump, priv);
470 if (error != 0)
471 return (error);
472
473 if ((m = priv->dump_first) != NULL) {
474 priv->dump_first = priv->dump_last = NULL;
475 NG_SEND_DATA_ONLY(error, priv->dump, m);
476 return (error);
477 }
478 return (0);
479}
480
481/*
482 * Control message
483 */
484static int
485ng_ccatm_rcvmsg(node_p node, item_p item, hook_p lasthook)
486{
487 struct ng_mesg *resp = NULL;
488 struct ng_mesg *msg;
489 struct ccnode *priv = NG_NODE_PRIVATE(node);
490 int error = 0;
491
492 NGI_GET_MSG(item, msg);
493
494 switch (msg->header.typecookie) {
495 case NGM_CCATM_COOKIE:
496 switch (msg->header.cmd) {
497 case NGM_CCATM_DUMP:
498 if (priv->dump)
499 error = ng_ccatm_dump(node);
500 else
501 error = ENOTCONN;
502 break;
503
504 case NGM_CCATM_STOP:
505 {
506 struct ngm_ccatm_port *arg;
507
508 if (msg->header.arglen != sizeof(*arg)) {
509 error = EINVAL;
510 break;
511 }
512 arg = (struct ngm_ccatm_port *)msg->data;
513 error = cc_port_stop(priv->data, arg->port);
514 break;
515 }
516
517 case NGM_CCATM_START:
518 {
519 struct ngm_ccatm_port *arg;
520
521 if (msg->header.arglen != sizeof(*arg)) {
522 error = EINVAL;
523 break;
524 }
525 arg = (struct ngm_ccatm_port *)msg->data;
526 error = cc_port_start(priv->data, arg->port);
527 break;
528 }
529
531 {
532 struct ngm_ccatm_port *arg;
533 int state;
534
535 if (msg->header.arglen != sizeof(*arg)) {
536 error = EINVAL;
537 break;
538 }
539 arg = (struct ngm_ccatm_port *)msg->data;
540 error = cc_port_isrunning(priv->data, arg->port,
541 &state);
542 if (error == 0) {
543 NG_MKRESPONSE(resp, msg, sizeof(uint32_t),
544 M_NOWAIT);
545 if (resp == NULL) {
546 error = ENOMEM;
547 break;
548 }
549 *(uint32_t *)resp->data = state;
550 }
551 break;
552 }
553
555 {
556 struct ngm_ccatm_port *arg;
557
558 if (msg->header.arglen != sizeof(*arg)) {
559 error = EINVAL;
560 break;
561 }
562 arg = (struct ngm_ccatm_port *)msg->data;
563 error = ng_ccatm_get_addresses(node, arg->port, msg,
564 &resp);
565 break;
566 }
567
568 case NGM_CCATM_CLEAR:
569 {
570 struct ngm_ccatm_port *arg;
571
572 if (msg->header.arglen != sizeof(*arg)) {
573 error = EINVAL;
574 break;
575 }
576 arg = (struct ngm_ccatm_port *)msg->data;
577 error = cc_port_clear(priv->data, arg->port);
578 break;
579 }
580
582 {
583 struct ngm_ccatm_addr_req *arg;
584
585 if (msg->header.arglen != sizeof(*arg)) {
586 error = EINVAL;
587 break;
588 }
589 arg = (struct ngm_ccatm_addr_req *)msg->data;
590 error = cc_addr_register(priv->data, arg->port,
591 &arg->addr);
592 break;
593 }
594
596 {
597 struct ngm_ccatm_addr_req *arg;
598
599 if (msg->header.arglen != sizeof(*arg)) {
600 error = EINVAL;
601 break;
602 }
603 arg = (struct ngm_ccatm_addr_req *)msg->data;
604 error = cc_addr_unregister(priv->data, arg->port,
605 &arg->addr);
606 break;
607 }
608
610 {
611 struct ngm_ccatm_port *arg;
612
613 if (msg->header.arglen != sizeof(*arg)) {
614 error = EINVAL;
615 break;
616 }
617 arg = (struct ngm_ccatm_port *)msg->data;
618 NG_MKRESPONSE(resp, msg, sizeof(struct atm_port_info),
619 M_NOWAIT);
620 if (resp == NULL) {
621 error = ENOMEM;
622 break;
623 }
624 error = cc_port_get_param(priv->data, arg->port,
625 (struct atm_port_info *)resp->data);
626 if (error != 0) {
627 free(resp, M_NETGRAPH_MSG);
628 resp = NULL;
629 }
630 break;
631 }
632
634 {
635 struct atm_port_info *arg;
636
637 if (msg->header.arglen != sizeof(*arg)) {
638 error = EINVAL;
639 break;
640 }
641 arg = (struct atm_port_info *)msg->data;
642 error = cc_port_set_param(priv->data, arg);
643 break;
644 }
645
647 {
648 struct ngm_ccatm_portlist *arg;
649 u_int n, *ports;
650
651 if (msg->header.arglen != 0) {
652 error = EINVAL;
653 break;
654 }
655 error = cc_port_getlist(priv->data, &n, &ports);
656 if (error != 0)
657 break;
658
659 NG_MKRESPONSE(resp, msg, sizeof(*arg) +
660 n * sizeof(arg->ports[0]), M_NOWAIT);
661 if (resp == NULL) {
662 free(ports, M_NG_CCATM);
663 error = ENOMEM;
664 break;
665 }
666 arg = (struct ngm_ccatm_portlist *)resp->data;
667
668 arg->nports = 0;
669 for (arg->nports = 0; arg->nports < n; arg->nports++)
670 arg->ports[arg->nports] = ports[arg->nports];
671 free(ports, M_NG_CCATM);
672 break;
673 }
674
675 case NGM_CCATM_SETLOG:
676 {
677 uint32_t log_level;
678
679 log_level = cc_get_log(priv->data);
680 if (msg->header.arglen != 0) {
681 if (msg->header.arglen != sizeof(log_level)) {
682 error = EINVAL;
683 break;
684 }
685 cc_set_log(priv->data, *(uint32_t *)msg->data);
686 }
687
688 NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
689 if (resp == NULL) {
690 error = ENOMEM;
691 if (msg->header.arglen != 0)
692 cc_set_log(priv->data, log_level);
693 break;
694 }
695 *(uint32_t *)resp->data = log_level;
696 break;
697 }
698
699 case NGM_CCATM_RESET:
700 if (msg->header.arglen != 0) {
701 error = EINVAL;
702 break;
703 }
704
705 if (priv->hook_cnt != 0) {
706 error = EBUSY;
707 break;
708 }
709 cc_reset(priv->data);
710 break;
711
713 {
714 struct atm_exstatus s;
715 struct atm_exstatus_ep *eps;
716 struct atm_exstatus_port *ports;
717 struct atm_exstatus_conn *conns;
718 struct atm_exstatus_party *parties;
719 size_t offs;
720
721 if (msg->header.arglen != 0) {
722 error = EINVAL;
723 break;
724 }
725 error = cc_get_extended_status(priv->data,
726 &s, &eps, &ports, &conns, &parties);
727 if (error != 0)
728 break;
729
730 offs = sizeof(s) + s.neps * sizeof(*eps) +
731 s.nports * sizeof(*ports) +
732 s.nconns * sizeof(*conns) +
733 s.nparties * sizeof(*parties);
734
735 NG_MKRESPONSE(resp, msg, offs, M_NOWAIT);
736 if (resp == NULL) {
737 error = ENOMEM;
738 break;
739 }
740
741 memcpy(resp->data, &s, sizeof(s));
742 offs = sizeof(s);
743
744 memcpy(resp->data + offs, eps,
745 sizeof(*eps) * s.neps);
746 offs += sizeof(*eps) * s.neps;
747
748 memcpy(resp->data + offs, ports,
749 sizeof(*ports) * s.nports);
750 offs += sizeof(*ports) * s.nports;
751
752 memcpy(resp->data + offs, conns,
753 sizeof(*conns) * s.nconns);
754 offs += sizeof(*conns) * s.nconns;
755
756 memcpy(resp->data + offs, parties,
757 sizeof(*parties) * s.nparties);
758 offs += sizeof(*parties) * s.nparties;
759
760 free(eps, M_NG_CCATM);
761 free(ports, M_NG_CCATM);
762 free(conns, M_NG_CCATM);
763 free(parties, M_NG_CCATM);
764 break;
765 }
766
767 default:
768 error = EINVAL;
769 break;
770 }
771 break;
772
773 default:
774 error = EINVAL;
775 break;
776 }
777
778 NG_RESPOND_MSG(error, node, item, resp);
779 NG_FREE_MSG(msg);
780 return (error);
781}
782
783/************************************************************
784 *
785 * New hook arrival
786 */
787static int
788ng_ccatm_newhook(node_p node, hook_p hook, const char *name)
789{
790 struct ccnode *priv = NG_NODE_PRIVATE(node);
791 struct ccport *port;
792 struct ccuser *user;
793 struct cchook *hd;
794 u_long lport;
795 char *end;
796
797 if (strncmp(name, "uni", 3) == 0) {
798 /*
799 * This is a UNI hook. Should be a new port.
800 */
801 if (name[3] == '\0')
802 return (EINVAL);
803 lport = strtoul(name + 3, &end, 10);
804 if (*end != '\0' || lport == 0 || lport > 0xffffffff)
805 return (EINVAL);
806
807 hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
808 if (hd == NULL)
809 return (ENOMEM);
810 hd->is_uni = 1;
811 hd->node = priv;
812 hd->hook = hook;
813
814 port = cc_port_create(priv->data, hd, (u_int)lport);
815 if (port == NULL) {
816 free(hd, M_NG_CCATM);
817 return (ENOMEM);
818 }
819 hd->inst = port;
820
824
825 priv->hook_cnt++;
826
827 return (0);
828 }
829
830 if (strcmp(name, "dump") == 0) {
831 priv->dump = hook;
833 return (0);
834 }
835
836 if (strcmp(name, "manage") == 0) {
837 priv->manage = hook;
839 return (0);
840 }
841
842 /*
843 * User hook
844 */
845 hd = malloc(sizeof(*hd), M_NG_CCATM, M_NOWAIT);
846 if (hd == NULL)
847 return (ENOMEM);
848 hd->is_uni = 0;
849 hd->node = priv;
850 hd->hook = hook;
851
852 user = cc_user_create(priv->data, hd, NG_HOOK_NAME(hook));
853 if (user == NULL) {
854 free(hd, M_NG_CCATM);
855 return (ENOMEM);
856 }
857
858 hd->inst = user;
861
862 priv->hook_cnt++;
863
864 return (0);
865}
866
867/*
868 * Disconnect a hook
869 */
870static int
872{
874 struct ccnode *priv = NG_NODE_PRIVATE(node);
875 struct cchook *hd = NG_HOOK_PRIVATE(hook);
876 struct ccdata *cc;
877
878 if (hook == priv->dump) {
879 priv->dump = NULL;
880
881 } else if (hook == priv->manage) {
882 priv->manage = NULL;
883 cc_unmanage(priv->data);
884
885 } else {
886 if (hd->is_uni)
887 cc_port_destroy(hd->inst, 0);
888 else
889 cc_user_destroy(hd->inst);
890
891 cc = hd->node->data;
892
893 free(hd, M_NG_CCATM);
894 NG_HOOK_SET_PRIVATE(hook, NULL);
895
896 priv->hook_cnt--;
897
898 cc_work(cc);
899 }
900
901 /*
902 * When the number of hooks drops to zero, delete the node.
903 */
904 if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
905 ng_rmnode_self(node);
906
907 return (0);
908}
909
910/************************************************************
911 *
912 * Receive data from user hook
913 */
914static int
916{
917 struct cchook *hd = NG_HOOK_PRIVATE(hook);
918 struct uni_msg *msg;
919 struct mbuf *m;
920 struct ccatm_op op;
921 int err;
922
923 NGI_GET_M(item, m);
924 NG_FREE_ITEM(item);
925
926 if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
927 m_freem(m);
928 return (err);
929 }
930 m_freem(m);
931
932 if (uni_msg_len(msg) < sizeof(op)) {
933 printf("%s: packet too short\n", __func__);
934 uni_msg_destroy(msg);
935 return (EINVAL);
936 }
937
938 bcopy(msg->b_rptr, &op, sizeof(op));
939 msg->b_rptr += sizeof(op);
940
941 err = cc_user_signal(hd->inst, op.op, msg);
942 cc_work(hd->node->data);
943 return (err);
944}
945
946/*
947 * Pack a header and a data area into an mbuf chain
948 */
949static struct mbuf *
950pack_buf(void *h, size_t hlen, void *t, size_t tlen)
951{
952 struct mbuf *m, *m0, *last;
953 u_char *buf = (u_char *)t;
954 size_t n;
955
956 /* header should fit into a normal mbuf */
957 MGETHDR(m0, M_NOWAIT, MT_DATA);
958 if (m0 == NULL)
959 return NULL;
960
961 KASSERT(hlen <= MHLEN, ("hlen > MHLEN"));
962
963 bcopy(h, m0->m_data, hlen);
964 m0->m_len = hlen;
965 m0->m_pkthdr.len = hlen;
966
967 last = m0;
968 while ((n = tlen) != 0) {
969 if (n > MLEN) {
970 m = m_getcl(M_NOWAIT, MT_DATA, 0);
971 if (n > MCLBYTES)
972 n = MCLBYTES;
973 } else
974 MGET(m, M_NOWAIT, MT_DATA);
975
976 if(m == NULL)
977 goto drop;
978
979 last->m_next = m;
980 last = m;
981
982 bcopy(buf, m->m_data, n);
983 buf += n;
984 tlen -= n;
985 m->m_len = n;
986 m0->m_pkthdr.len += n;
987 }
988
989 return (m0);
990
991 drop:
992 m_freem(m0);
993 return NULL;
994}
995
996/*
997 * Send an indication to the user.
998 */
999static void
1000ng_ccatm_send_user(struct ccuser *user, void *uarg, u_int op,
1001 void *val, size_t len)
1002{
1003 struct cchook *hd = uarg;
1004 struct mbuf *m;
1005 struct ccatm_op h;
1006 int error;
1007
1008 h.op = op;
1009 m = pack_buf(&h, sizeof(h), val, len);
1010 if (m == NULL)
1011 return;
1012
1013 NG_SEND_DATA_ONLY(error, hd->hook, m);
1014 if (error != 0)
1015 printf("%s: error=%d\n", __func__, error);
1016}
1017
1018/*
1019 * Send a response to the user.
1020 */
1021static void
1022ng_ccatm_respond_user(struct ccuser *user, void *uarg, int err, u_int data,
1023 void *val, size_t len)
1024{
1025 struct cchook *hd = uarg;
1026 struct mbuf *m;
1027 struct {
1028 struct ccatm_op op;
1029 struct atm_resp resp;
1030 } resp;
1031 int error;
1032
1033 resp.op.op = ATMOP_RESP;
1034 resp.resp.resp = err;
1035 resp.resp.data = data;
1036 m = pack_buf(&resp, sizeof(resp), val, len);
1037 if (m == NULL)
1038 return;
1039
1040 NG_SEND_DATA_ONLY(error, hd->hook, m);
1041 if (error != 0)
1042 printf("%s: error=%d\n", __func__, error);
1043}
1044
1045/*
1046 * Receive data from UNI.
1047 */
1048static int
1050{
1051 struct cchook *hd = NG_HOOK_PRIVATE(hook);
1052 struct uni_msg *msg;
1053 struct uni_arg arg;
1054 struct mbuf *m;
1055 int err;
1056
1057 NGI_GET_M(item, m);
1058 NG_FREE_ITEM(item);
1059
1060 if ((err = uni_msg_unpack_mbuf(m, &msg)) != 0) {
1061 m_freem(m);
1062 return (err);
1063 }
1064 m_freem(m);
1065
1066 if (uni_msg_len(msg) < sizeof(arg)) {
1067 printf("%s: packet too short\n", __func__);
1068 uni_msg_destroy(msg);
1069 return (EINVAL);
1070 }
1071
1072 bcopy(msg->b_rptr, &arg, sizeof(arg));
1073 msg->b_rptr += sizeof(arg);
1074
1075 if (arg.sig == UNIAPI_ERROR) {
1076 if (uni_msg_len(msg) != sizeof(struct uniapi_error)) {
1077 printf("%s: bad UNIAPI_ERROR size %zu\n", __func__,
1078 uni_msg_len(msg));
1079 uni_msg_destroy(msg);
1080 return (EINVAL);
1081 }
1082 err = cc_uni_response(hd->inst, arg.cookie,
1083 ((struct uniapi_error *)msg->b_rptr)->reason,
1084 ((struct uniapi_error *)msg->b_rptr)->state);
1085 uni_msg_destroy(msg);
1086 } else
1087 err = cc_uni_signal(hd->inst, arg.cookie, arg.sig, msg);
1088
1089 cc_work(hd->node->data);
1090 return (err);
1091}
1092
1093/*
1094 * Uarg is the port's uarg.
1095 */
1096static void
1097ng_ccatm_send_uni(struct ccconn *conn, void *uarg, u_int op, u_int cookie,
1098 struct uni_msg *msg)
1099{
1100 struct cchook *hd = uarg;
1101 struct uni_arg arg;
1102 struct mbuf *m;
1103 int error;
1104
1105 arg.sig = op;
1106 arg.cookie = cookie;
1107
1108 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1109 uni_msg_destroy(msg);
1110 if (m == NULL)
1111 return;
1112
1113 NG_SEND_DATA_ONLY(error, hd->hook, m);
1114 if (error != 0)
1115 printf("%s: error=%d\n", __func__, error);
1116}
1117
1118/*
1119 * Send a global message to the UNI
1120 */
1121static void
1122ng_ccatm_send_uni_glob(struct ccport *port, void *uarg, u_int op, u_int cookie,
1123 struct uni_msg *msg)
1124{
1125 struct cchook *hd = uarg;
1126 struct uni_arg arg;
1127 struct mbuf *m;
1128 int error;
1129
1130 arg.sig = op;
1131 arg.cookie = cookie;
1132
1133 m = uni_msg_pack_mbuf(msg, &arg, sizeof(arg));
1134 if (msg != NULL)
1135 uni_msg_destroy(msg);
1136 if (m == NULL)
1137 return;
1138
1139 NG_SEND_DATA_ONLY(error, hd->hook, m);
1140 if (error != 0)
1141 printf("%s: error=%d\n", __func__, error);
1142}
1143/*
1144 * Receive from ILMID
1145 */
1146static int
1148{
1149 NG_FREE_ITEM(item);
1150 return (0);
1151}
1152
1153static int
1155{
1156 NG_FREE_ITEM(item);
1157 return (0);
1158}
1159
1160static void
1161ng_ccatm_log(const char *fmt, ...)
1162{
1163 va_list ap;
1164
1165 va_start(ap, fmt);
1166 vprintf(fmt, ap);
1167 printf("\n");
1168 va_end(ap);
1169}
1170
1171/*
1172 * Loading and unloading of node type
1173 */
1174static int
1175ng_ccatm_mod_event(module_t mod, int event, void *data)
1176{
1177 int error = 0;
1178
1179 switch (event) {
1180 case MOD_LOAD:
1181 break;
1182
1183 case MOD_UNLOAD:
1184 break;
1185
1186 default:
1187 error = EOPNOTSUPP;
1188 break;
1189 }
1190 return (error);
1191}
uint32_t last
Definition: netflow.h:8
uint16_t count
Definition: netflow.h:1
#define NG_HOOK_NODE(hook)
Definition: netgraph.h:339
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
Definition: netgraph.h:105
int ng_disconnect_t(hook_p hook)
Definition: netgraph.h:107
#define NG_NODE_SET_PRIVATE(node, val)
Definition: netgraph.h:608
#define NG_RESPOND_MSG(error, here, item, resp)
Definition: netgraph.h:1025
#define NG_NODE_IS_VALID(node)
Definition: netgraph.h:610
#define NG_NODE_UNREF(node)
Definition: netgraph.h:607
#define NG_HOOK_SET_PRIVATE(hook, val)
Definition: netgraph.h:333
int ng_rmnode_self(node_p here)
Definition: ng_base.c:1609
#define NG_SEND_DATA_ONLY(error, hook, m)
Definition: netgraph.h:932
#define NG_HOOK_FORCE_QUEUE(hook)
Definition: netgraph.h:342
int ng_rcvdata_t(hook_p hook, item_p item)
Definition: netgraph.h:106
int ng_shutdown_t(node_p node)
Definition: netgraph.h:101
#define NG_HOOK_NAME(hook)
Definition: netgraph.h:331
#define NG_FREE_ITEM(item)
Definition: netgraph.h:847
#define NG_HOOK_SET_RCVDATA(hook, val)
Definition: netgraph.h:335
int ng_constructor_t(node_p node)
Definition: netgraph.h:99
#define NGI_GET_M(i, m)
Definition: netgraph.h:852
#define NG_FREE_MSG(msg)
Definition: netgraph.h:938
#define NG_ABI_VERSION
Definition: netgraph.h:77
#define NG_NODE_NUMHOOKS(node)
Definition: netgraph.h:615
#define NGI_GET_MSG(i, m)
Definition: netgraph.h:858
#define NG_NODE_PRIVATE(node)
Definition: netgraph.h:609
int ng_newhook_t(node_p node, hook_p hook, const char *name)
Definition: netgraph.h:102
#define NG_HOOK_PRIVATE(hook)
Definition: netgraph.h:336
u_int8_t type
static void ng_ccatm_log(const char *,...)
Definition: ng_ccatm.c:332
static const struct ng_parse_fixedarray_info ng_ccatm_esi_type_info
Definition: ng_ccatm.c:74
static ng_shutdown_t ng_ccatm_shutdown
Definition: ng_ccatm.c:276
static ng_disconnect_t ng_ccatm_disconnect
Definition: ng_ccatm.c:279
static struct mbuf * pack_buf(void *h, size_t hlen, void *t, size_t tlen)
Definition: ng_ccatm.c:950
static int ng_ccatm_dump(node_p node)
Definition: ng_ccatm.c:462
static const struct ng_cmdlist ng_ccatm_cmdlist[]
Definition: ng_ccatm.c:176
static ng_rcvdata_t ng_ccatm_rcvmanage
Definition: ng_ccatm.c:298
static const struct ng_parse_type ng_ccatm_get_addresses_type
Definition: ng_ccatm.c:142
static ng_rcvmsg_t ng_ccatm_rcvmsg
Definition: ng_ccatm.c:275
static const struct ng_parse_type ng_ccatm_port_type
Definition: ng_ccatm.c:92
static const struct ng_parse_type ng_ccatm_port_array_type
Definition: ng_ccatm.c:160
static const struct ng_parse_type ng_ccatm_uni_addr_type
Definition: ng_ccatm.c:108
static struct ng_type ng_ccatm_typestruct
Definition: ng_ccatm.c:282
static const struct ng_parse_type ng_ccatm_portlist_type
Definition: ng_ccatm.c:168
static const struct ng_parse_struct_field ng_ccatm_uni_addr_type_info[]
Definition: ng_ccatm.c:106
static void ng_ccatm_send_uni_glob(struct ccport *, void *, u_int, u_int, struct uni_msg *)
Definition: ng_ccatm.c:1122
static void ng_ccatm_send_user(struct ccuser *, void *, u_int, void *, size_t)
Definition: ng_ccatm.c:1000
static int send_dump(struct ccdata *data, void *uarg, const char *buf)
Definition: ng_ccatm.c:431
static int ng_ccatm_addr_req_array_getlen(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
Definition: ng_ccatm.c:123
static const struct ng_parse_type ng_ccatm_atm_port_type
Definition: ng_ccatm.c:84
static int ng_ccatm_get_addresses(node_p node, uint32_t portno, struct ng_mesg *msg, struct ng_mesg **resp)
Definition: ng_ccatm.c:391
static ng_newhook_t ng_ccatm_newhook
Definition: ng_ccatm.c:277
static ng_rcvdata_t ng_ccatm_rcvdata
Definition: ng_ccatm.c:278
static const struct ng_parse_type ng_ccatm_addr_array_type
Definition: ng_ccatm.c:100
static ng_rcvdata_t ng_ccatm_rcvdump
Definition: ng_ccatm.c:297
MODULE_DEPEND(ng_ccatm, ngatmbase, 1, 1, 1)
static const struct ng_parse_struct_field ng_ccatm_get_addresses_type_info[]
Definition: ng_ccatm.c:140
static const struct ng_parse_array_info ng_ccatm_addr_req_array_type_info
Definition: ng_ccatm.c:132
__FBSDID("$FreeBSD$")
static const struct ng_parse_struct_field ng_ccatm_atm_port_type_info[]
Definition: ng_ccatm.c:82
static int ng_ccatm_port_array_getlen(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
Definition: ng_ccatm.c:149
static ng_constructor_t ng_ccatm_constructor
Definition: ng_ccatm.c:274
NETGRAPH_INIT(ccatm, &ng_ccatm_typestruct)
static void ng_ccatm_respond_user(struct ccuser *, void *, int, u_int, void *, size_t)
Definition: ng_ccatm.c:1022
static const struct ng_parse_array_info ng_ccatm_port_array_type_info
Definition: ng_ccatm.c:158
static const struct ng_parse_struct_field ng_ccatm_addr_req_type_info[]
Definition: ng_ccatm.c:114
static void ng_ccatm_send_uni(struct ccconn *, void *, u_int, u_int, struct uni_msg *)
Definition: ng_ccatm.c:1097
static const struct ng_parse_fixedarray_info ng_ccatm_addr_array_type_info
Definition: ng_ccatm.c:98
static const struct ng_parse_type ng_ccatm_addr_req_type
Definition: ng_ccatm.c:116
static const struct ng_parse_struct_field ng_ccatm_portlist_type_info[]
Definition: ng_ccatm.c:166
static int ng_ccatm_mod_event(module_t, int, void *)
Definition: ng_ccatm.c:1175
static const struct ng_parse_type ng_ccatm_addr_req_array_type
Definition: ng_ccatm.c:134
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
static ng_rcvdata_t ng_ccatm_rcvuni
Definition: ng_ccatm.c:296
static const struct ng_parse_type ng_ccatm_esi_type
Definition: ng_ccatm.c:76
static const struct ng_parse_struct_field ng_ccatm_port_type_info[]
Definition: ng_ccatm.c:90
#define NGM_CCATM_ESI_INFO
Definition: ng_ccatm.h:129
#define NGM_CCATM_PORT_INFO
Definition: ng_ccatm.h:119
@ NGM_CCATM_ADDRESS_REGISTERED
Definition: ng_ccatm.h:51
@ NGM_CCATM_START
Definition: ng_ccatm.h:48
@ NGM_CCATM_GETSTATE
Definition: ng_ccatm.h:56
@ NGM_CCATM_ADDRESS_UNREGISTERED
Definition: ng_ccatm.h:52
@ NGM_CCATM_CLEAR
Definition: ng_ccatm.h:49
@ NGM_CCATM_DUMP
Definition: ng_ccatm.h:46
@ NGM_CCATM_SET_PORT_PARAM
Definition: ng_ccatm.h:53
@ NGM_CCATM_GET_PORT_PARAM
Definition: ng_ccatm.h:54
@ NGM_CCATM_RESET
Definition: ng_ccatm.h:58
@ NGM_CCATM_GET_ADDRESSES
Definition: ng_ccatm.h:50
@ NGM_CCATM_SETLOG
Definition: ng_ccatm.h:57
@ NGM_CCATM_GET_EXSTAT
Definition: ng_ccatm.h:59
@ NGM_CCATM_GET_PORTLIST
Definition: ng_ccatm.h:55
@ NGM_CCATM_STOP
Definition: ng_ccatm.h:47
#define NG_CCATM_NODE_TYPE
Definition: ng_ccatm.h:42
#define NGM_CCATM_ADDR_REQ_ARRAY_INFO
Definition: ng_ccatm.h:101
#define NGM_CCATM_UNI_ADDR_INFO
Definition: ng_ccatm.h:71
#define NGM_CCATM_GET_ADDRESSES_INFO
Definition: ng_ccatm.h:106
#define NGM_CCATM_PORT_ARRAY_INFO
Definition: ng_ccatm.h:155
#define NGM_CCATM_COOKIE
Definition: ng_ccatm.h:43
#define NGM_CCATM_PORTLIST_INFO
Definition: ng_ccatm.h:160
#define NGM_CCATM_ADDR_REQ_INFO
Definition: ng_ccatm.h:87
#define NGM_CCATM_ADDR_ARRAY_INFO
Definition: ng_ccatm.h:65
#define NGM_CCATM_ATM_PORT_INFO
Definition: ng_ccatm.h:134
#define NG_MKRESPONSE(rsp, msg, len, how)
Definition: ng_message.h:396
const struct ng_parse_type ng_parse_fixedarray_type
Definition: ng_parse.c:271
const struct ng_parse_type ng_parse_array_type
Definition: ng_parse.c:318
const struct ng_parse_type ng_parse_struct_type
Definition: ng_parse.c:222
const struct ng_parse_type ng_parse_uint32_type
Definition: ng_parse.c:608
const struct ng_parse_type ng_parse_hint32_type
Definition: ng_parse.c:613
char *const name
Definition: ng_ppp.c:261
state
Definition: ng_pppoe.c:215
uint8_t data[]
Definition: ng_ubt_var.h:2
uint8_t event
Definition: ng_ubt_var.h:0
int uni_msg_unpack_mbuf(struct mbuf *m, struct uni_msg **pmsg)
Definition: ngatmbase.c:458
struct mbuf * uni_msg_pack_mbuf(struct uni_msg *msg, void *hdr, size_t hdrlen)
Definition: ngatmbase.c:138
void uni_msg_destroy(struct uni_msg *m)
Definition: ngatmbase.c:387
uint32_t op
Definition: ng_ccatm.h:168
hook_p hook
Definition: ng_ccatm.c:321
int is_uni
Definition: ng_ccatm.c:319
struct ccnode * node
Definition: ng_ccatm.c:320
void * inst
Definition: ng_ccatm.c:322
struct ccdata * data
Definition: ng_ccatm.c:308
hook_p dump
Definition: ng_ccatm.c:305
hook_p manage
Definition: ng_ccatm.c:306
struct mbuf * dump_first
Definition: ng_ccatm.c:309
node_p node
Definition: ng_ccatm.c:304
struct mbuf * dump_last
Definition: ng_ccatm.c:310
u_int hook_cnt
Definition: ng_ccatm.c:312
u_int32_t arglen
Definition: ng_message.h:62
u_int32_t typecookie
Definition: ng_message.h:66
struct ng_mesg::ng_msghdr header
char data[]
Definition: ng_message.h:69
u_int32_t version
Definition: netgraph.h:1077
uint32_t port
Definition: ng_ccatm.h:84
struct uni_addr addr
Definition: ng_ccatm.h:85
struct ngm_ccatm_addr_req addr[]
Definition: ng_ccatm.h:99
uint32_t port
Definition: ng_ccatm.h:117
uint32_t ports[]
Definition: ng_ccatm.h:153
uint32_t nports
Definition: ng_ccatm.h:152
Definition: ng_sscfu.c:66
hook_p manage
Definition: ng_sscop.c:93
uint32_t cookie
Definition: ng_uni.h:117
uint32_t sig
Definition: ng_uni.h:116