]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/api/cc_port.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / api / cc_port.c
1 /*
2  * Copyright (c) 2003-2004
3  *      Hartmut Brandt
4  *      All rights reserved.
5  *
6  * Copyright (c) 2001-2002
7  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
8  *      All rights reserved.
9  *
10  * Author: Harti Brandt <harti@freebsd.org>
11  *
12  * Redistribution of this software and documentation and use in source and
13  * binary forms, with or without modification, are permitted provided that
14  * the following conditions are met:
15  *
16  * 1. Redistributions of source code or documentation must retain the above
17  *    copyright notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
23  * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
25  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
26  * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
29  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $Begemot: libunimsg/netnatm/api/cc_port.c,v 1.1 2004/07/08 08:21:53 brandt Exp $
35  *
36  * ATM API as defined per af-saa-0108
37  *
38  * Port-global stuff (ILMI and Co.)
39  */
40 #include <netnatm/unimsg.h>
41 #include <netnatm/msg/unistruct.h>
42 #include <netnatm/api/unisap.h>
43 #include <netnatm/sig/unidef.h>
44 #include <netnatm/api/atmapi.h>
45 #include <netnatm/api/ccatm.h>
46 #include <netnatm/api/ccpriv.h>
47
48 /*
49  * Find a port with a given number
50  */
51 static struct ccport *
52 find_port(struct ccdata *cc, u_int portno)
53 {
54         struct ccport *port;
55
56         TAILQ_FOREACH(port, &cc->port_list, node_link)
57                 if (port->param.port == portno)
58                         return (port);
59         return (NULL);
60 }
61
62 /*
63  * Create a new port structure, initialize it and link it to the node.
64  * Returns 0 on success, an errno otherwise.
65  */
66 struct ccport *
67 cc_port_create(struct ccdata *cc, void *uarg, u_int portno)
68 {
69         struct ccport *port, *p1;
70
71         if (portno == 0 || portno > 0xffffffff)
72                 return (NULL);
73
74         TAILQ_FOREACH(port, &cc->port_list, node_link)
75                 if (port->param.port == portno)
76                         return (NULL);
77
78         port = CCZALLOC(sizeof(*port));
79         if (port == NULL)
80                 return (NULL);
81
82         port->uarg = uarg;
83         port->cc = cc;
84         port->admin = CCPORT_STOPPED;
85         LIST_INIT(&port->conn_list);
86         TAILQ_INIT(&port->addr_list);
87         port->param.port = portno;
88         port->param.pcr = 350053;
89         port->param.max_vpi_bits = 0;
90         port->param.max_vci_bits = 8;
91         port->param.max_svpc_vpi = 0;
92         port->param.max_svcc_vpi = 0;
93         port->param.min_svcc_vci = 32;
94         port->param.num_addrs = 0;
95         TAILQ_INIT(&port->cookies);
96
97         TAILQ_FOREACH(p1, &cc->port_list, node_link)
98                 if (p1->param.port > portno) {
99                         TAILQ_INSERT_BEFORE(p1, port, node_link);
100                         break;
101                 }
102         if (p1 == NULL)
103                 TAILQ_INSERT_TAIL(&cc->port_list, port, node_link);
104
105         return (port);
106 }
107
108 /*
109  * Destroy a port. This closes all connections and aborts all the users of
110  * these connections.
111  * This should be called only after work has returned so that no signals
112  * are pending.
113  */
114 void
115 cc_port_destroy(struct ccport *port, int shutdown)
116 {
117         struct ccaddr *addr;
118         struct ccreq *r;
119
120         TAILQ_REMOVE(&port->cc->port_list, port, node_link);
121
122         while ((r = TAILQ_FIRST(&port->cookies)) != NULL) {
123                 TAILQ_REMOVE(&port->cookies, r, link);
124                 CCFREE(r);
125         }
126
127         /*
128          * Abort all connections.
129          */
130         while (!LIST_EMPTY(&port->conn_list))
131                 cc_conn_abort(LIST_FIRST(&port->conn_list), shutdown);
132
133         /*
134          * Free addresses.
135          */
136         while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) {
137                 TAILQ_REMOVE(&port->addr_list, addr, port_link);
138                 CCFREE(addr);
139         }
140
141         CCFREE(port);
142 }
143
144 /*
145  * Management is given up on this node. Remove all addresses from the port.
146  */
147 void
148 cc_unmanage(struct ccdata *cc)
149 {
150         struct ccport *port;
151         struct ccaddr *addr;
152
153         TAILQ_FOREACH(port, &cc->port_list, node_link) {
154                 while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) {
155                         TAILQ_REMOVE(&port->addr_list, addr, port_link);
156                         CCFREE(addr);
157                 }
158         }
159 }
160
161 /*
162  * Compare two addresses
163  */
164 static __inline int
165 addr_eq(const struct uni_addr *a1, const struct uni_addr *a2)
166 {
167         return (a1->type == a2->type && a1->plan == a2->plan &&
168             a1->len == a2->len && memcmp(a1->addr, a2->addr, a1->len) == 0);
169 }
170
171
172 /*
173  * retrieve addresses
174  */
175 int
176 cc_get_addrs(struct ccdata *cc, u_int portno,
177     struct uni_addr **pa, u_int **ports, u_int *count)
178 {
179         struct ccport *port = NULL;
180         struct ccaddr *addr;
181         struct uni_addr *buf, *ptr;
182         u_int *pports;
183
184         /*
185          * If a port number is specified and the port does not exist,
186          * return an error.
187          */
188         if (portno != 0)
189                 if ((port = find_port(cc, portno)) == NULL)
190                         return (ENOENT);
191
192         /*
193          * Count the addresses
194          */
195         *count = 0;
196         if (portno != 0) {
197                 TAILQ_FOREACH(addr, &port->addr_list, port_link)
198                         (*count)++;
199         } else {
200                 TAILQ_FOREACH(port, &cc->port_list, node_link)
201                         TAILQ_FOREACH(addr, &port->addr_list, port_link)
202                                 (*count)++;
203         }
204
205         buf = CCMALLOC(*count * sizeof(struct uni_addr));
206         if (buf == NULL)
207                 return (ENOMEM);
208         ptr = buf;
209
210         *ports = CCMALLOC(*count * sizeof(u_int));
211         if (*ports == NULL) {
212                 CCFREE(buf);
213                 return (ENOMEM);
214         }
215         pports = *ports;
216
217         if (portno != 0) {
218                 TAILQ_FOREACH(addr, &port->addr_list, port_link) {
219                         *ptr++ = addr->addr;
220                         *pports++ = portno;
221                 }
222         } else {
223                 TAILQ_FOREACH(port, &cc->port_list, node_link)
224                         TAILQ_FOREACH(addr, &port->addr_list, port_link) {
225                                 *ptr++ = addr->addr;
226                                 *pports++ = port->param.port;
227                         }
228         }
229
230         *pa = buf;
231         return (0);
232 }
233
234 /*
235  * return port number
236  */
237 u_int
238 cc_port_no(struct ccport *port)
239 {
240         return (port->param.port);
241 }
242
243 /*
244  * Address unregisterd.
245  */
246 int
247 cc_addr_unregister(struct ccdata *cc, u_int portno, const struct uni_addr *arg)
248 {
249         struct ccport *port;
250         struct ccaddr *a;
251
252         if ((port = find_port(cc, portno)) == NULL)
253                 return (ENOENT);
254
255         /* Find the address */
256         TAILQ_FOREACH(a, &port->addr_list, port_link)
257                 if (addr_eq(arg, &a->addr)) {
258                         TAILQ_REMOVE(&port->addr_list, a, port_link);
259                         CCFREE(a);
260                         return (0);
261                 }
262
263         return (ENOENT);
264 }
265
266 /*
267  * Address registerd.
268  */
269 int
270 cc_addr_register(struct ccdata *cc, u_int portno, const struct uni_addr *arg)
271 {
272         struct ccport *port, *p1;
273         struct ccaddr *a;
274
275         if ((port = find_port(cc, portno)) == NULL)
276                 return (ENOENT);
277
278         /* maybe we know it already? */
279         TAILQ_FOREACH(p1, &port->cc->port_list, node_link)
280                 TAILQ_FOREACH(a, &p1->addr_list, port_link)
281                         if (addr_eq(arg, &a->addr))
282                                 return (EISCONN);
283
284         a = CCZALLOC(sizeof(*a));
285         if (a == NULL)
286                 return (ENOMEM);
287         a->addr = *arg;
288
289         TAILQ_INSERT_TAIL(&port->addr_list, a, port_link);
290
291         return (0);
292 }
293
294 /*
295  * Set/get port parameters.
296  */
297 int
298 cc_port_get_param(struct ccdata *cc, u_int portno,
299     struct atm_port_info *param)
300 {
301         struct ccport *port;
302
303         if ((port = find_port(cc, portno)) == NULL)
304                 return (ENOENT);
305
306         *param = port->param;
307         return (0);
308 }
309
310 /* XXX maybe allow only in stopped. */
311 int
312 cc_port_set_param(struct ccdata *cc, const struct atm_port_info *param)
313 {
314         struct ccport *port;
315         struct ccaddr *addr;
316
317         if ((port = find_port(cc, param->port)) == NULL)
318                 return (ENOENT);
319
320         port->param = *param;
321
322         port->param.num_addrs = 0;
323         TAILQ_FOREACH(addr, &port->addr_list, port_link)
324                 port->param.num_addrs++;
325
326         return (0);
327 }
328
329 /*
330  * get port list
331  */
332 int
333 cc_port_getlist(struct ccdata *cc, u_int *cnt, u_int **ports)
334 {
335         struct ccport *p;
336         u_int n;
337
338         n = 0;
339         TAILQ_FOREACH(p, &cc->port_list, node_link)
340                 n++;
341
342         *ports = CCMALLOC(n * sizeof(u_int));
343         if (*ports == NULL)
344                 return (ENOMEM);
345
346         n = 0;
347         TAILQ_FOREACH(p, &cc->port_list, node_link)
348                 (*ports)[n++] = p->param.port;
349         *cnt = n;
350
351         return (0);
352 }
353
354 /*
355  * START and STOP signalling
356  */
357 int
358 cc_port_start(struct ccdata *cc, u_int portno)
359 {
360         struct ccport *port;
361
362         if ((port = find_port(cc, portno)) == NULL)
363                 return (ENOENT);
364         if (port->admin != CCPORT_STOPPED)
365                 return (EISCONN);
366
367         cc->funcs->send_uni_glob(port, port->uarg,
368             UNIAPI_LINK_ESTABLISH_request, 0, NULL);
369         port->admin = CCPORT_RUNNING;
370
371         return (0);
372 }
373
374 int
375 cc_port_stop(struct ccdata *cc, u_int portno)
376 {
377         struct ccport *port;
378
379         if ((port = find_port(cc, portno)) == NULL)
380                 return (ENOENT);
381         if (port->admin != CCPORT_RUNNING)
382                 return (ENOTCONN);
383
384         port->admin = CCPORT_STOPPED;
385
386         /*
387          * Abort all connections.
388          */
389         while (!LIST_EMPTY(&port->conn_list))
390                 cc_conn_destroy(LIST_FIRST(&port->conn_list));
391
392         return (0);
393 }
394
395 /*
396  * is port running?
397  */
398 int
399 cc_port_isrunning(struct ccdata *cc, u_int portno, int *state)
400 {
401         struct ccport *port;
402
403         if ((port = find_port(cc, portno)) == NULL)
404                 return (ENOENT);
405         if (port->admin == CCPORT_RUNNING)
406                 *state = 1;
407         else
408                 *state = 0;
409         return (0);
410 }
411
412 /*
413  * Clear address and prefix information from the named port.
414  */
415 int
416 cc_port_clear(struct ccdata *cc, u_int portno)
417 {
418         struct ccaddr *addr;
419         struct ccport *port;
420
421         if ((port = find_port(cc, portno)) == NULL)
422                 return (ENOENT);
423
424         while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) {
425                 TAILQ_REMOVE(&port->addr_list, addr, port_link);
426                 CCFREE(addr);
427         }
428         return (0);
429 }
430
431 /*
432  * retrieve info on local ports
433  */
434 struct atm_port_list *
435 cc_get_local_port_info(struct ccdata *cc, u_int portno, size_t *lenp)
436 {
437         struct atm_port_list *list;
438         struct atm_port_info *pp;
439         struct uni_addr *aa;
440         struct ccaddr *addr;
441         struct ccport *port;
442         u_int nports, naddrs;
443
444         /*
445          * Count ports and addresses.
446          */
447         nports = 0;
448         naddrs = 0;
449         TAILQ_FOREACH(port, &cc->port_list, node_link) {
450                 if (portno == 0 || port->param.port == portno) {
451                         nports++;
452                         TAILQ_FOREACH(addr, &port->addr_list, port_link)
453                                 naddrs++;
454                 }
455         }
456
457         /*
458          * Size and allocate message
459          */
460         *lenp = sizeof(*list) + nports * sizeof(*pp) + naddrs * sizeof(*aa);
461
462         list = CCZALLOC(*lenp);
463         if (list == NULL)
464                 return (NULL);
465
466         /*
467          * Fill the message.
468          */
469         list->num_ports = nports;
470         list->num_addrs = naddrs;
471
472         pp = (void *)((u_char *)list + sizeof(*list));
473         aa = (void *)((u_char *)list + sizeof(*list) + nports * sizeof(*pp));
474
475         TAILQ_FOREACH(port, &cc->port_list, node_link) {
476                 if (portno == 0 || port->param.port == portno) {
477                         *pp = port->param;
478                         pp->num_addrs = 0;
479                         TAILQ_FOREACH(addr, &port->addr_list, port_link) {
480                                 *aa++ = addr->addr;
481                                 pp->num_addrs++;
482                         }
483                         pp++;
484                 }
485         }
486
487         return (list);
488 }
489
490 static struct ccreq *
491 find_cookie(struct ccport *port, u_int cookie)
492 {
493         struct ccreq *r;
494
495         TAILQ_FOREACH(r, &port->cookies, link)
496                 if (r->cookie == cookie)
497                         return (r);
498         return (NULL);
499 }
500
501 /*
502  * input a response from the UNI layer to CC
503  */
504 int
505 cc_uni_response(struct ccport *port, u_int cookie, u_int reason, u_int state)
506 {
507         struct ccconn *conn;
508         struct ccreq *req;
509
510         if (cookie == 0)
511                 return (EINVAL);
512
513         if (port->admin != CCPORT_RUNNING)
514                 return (ENOTCONN);
515
516         if ((req = find_cookie(port, cookie)) == NULL) {
517                 cc_port_log(port, "UNI response for unknown cookie %u", cookie);
518                 return (EINVAL);
519         }
520         conn = req->conn;
521
522         TAILQ_REMOVE(&port->cookies, req, link);
523         CCFREE(req);
524
525         if (reason == UNIAPI_OK)
526                 return (cc_conn_resp(conn, CONN_SIG_OK,
527                     cookie, reason, state));
528         else
529                 return (cc_conn_resp(conn, CONN_SIG_ERROR,
530                     cookie, reason, state));
531 }
532
533 static struct ccconn *
534 find_cref(const struct ccport *port, const struct uni_cref *cref)
535 {
536         struct ccconn *conn;
537
538         LIST_FOREACH(conn, &port->conn_list, port_link)
539                 if (conn->cref.cref == cref->cref &&
540                     conn->cref.flag == cref->flag)
541                         return (conn);
542         return (NULL);
543 }
544
545 /*
546  * Signal from UNI on this port
547  */
548 int
549 cc_uni_signal(struct ccport *port, u_int cookie, u_int sig, struct uni_msg *msg)
550 {
551         int error = 0;
552         size_t len, ilen = 0;
553         struct uni_cref *cref;
554         struct ccconn *conn;
555
556         if (port->admin != CCPORT_RUNNING) {
557                 error = ENOTCONN;
558                 goto out;
559         }
560         len = (msg != NULL) ? uni_msg_len(msg) : 0;
561
562         switch ((enum uni_sig)sig) {
563
564           case UNIAPI_ERROR:
565                 /* handled above */
566                 cc_port_log(port, "bad UNIAPI_ERROR cookie=%u", cookie);
567                 error = EINVAL;
568                 break;
569
570           case UNIAPI_CALL_CREATED:
571                 ilen = sizeof(struct uniapi_call_created);
572                 if (len != ilen)
573                         goto bad_len;
574
575                 if (cookie != 0) {
576                         /* outgoing call */
577                         struct ccreq *req;
578
579                         if ((req = find_cookie(port, cookie)) == NULL) {
580                                 cc_port_log(port, "bad cookie %u in CREATE",
581                                     cookie);
582                                 error = EINVAL;
583                                 goto out;
584                         }
585                         conn = req->conn;
586
587                 } else {
588                         if ((conn = cc_conn_create(port->cc)) == NULL) {
589                                 error = ENOMEM;
590                                 goto out;
591                         }
592                         cc_conn_ins_port(conn, port);
593                 }
594
595                 cc_conn_sig_msg_nodef(conn, CONN_SIG_CREATED, msg);
596                 msg = NULL;
597                 goto out;
598
599           case UNIAPI_CALL_DESTROYED:
600                 ilen = sizeof(struct uniapi_call_destroyed);
601                 if (len != ilen)
602                         goto bad_len;
603
604                 cref = &uni_msg_rptr(msg, struct uniapi_call_destroyed *)->cref;
605                 if ((conn = find_cref(port, cref)) == NULL)
606                         goto unk_call;
607
608                 error = cc_conn_sig(conn, CONN_SIG_DESTROYED, NULL);
609                 goto out;
610
611           case UNIAPI_LINK_ESTABLISH_confirm:
612                 goto out;
613
614           case UNIAPI_LINK_RELEASE_confirm:
615                 /* Ups. If we administratively up, restart the link */
616                 if (port->admin == CCPORT_RUNNING)
617                         port->cc->funcs->send_uni_glob(port, port->uarg,
618                             UNIAPI_LINK_ESTABLISH_request, 0, NULL);
619                 goto out;
620
621           case UNIAPI_PARTY_CREATED:
622                 ilen = sizeof(struct uniapi_party_created);
623                 if (len != ilen)
624                         goto bad_len;
625
626                 cref = &uni_msg_rptr(msg, struct uniapi_party_created *)->cref;
627
628                 if ((conn = find_cref(port, cref)) == NULL)
629                         goto unk_call;
630
631                 error = cc_conn_sig_msg_nodef(conn,
632                      CONN_SIG_PARTY_CREATED, msg);
633                 msg = NULL;
634                 goto out;
635
636           case UNIAPI_PARTY_DESTROYED:
637                 ilen = sizeof(struct uniapi_party_destroyed);
638                 if (len != ilen)
639                         goto bad_len;
640
641                 cref = &uni_msg_rptr(msg,
642                     struct uniapi_party_destroyed *)->cref;
643
644                 if ((conn = find_cref(port, cref)) == NULL)
645                         goto unk_call;
646
647                 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_DESTROYED, msg);
648                 msg = NULL;
649                 goto out;
650
651           case UNIAPI_DROP_PARTY_ACK_indication:        /* UNI -> API */
652                 ilen = sizeof(struct uniapi_drop_party_ack_indication);
653                 if (len != ilen)
654                         goto bad_len;
655
656                 cref = &uni_msg_rptr(msg,
657                     struct uniapi_drop_party_ack_indication *)->drop.hdr.cref;
658
659                 if ((conn = find_cref(port, cref)) == NULL)
660                         goto unk_call;
661
662                 error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_ACK_IND, msg);
663                 msg = NULL;
664                 goto out;
665
666           case UNIAPI_RESET_indication:                 /* UNI -> API */
667             {
668                 /*
669                  * XXX - do the right thing
670                  */
671                 struct uniapi_reset_indication *ind = uni_msg_rptr(msg,
672                     struct uniapi_reset_indication *);
673                 struct uniapi_reset_response *resp;
674                 struct uni_msg *u;
675                 
676                 /*
677                  * Construct message to UNI.
678                  */
679                 if ((u = uni_msg_alloc(sizeof(*resp))) == NULL)
680                         return (ENOMEM);
681
682                 resp = uni_msg_wptr(u, struct uniapi_reset_response *);
683                 memset(resp, 0, sizeof(*resp));
684                 u->b_wptr += sizeof(*resp);
685
686                 resp->restart = ind->restart;
687                 resp->connid = ind->connid;
688
689                 port->cc->funcs->send_uni_glob(port, port->uarg,
690                     UNIAPI_RESET_response, 0, u);
691
692                 goto out;
693             }
694
695           case UNIAPI_RELEASE_indication:               /* UNI -> API */
696                 ilen = sizeof(struct uniapi_release_indication);
697                 if (len != ilen)
698                         goto bad_len;
699
700                 cref = &uni_msg_rptr(msg, struct uniapi_release_indication *)
701                     ->release.hdr.cref;
702
703                 if ((conn = find_cref(port, cref)) == NULL)
704                         goto unk_call;
705
706                 error = cc_conn_sig_msg(conn, CONN_SIG_REL_IND, msg);
707                 msg = NULL;
708                 goto out;
709
710           case UNIAPI_RELEASE_confirm:                  /* UNI -> API */
711                 ilen = sizeof(struct uniapi_release_confirm);
712                 if (len != ilen)
713                         goto bad_len;
714
715                 cref = &uni_msg_rptr(msg, struct uniapi_release_confirm *)
716                     ->release.hdr.cref;
717
718                 if ((conn = find_cref(port, cref)) == NULL)
719                         goto unk_call;
720
721                 error = cc_conn_sig_msg(conn, CONN_SIG_REL_CONF, msg);
722                 msg = NULL;
723                 goto out;
724
725           case UNIAPI_SETUP_confirm:                    /* UNI -> API */
726                 ilen = sizeof(struct uniapi_setup_confirm);
727                 if (len != ilen)
728                         goto bad_len;
729
730                 cref = &uni_msg_rptr(msg, struct uniapi_setup_confirm *)
731                     ->connect.hdr.cref;
732
733                 if ((conn = find_cref(port, cref)) == NULL)
734                         goto unk_call;
735
736                 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_CONFIRM, msg);
737                 msg = NULL;
738                 goto out;
739
740
741           case UNIAPI_ALERTING_indication:              /* UNI -> API */
742                 ilen = sizeof(struct uniapi_alerting_indication);
743                 if (len != ilen)
744                         goto bad_len;
745
746                 cref = &uni_msg_rptr(msg, struct uniapi_alerting_indication *)
747                     ->alerting.hdr.cref;
748
749                 if ((conn = find_cref(port, cref)) == NULL)
750                         goto unk_call;
751
752                 error = cc_conn_sig_msg(conn, CONN_SIG_ALERTING_IND, msg);
753                 msg = NULL;
754                 goto out;
755
756
757           case UNIAPI_PROCEEDING_indication:            /* UNI -> API */
758                 ilen = sizeof(struct uniapi_proceeding_indication);
759                 if (len != ilen)
760                         goto bad_len;
761
762                 cref = &uni_msg_rptr(msg, struct uniapi_proceeding_indication *)
763                     ->call_proc.hdr.cref;
764
765                 if ((conn = find_cref(port, cref)) == NULL)
766                         goto unk_call;
767
768                 error = cc_conn_sig_msg(conn, CONN_SIG_PROC_IND, msg);
769                 msg = NULL;
770                 goto out;
771
772
773           case UNIAPI_SETUP_indication:                 /* UNI -> API */
774                 ilen = sizeof(struct uniapi_setup_indication);
775                 if (len != ilen)
776                         goto bad_len;
777
778                 cref = &uni_msg_rptr(msg, struct uniapi_setup_indication *)
779                     ->setup.hdr.cref;
780
781                 if ((conn = find_cref(port, cref)) == NULL)
782                         goto unk_call;
783
784                 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_IND, msg);
785                 msg = NULL;
786                 goto out;
787
788           case UNIAPI_SETUP_COMPLETE_indication:        /* UNI -> API */
789                 ilen = sizeof(struct uniapi_setup_complete_indication);
790                 if (len != ilen)
791                         goto bad_len;
792
793                 cref = &uni_msg_rptr(msg,
794                     struct uniapi_setup_complete_indication *)
795                     ->connect_ack.hdr.cref;
796
797                 if ((conn = find_cref(port, cref)) == NULL)
798                         goto unk_call;
799
800                 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_COMPL, msg);
801                 msg = NULL;
802                 goto out;
803
804           case UNIAPI_PARTY_ALERTING_indication:        /* UNI -> API */
805                 ilen = sizeof(struct uniapi_party_alerting_indication);
806                 if (len != ilen)
807                         goto bad_len;
808
809                 cref = &uni_msg_rptr(msg,
810                     struct uniapi_party_alerting_indication *)->alert.hdr.cref;
811
812                 if ((conn = find_cref(port, cref)) == NULL)
813                         goto unk_call;
814
815                 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ALERTING_IND, msg);
816                 msg = NULL;
817                 goto out;
818
819           case UNIAPI_ADD_PARTY_ACK_indication:         /* UNI -> API */
820                 ilen = sizeof(struct uniapi_add_party_ack_indication);
821                 if (len != ilen)
822                         goto bad_len;
823
824                 cref = &uni_msg_rptr(msg,
825                     struct uniapi_add_party_ack_indication *)->ack.hdr.cref;
826
827                 if ((conn = find_cref(port, cref)) == NULL)
828                         goto unk_call;
829
830                 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_ACK_IND, msg);
831                 msg = NULL;
832                 goto out;
833
834           case UNIAPI_ADD_PARTY_REJ_indication:         /* UNI -> API */
835                 ilen = sizeof(struct uniapi_add_party_rej_indication);
836                 if (len != ilen)
837                         goto bad_len;
838
839                 cref = &uni_msg_rptr(msg,
840                     struct uniapi_add_party_rej_indication *)->rej.hdr.cref;
841
842                 if ((conn = find_cref(port, cref)) == NULL)
843                         goto unk_call;
844
845                 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_REJ_IND, msg);
846                 msg = NULL;
847                 goto out;
848
849           case UNIAPI_DROP_PARTY_indication:            /* UNI -> API */
850                 ilen = sizeof(struct uniapi_drop_party_indication);
851                 if (len != ilen)
852                         goto bad_len;
853
854                 cref = &uni_msg_rptr(msg, struct uniapi_drop_party_indication *)
855                     ->drop.hdr.cref;
856
857                 if ((conn = find_cref(port, cref)) == NULL)
858                         goto unk_call;
859
860                 error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_IND, msg);
861                 msg = NULL;
862                 goto out;
863
864           case UNIAPI_RESET_confirm:                    /* UNI -> API */
865           case UNIAPI_RESET_ERROR_indication:           /* UNI -> API */
866           case UNIAPI_RESET_STATUS_indication:          /* UNI -> API */
867                 /* XXX */
868                 goto out;
869
870           case UNIAPI_NOTIFY_indication:                /* UNI -> API */
871           case UNIAPI_STATUS_indication:                /* UNI -> API */
872                 break;
873
874           case UNIAPI_ADD_PARTY_indication:             /* UNI -> API */
875                 /* not supported by the API */
876                 break;
877
878         /*
879          * All these are illegal in this direction
880          */
881           case UNIAPI_LINK_ESTABLISH_request:           /* API -> UNI */
882           case UNIAPI_LINK_RELEASE_request:             /* API -> UNI */
883           case UNIAPI_RESET_request:                    /* API -> UNI */
884           case UNIAPI_RESET_response:                   /* API -> UNI */
885           case UNIAPI_RESET_ERROR_response:             /* API -> UNI */
886           case UNIAPI_SETUP_request:                    /* API -> UNI */
887           case UNIAPI_SETUP_response:                   /* API -> UNI */
888           case UNIAPI_ALERTING_request:                 /* API -> UNI */
889           case UNIAPI_PROCEEDING_request:               /* API -> UNI */
890           case UNIAPI_RELEASE_request:                  /* API -> UNI */
891           case UNIAPI_RELEASE_response:                 /* API -> UNI */
892           case UNIAPI_NOTIFY_request:                   /* API -> UNI */
893           case UNIAPI_STATUS_ENQUIRY_request:           /* API -> UNI */
894           case UNIAPI_ADD_PARTY_request:                /* API -> UNI */
895           case UNIAPI_PARTY_ALERTING_request:           /* API -> UNI */
896           case UNIAPI_ADD_PARTY_ACK_request:            /* API -> UNI */
897           case UNIAPI_ADD_PARTY_REJ_request:            /* API -> UNI */
898           case UNIAPI_DROP_PARTY_request:               /* API -> UNI */
899           case UNIAPI_DROP_PARTY_ACK_request:           /* API -> UNI */
900           case UNIAPI_ABORT_CALL_request:               /* API -> UNI */
901           case UNIAPI_SETUP_COMPLETE_request:           /* API -> UNI */
902           case UNIAPI_MAXSIG:
903                 break;
904         }
905         cc_port_log(port, "bad signal %u", sig);
906         error = EINVAL;
907         goto out;
908
909   bad_len:
910         cc_port_log(port, "signal %u bad length: %zu, need %zu", len, ilen);
911         error = EINVAL;
912         goto out;
913
914   unk_call:
915         cc_port_log(port, "unknown call %u/%u", cref->cref, cref->flag);
916         error = EINVAL;
917
918   out:
919         if (msg != NULL)
920                 uni_msg_destroy(msg);
921         return (error);
922 }
923