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
Cache object: a3dca657135e2a7a7298dc512b342229
|