Deleted Added
full compact
uni_ie.c (133492) uni_ie.c (146539)
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 *
27 * Author: Hartmut Brandt <harti@freebsd.org>
28 *
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 *
27 * Author: Hartmut Brandt <harti@freebsd.org>
28 *
29 * $Begemot: libunimsg/netnatm/msg/uni_ie.c,v 1.15 2004/08/05 07:10:59 brandt Exp $
29 * $Begemot: libunimsg/netnatm/msg/uni_ie.c,v 1.16 2005/05/23 12:06:30 brandt_h Exp $
30 *
31 * Private definitions for the IE code file.
32 *
33 * This file includes the table generated automatically.
34 */
35
36#include <sys/types.h>
37#include <sys/param.h>
38
39#ifdef _KERNEL
40#include <sys/libkern.h>
41#else
42#include <string.h>
43#endif
44#include <netnatm/unimsg.h>
45#include <netnatm/msg/unistruct.h>
46#include <netnatm/msg/unimsglib.h>
47#include <netnatm/msg/uniprint.h>
48#include <netnatm/msg/priv.h>
49
50/*
51 * Define internal functions.
52 */
53#define DEF_IE_PRINT(Coding, IE) \
54 void uni_ie_print_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
55
56#define DEF_IE_CHECK(Coding, IE) \
57 int uni_ie_check_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
58
59#define DEF_IE_ENCODE(Coding, IE) \
60 int uni_ie_encode_##Coding##_##IE(struct uni_msg *msg, struct uni_ie_##IE *ie, struct unicx *cx)
61
62#define DEF_IE_DECODE(Coding, IE) \
63 int uni_ie_decode_##Coding##_##IE(struct uni_ie_##IE *ie, struct uni_msg *msg, u_int ielen, struct unicx *cx)
64
65/*
66 * This structure is used to define value->string mappings. MKT() is used
67 * to generate a table entry. EOT() to end the table.
68 */
69#define MKT(V,N) { #N, V }
70#define EOT() { NULL, 0 }
71
72/* library internal functions */
73static void uni_entry(const char *, struct unicx *);
74static int uni_print_iehdr(const char *, struct uni_iehdr *h, struct unicx *);
75static void uni_print_ieend(struct unicx *);
76static void uni_putc(int, struct unicx *);
77
78
79/*
80 * Encoding
81 */
82#define APP_BYTE(M, B) do { \
83 *(M)->b_wptr++ = (B); \
84 } while (0)
85#define APP_16BIT(M, B) do { \
86 u_int _v = (B); \
87 *(M)->b_wptr++ = _v >> 8; \
88 *(M)->b_wptr++ = _v; \
89 } while (0)
90#define APP_24BIT(M, B) do { \
91 u_int _v = (B); \
92 *(M)->b_wptr++ = _v >> 16; \
93 *(M)->b_wptr++ = _v >> 8; \
94 *(M)->b_wptr++ = _v; \
95 } while (0)
96#define APP_32BIT(M, B) do { \
97 u_int _v = (B); \
98 *(M)->b_wptr++ = _v >> 24; \
99 *(M)->b_wptr++ = _v >> 16; \
100 *(M)->b_wptr++ = _v >> 8; \
101 *(M)->b_wptr++ = _v; \
102 } while (0)
103#define APP_BUF(M, B, L) do { \
104 (void)memcpy((M)->b_wptr, (B), (L)); \
105 (M)->b_wptr += (L); \
106 } while (0)
107
108#define APP_SUB_BYTE(M, T, B) do { APP_BYTE(M, T); APP_BYTE(M, B); } while (0)
109#define APP_SUB_16BIT(M, T, B) do { APP_BYTE(M, T); APP_16BIT(M, B); } while (0)
110#define APP_SUB_24BIT(M, T, B) do { APP_BYTE(M, T); APP_24BIT(M, B); } while (0)
111#define APP_SUB_32BIT(M, T, B) do { APP_BYTE(M, T); APP_32BIT(M, B); } while (0)
112
113#define APP_OPT(M, F, P, T) do { \
114 if ((F) & (P)) \
115 APP_BYTE((M), (T)); \
116 } while (0)
117#define APP_OPT_BYTE(M, F, P, T, B) do { \
118 if ((F) & (P)) \
119 APP_SUB_BYTE((M), (T), (B)); \
120 } while (0)
121#define APP_OPT_16BIT(M, F, P, T, B) do { \
122 if ((F) & (P)) \
123 APP_SUB_16BIT((M), (T), (B)); \
124 } while (0)
125#define APP_OPT_24BIT(M, F, P, T, B) do { \
126 if ((F) & (P)) \
127 APP_SUB_24BIT((M), (T), (B)); \
128 } while (0)
129
130#define START_IE(TYPE,CODE,LEN) \
131 u_int ielen; \
132 \
133 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
134 return (-1); \
135 if (uni_encode_ie_hdr(msg, CODE, &ie->h, (LEN), cx)) \
136 return (0); \
137 \
138 ielen = msg->b_wptr - msg->b_rptr - 2;
139
140#define START_IE2(TYPE,CODE,LEN,REALCODE) \
141 u_int ielen; \
142 \
143 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
144 return (-1); \
145 if (uni_encode_ie_hdr(msg, REALCODE, &ie->h, (LEN), cx)) \
146 return (0); \
147 \
148 ielen = msg->b_wptr - msg->b_rptr - 2;
149
150#define SET_IE_LEN(M) do { \
151 (M)->b_buf[ielen + 0] = \
152 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 8; \
153 (M)->b_buf[ielen + 1] = \
154 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 0; \
155 } while (0)
156
157
158/***********************************************************************/
159/*
160 * Decoding
161 */
162#define IE_START(ERR) \
163 if (IE_ISPRESENT(*ie)) \
164 return (0); \
165 if (ielen == 0) { \
166 IE_SETEMPTY(*ie); \
167 return (0); \
168 }
169
170#define IE_END(IE) \
171 IE_SETPRESENT(*ie); \
172 if (uni_check_ie(UNI_IE_##IE, (union uni_ieall *)ie, cx) == 0) \
173 return (0); \
174 rej: \
175 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT; \
176 return (1);
177
178#define DEC_GETF3(ID, F, P) \
179 case UNI_##ID##_ID: \
180 if (ielen < 3) \
181 goto rej; \
182 ielen -= 3; \
183 if (!(P & UNI_##ID##_P)) { \
184 P |= UNI_##ID##_P; \
185 ie->F = *msg->b_rptr++ << 16; \
186 ie->F |= *msg->b_rptr++ << 8; \
187 ie->F |= *msg->b_rptr++; \
188 } else \
189 msg->b_rptr += 3; \
190 break;
191
192#define DEC_GETF1(ID, F, P) \
193 case UNI_##ID##_ID: \
194 if (ielen < 1) \
195 goto rej; \
196 ielen--; \
197 if (!(P & UNI_##ID##_P)) { \
198 P |= UNI_##ID##_P; \
199 ie->F = *msg->b_rptr++; \
200 } else \
201 msg->b_rptr++; \
202 break;
203
204
205#define PRINT_NPREFIX (sizeof(((struct unicx *)0)->prefix) / \
206 sizeof(((struct unicx *)0)->prefix[0]))
207
208/*
209 * This is rather here than in privmsg.c because we need the APP macros.
210 */
211int
212uni_encode_msg_hdr(struct uni_msg *msg, struct uni_msghdr *h,
213 enum uni_msgtype type, struct unicx *cx, int *mlen)
214{
215 u_char byte;
216
217 uni_msg_ensure(msg, 9);
218
219 APP_BYTE(msg, cx->pnni ? PNNI_PROTO : UNI_PROTO);
220 APP_BYTE(msg, 3);
221 if(h->cref.cref >= 1<<23)
222 return -1;
223 APP_24BIT(msg, h->cref.cref | (h->cref.flag ? 0x800000 : 0));
224 APP_BYTE(msg, type);
225
226 byte = 0x80;
227 if(h->act != UNI_MSGACT_DEFAULT)
228 byte |= 0x10 | (h->act & 3);
229 if(cx->pnni && h->pass)
230 byte |= 0x08;
231 APP_BYTE(msg, byte);
232
233 *mlen = msg->b_wptr - msg->b_rptr;
234 APP_16BIT(msg, 0);
235
236 return 0;
237}
238
239/*
240 * Initialize printing. This must be called by all printing routines
241 * that are exported to the user.
242 */
243void
244uni_print_init(char *buf, size_t bufsiz, struct unicx *cx)
245{
246 if (cx->dont_init)
247 return;
248
249 cx->indent = 0;
250 cx->nprefix = 0;
251 cx->doindent = 0;
252 if (cx->tabsiz == 0)
253 cx->tabsiz = 4;
254 cx->buf = buf;
255 cx->bufsiz = bufsiz;
256}
257
258/*
259 * Append a character to the buffer if there is still space
260 */
261static void
262uni_putc(int c, struct unicx *cx)
263{
264 if(cx->bufsiz > 1) {
265 *cx->buf++ = c;
266 cx->bufsiz--;
267 *cx->buf = '\0';
268 }
269}
270
271void
272uni_printf(struct unicx *cx, const char *fmt, ...)
273{
274 u_int n;
275 va_list ap;
276
277 if(cx->bufsiz > 1) {
278 va_start(ap, fmt);
279 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
280 va_end(ap);
281 if(n > 0) {
282 if(n < cx->bufsiz) {
283 cx->bufsiz -= n;
284 cx->buf += n;
285 } else {
286 cx->buf += cx->bufsiz - 1;
287 cx->bufsiz = 1;
288 }
289 }
290 *cx->buf = '\0';
291 }
292}
293
294/*
295 * Print mode:
296 * 0 - print all into one line, fully prefixed
297 * 1 - print on multiple lines, full prefixed, but equal level
298 * entries on one line
299 * 2 - like 2, but only partial prefixed
300 * 3 - like 1, but each entry onto a new line
301 * 4 - like 2 + 3
302 */
303
304/*
305 * If we are in multiline mode, end the current line and set the
306 * flag, that we need indentation. But prevent double new lines.
307 */
308void
309uni_print_eol(struct unicx *cx)
310{
311 if (cx->multiline) {
312 if (!cx->doindent) {
313 uni_putc('\n', cx);
314 cx->doindent = 1;
315 }
316 }
317}
318
319/*
320 * New entry. Do the prefixing, indentation and spacing.
321 */
322static void
323doprefix(struct unicx *cx, const char *s)
324{
325 u_int i;
326
327 if(cx->multiline == 0) {
328 uni_putc(' ', cx);
329 for(i = 0; i < cx->nprefix; i++)
330 if(cx->prefix[i])
331 uni_printf(cx, "%s.", cx->prefix[i]);
332 } else if(cx->multiline == 1) {
333 if(cx->doindent) {
334 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
335 cx->doindent = 0;
336 } else
337 uni_putc(' ', cx);
338 for(i = 0; i < cx->nprefix; i++)
339 if(cx->prefix[i])
340 uni_printf(cx, "%s.", cx->prefix[i]);
341 } else if(cx->multiline == 2) {
342 if(cx->doindent) {
343 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
344 cx->doindent = 0;
345 } else
346 uni_putc(' ', cx);
347 } else if(cx->multiline == 3) {
348 if(cx->doindent)
349 cx->doindent = 0;
350 else
351 uni_putc('\n', cx);
352 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
353 for(i = 0; i < cx->nprefix; i++)
354 if(cx->prefix[i])
355 uni_printf(cx, "%s.", cx->prefix[i]);
356 } else if(cx->multiline == 4) {
357 if(cx->doindent)
358 cx->doindent = 0;
359 else
360 uni_putc('\n', cx);
361 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
362 }
363 uni_printf(cx, "%s", s);
364}
365static void
366uni_entry(const char *s, struct unicx *cx)
367{
368 doprefix(cx, s);
369 uni_putc('=', cx);
370}
371void
372uni_print_flag(const char *s, struct unicx *cx)
373{
374 doprefix(cx, s);
375}
376
377
378/*
379 * Start a deeper level of indendation. If multiline is in effect,
380 * we end the current line.
381 */
382void
383uni_print_push_prefix(const char *prefix, struct unicx *cx)
384{
385 if (cx->nprefix < PRINT_NPREFIX)
386 cx->prefix[cx->nprefix++] = prefix;
387}
388void
389uni_print_pop_prefix(struct unicx *cx)
390{
391 if (cx->nprefix > 0)
392 cx->nprefix--;
393}
394
395void
396uni_print_tbl(const char *entry, u_int val, const struct uni_print_tbl *tbl,
397 struct unicx *cx)
398{
399 if (entry)
400 uni_entry(entry, cx);
401 while (tbl->name) {
402 if (tbl->val == val) {
403 uni_printf(cx, "%s", tbl->name);
404 return;
405 }
406 tbl++;
407 }
408 uni_printf(cx, "ERROR(0x%x)", val);
409}
410
411void
412uni_print_entry(struct unicx *cx, const char *e, const char *fmt, ...)
413{
414 u_int n;
415 va_list ap;
416
417 uni_entry(e, cx);
418
419 if (cx->bufsiz > 1) {
420 va_start(ap, fmt);
421 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
422 va_end(ap);
423 if (n > 0) {
424 if (n < cx->bufsiz) {
425 cx->bufsiz -= n;
426 cx->buf += n;
427 } else {
428 cx->buf += cx->bufsiz - 1;
429 cx->bufsiz = 1;
430 }
431 }
432 *cx->buf = '\0';
433 }
434}
435
436/**********************************************************************/
437/*
438 * Printing information elements.
439 */
440static int
441uni_print_iehdr(const char *name, struct uni_iehdr *h, struct unicx *cx)
442{
443 static const struct uni_print_tbl act_tab[] = {
444 MKT(UNI_IEACT_CLEAR, clear),
445 MKT(UNI_IEACT_IGNORE, ignore),
446 MKT(UNI_IEACT_REPORT, report),
447 MKT(UNI_IEACT_MSG_IGNORE, ignore-msg),
448 MKT(UNI_IEACT_MSG_REPORT, report-msg),
449 MKT(UNI_IEACT_DEFAULT, default),
450 EOT()
451 };
452 static const struct uni_print_tbl cod_tab[] = {
453 MKT(UNI_CODING_ITU, itut),
454 MKT(UNI_CODING_NET, atmf),
455 EOT()
456 };
457
458 uni_print_entry(cx, name, "(");
459 uni_print_tbl(NULL, h->act, act_tab, cx);
460 uni_putc(',', cx);
461 uni_print_tbl(NULL, h->coding, cod_tab, cx);
462 if(cx->pnni && h->pass)
463 uni_printf(cx, ",pass");
464 if(IE_ISEMPTY(*(struct uni_ie_aal *)h)) {
465 uni_printf(cx, ",empty)");
466 uni_print_eol(cx);
467 return 1;
468 }
469 if(IE_ISERROR(*(struct uni_ie_aal *)h)) {
470 uni_printf(cx, ",error)");
471 uni_print_eol(cx);
472 return 1;
473 }
474
475 uni_putc(')', cx);
476
477 uni_print_push_prefix(name, cx);
478 uni_print_eol(cx);
479 cx->indent++;
480
481 return 0;
482}
483
484static void
485uni_print_ieend(struct unicx *cx)
486{
487 uni_print_pop_prefix(cx);
488 uni_print_eol(cx);
489 cx->indent--;
490}
491
492void
493uni_print_ie_internal(enum uni_ietype code, const union uni_ieall *ie,
494 struct unicx *cx)
495{
496 const struct iedecl *iedecl;
497
498 if((iedecl = GET_IEDECL(code, ie->h.coding)) != NULL)
499 (*iedecl->print)(ie, cx);
500}
501
502void
503uni_print_ie(char *buf, size_t size, enum uni_ietype code,
504 const union uni_ieall *ie, struct unicx *cx)
505{
506 uni_print_init(buf, size, cx);
507 uni_print_ie_internal(code, ie, cx);
508}
509
510int
511uni_check_ie(enum uni_ietype code, union uni_ieall *ie, struct unicx *cx)
512{
513 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
514
515 if (iedecl != NULL)
516 return (iedecl->check(ie, cx));
517 else
518 return (-1);
519}
520
521/*
522 * Decode a information element header.
523 * Returns -1 if the message is too short.
524 * Strip the header from the message.
525 * The header is stripped, even if it is too short.
526 */
527int
528uni_decode_ie_hdr(enum uni_ietype *ietype, struct uni_iehdr *hdr,
529 struct uni_msg *msg, struct unicx *cx, u_int *ielen)
530{
531 u_int len;
532
533 *ietype = (enum uni_ietype)0;
534 *ielen = 0;
535 hdr->present = 0;
536 hdr->coding = UNI_CODING_ITU;
537 hdr->act = UNI_IEACT_DEFAULT;
538
539 if ((len = uni_msg_len(msg)) == 0)
540 return (-1);
541
542 *ietype = *msg->b_rptr++;
543
544 if (--len == 0)
545 return (-1);
546
547 hdr->coding = (*msg->b_rptr >> 5) & 3;
548 hdr->present = 0;
549
550 switch (*msg->b_rptr & 0x17) {
551
552 case 0x10: case 0x11: case 0x12:
553 case 0x15: case 0x16:
554 hdr->act = *msg->b_rptr & 0x7;
555 break;
556
557 case 0x00: case 0x01: case 0x02: case 0x03:
558 case 0x04: case 0x05: case 0x06: case 0x07:
559 hdr->act = UNI_IEACT_DEFAULT;
560 break;
561
562 default:
563 /* Q.2931 5.7.2 last sentence */
564 hdr->act = UNI_IEACT_REPORT;
565 break;
566 }
567 if (cx->pnni && (*msg->b_rptr & 0x08))
568 hdr->pass = 1;
569 else
570 hdr->pass = 0;
571 msg->b_rptr++;
572
573 if (--len == 0) {
574 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
575 return (-1);
576 }
577
578 if (len < 2) {
579 msg->b_rptr += len;
580 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
581 return (-1);
582 }
583
584 *ielen = *msg->b_rptr++ << 8;
585 *ielen |= *msg->b_rptr++;
586
587 return (0);
588}
589
590/*
591 * Decode the body of an information element.
592 */
593int
594uni_decode_ie_body(enum uni_ietype ietype, union uni_ieall *ie,
595 struct uni_msg *msg, u_int ielen, struct unicx *cx)
596{
597 const struct iedecl *iedecl;
598 u_char *end;
599 int ret;
600
601 if (ielen > uni_msg_len(msg)) {
602 /*
603 * Information element too long -> content error.
604 * Q.2931 5.6.8.2
605 */
606 msg->b_rptr = msg->b_wptr;
607 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
608 return (-1);
609 }
610
611 if ((iedecl = GET_IEDECL(ietype, ie->h.coding)) == NULL) {
612 /*
613 * entirly unknown IE.
614 * Q.2931 5.6.8.1
615 */
616 msg->b_rptr += ielen;
617 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
618 return (-1);
619 }
620
621 if (ielen > iedecl->maxlen) {
622 /*
623 * Information element too long -> content error.
624 * Q.2931 5.6.8.2
625 */
626 msg->b_rptr += iedecl->maxlen;
627 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
628 return (-1);
629 }
630
631 end = msg->b_rptr + ielen;
632 ret = (*iedecl->decode)(ie, msg, ielen, cx);
633 msg->b_rptr = end;
634
635 return (ret);
636}
637
638int
639uni_encode_ie(enum uni_ietype code, struct uni_msg *msg, union uni_ieall *ie,
640 struct unicx *cx)
641{
642 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
643
644 if (iedecl == NULL)
645 return (-1);
646 return (iedecl->encode(msg, ie, cx));
647}
648
649int
650uni_encode_ie_hdr(struct uni_msg *msg, enum uni_ietype type,
651 struct uni_iehdr *h, u_int len, struct unicx *cx)
652{
653 u_char byte;
654
655 uni_msg_ensure(msg, 4 + len);
656 *msg->b_wptr++ = type;
657
658 byte = 0x80 | (h->coding << 5);
659 if(h->act != UNI_IEACT_DEFAULT)
660 byte |= 0x10 | (h->act & 7);
661 if(cx->pnni)
662 byte |= h->pass << 3;
663 *msg->b_wptr++ = byte;
664
665 if(h->present & UNI_IE_EMPTY) {
666 *msg->b_wptr++ = 0;
667 *msg->b_wptr++ = 4;
668 return -1;
669 }
670 *msg->b_wptr++ = 0;
671 *msg->b_wptr++ = 0;
672
673 return 0;
674}
675
676/*
677 * Printing messages.
678 */
679static void
680uni_print_cref_internal(const struct uni_cref *cref, struct unicx *cx)
681{
682 uni_print_entry(cx, "cref", "%d.", cref->flag);
683 if (cref->cref == CREF_GLOBAL)
684 uni_printf(cx, "GLOBAL");
685 else if (cref->cref == CREF_DUMMY)
686 uni_printf(cx, "DUMMY");
687 else
688 uni_printf(cx, "%d", cref->cref);
689}
690void
691uni_print_cref(char *str, size_t len, const struct uni_cref *cref,
692 struct unicx *cx)
693{
694 uni_print_init(str, len, cx);
695 uni_print_cref_internal(cref, cx);
696}
697
698static void
699uni_print_msghdr_internal(const struct uni_msghdr *hdr, struct unicx *cx)
700{
701 static const struct uni_print_tbl tab[] = {
702 MKT(UNI_MSGACT_CLEAR, clear),
703 MKT(UNI_MSGACT_IGNORE, ignore),
704 MKT(UNI_MSGACT_REPORT, report),
705 MKT(UNI_MSGACT_DEFAULT, default),
706 EOT()
707 };
708
709 uni_print_cref_internal(&hdr->cref, cx);
710 uni_print_tbl("act", hdr->act, tab, cx);
711 if (cx->pnni)
712 uni_print_entry(cx, "pass", "%s", hdr->pass ? "yes" : "no");
713}
714
715void
716uni_print_msghdr(char *str, size_t len, const struct uni_msghdr *hdr,
717 struct unicx *cx)
718{
719 uni_print_init(str, len, cx);
720 uni_print_msghdr_internal(hdr, cx);
721}
722
723
724static void
725uni_print_internal(const struct uni_all *msg, struct unicx *cx)
726{
727 uni_entry("mtype", cx);
728 if(msg->mtype >= 256 || uni_msgtable[msg->mtype] == NULL) {
729 uni_printf(cx, "0x%02x(ERROR)", msg->mtype);
730 } else {
731 uni_printf(cx, "%s", uni_msgtable[msg->mtype]->name);
732 uni_print_msghdr_internal(&msg->u.hdr, cx);
733 cx->indent++;
734 uni_print_eol(cx);
735 (*uni_msgtable[msg->mtype]->print)(&msg->u, cx);
736 cx->indent--;
737 }
738
739 if(cx->multiline == 0)
740 uni_printf(cx, "\n");
741}
742
743void
744uni_print(char *buf, size_t size, const struct uni_all *all, struct unicx *cx)
745{
746 uni_print_init(buf, size, cx);
747 uni_print_internal(all, cx);
748}
749
750static void
751uni_print_msg_internal(u_int mtype, const union uni_msgall *msg,
752 struct unicx *cx)
753{
754
755 uni_entry("mtype", cx);
756 if (mtype >= 256 || uni_msgtable[mtype] == NULL) {
757 uni_printf(cx, "0x%02x(ERROR)", mtype);
758 } else {
759 uni_printf(cx, "%s", uni_msgtable[mtype]->name);
760 uni_print_msghdr_internal(&msg->hdr, cx);
761 cx->indent++;
762 uni_print_eol(cx);
763 (*uni_msgtable[mtype]->print)(msg, cx);
764 cx->indent--;
765 }
766
767 if(cx->multiline == 0)
768 uni_printf(cx, "\n");
769}
770
771void
772uni_print_msg(char *buf, size_t size, u_int mtype, const union uni_msgall *all,
773 struct unicx *cx)
774{
775 uni_print_init(buf, size, cx);
776 uni_print_msg_internal(mtype, all, cx);
777}
778
779void
780uni_print_cx(char *buf, size_t size, struct unicx *cx)
781{
782 static const char *acttab[] = {
783 "clr", /* 0x00 */
784 "ign", /* 0x01 */
785 "rep", /* 0x02 */
786 "x03", /* 0x03 */
787 "x04", /* 0x04 */
788 "mig", /* 0x05 */
789 "mrp", /* 0x06 */
790 "x07", /* 0x07 */
791 "def", /* 0x08 */
792 };
793
794 static const char *errtab[] = {
795 [UNI_IERR_UNK] = "unk", /* unknown IE */
796 [UNI_IERR_LEN] = "len", /* length error */
797 [UNI_IERR_BAD] = "bad", /* content error */
798 [UNI_IERR_ACC] = "acc", /* access element discarded */
799 [UNI_IERR_MIS] = "mis", /* missing IE */
800 };
801
802 u_int i;
803
804 uni_print_init(buf, size, cx);
805
806 uni_printf(cx, "q2932 %d\n", cx->q2932);
807 uni_printf(cx, "pnni %d\n", cx->pnni);
808 uni_printf(cx, "git_hard %d\n", cx->git_hard);
809 uni_printf(cx, "bearer_hard %d\n", cx->bearer_hard);
810 uni_printf(cx, "cause_hard %d\n", cx->cause_hard);
811
812 uni_printf(cx, "multiline %d\n", cx->multiline);
813 uni_printf(cx, "tabsiz %d\n", cx->tabsiz);
814
815 uni_printf(cx, "errcnt %d (", cx->errcnt);
816 for(i = 0; i < cx->errcnt; i++) {
817 uni_printf(cx, "%02x[%s,%s%s]", cx->err[i].ie,
818 errtab[cx->err[i].err], acttab[cx->err[i].act],
819 cx->err[i].man ? ",M" : "");
820 if(i != cx->errcnt - 1)
821 uni_putc(' ', cx);
822 }
823 uni_printf(cx, ")\n");
824}
825
826#include <netnatm/msg/uni_ietab.h>
827
828/*********************************************************************
829 *
830 * Cause
831 *
832 * References for this IE are:
833 *
834 * Q.2931 pp. 69 (just a pointer to Q.2610)
835 * Q.2610 (this is a small diff to Q.850)
836 * Q.850 !!
837 * UNI4.0 pp. 15
838 * PNNI1.0 p. 198
839 *
840 * ITU-T and NET coding for different values.
841 */
842static const struct causetab {
843 const char *str;
844 enum uni_diag diag;
845} itu_causes[128] = {
846
847#define D(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
848#define N(NAME,VAL,DIAG,STD,STR)
849
850UNI_DECLARE_CAUSE_VALUES
851
852#undef D
853#undef N
854
855}, net_causes[128] = {
856
857#define D(NAME,VAL,DIAG,STD,STR)
858#define N(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
859
860UNI_DECLARE_CAUSE_VALUES
861
862#undef D
863#undef N
864
865};
866
867enum uni_diag
868uni_diag(enum uni_cause cause, enum uni_coding code)
869{
870 if (cause >= 128)
871 return (UNI_DIAG_NONE);
872
873 if (code == UNI_CODING_NET)
874 if (net_causes[cause].str != NULL)
875 return (net_causes[cause].diag);
876 if (itu_causes[cause].str != NULL)
877 return (itu_causes[cause].diag);
878 return (UNI_DIAG_NONE);
879}
880
881/**********************************************************************/
882
883static void
884print_cause(struct unicx *cx, struct uni_ie_cause *ie,
885 const struct causetab *tab1, const struct causetab *tab2)
886{
887 static const struct uni_print_tbl loc_tbl[] = {
888 MKT(UNI_CAUSE_LOC_USER, user),
889 MKT(UNI_CAUSE_LOC_PRIVLOC, priv-net:loc-user),
890 MKT(UNI_CAUSE_LOC_PUBLOC, pub-net:loc-user),
891 MKT(UNI_CAUSE_LOC_TRANSIT, transit-net),
892 MKT(UNI_CAUSE_LOC_PUBREM, pub-net:rem-user),
893 MKT(UNI_CAUSE_LOC_PRIVREM, priv-net:rem-user),
894 MKT(UNI_CAUSE_LOC_INTERNAT, int-net),
895 MKT(UNI_CAUSE_LOC_BEYOND, beyond),
896 EOT()
897 };
898 static const struct uni_print_tbl pu_tbl[] = {
899 MKT(UNI_CAUSE_PU_PROVIDER, provider),
900 MKT(UNI_CAUSE_PU_USER, user),
901 EOT()
902 };
903 static const struct uni_print_tbl na_tbl[] = {
904 MKT(UNI_CAUSE_NA_NORMAL, normal),
905 MKT(UNI_CAUSE_NA_ABNORMAL, abnormal),
906 EOT()
907 };
908 static const struct uni_print_tbl cond_tbl[] = {
909 MKT(UNI_CAUSE_COND_UNKNOWN, unknown),
910 MKT(UNI_CAUSE_COND_PERM, permanent),
911 MKT(UNI_CAUSE_COND_TRANS, transient),
912 EOT()
913 };
914 static const struct uni_print_tbl rej_tbl[] = {
915 MKT(UNI_CAUSE_REASON_USER, user),
916 MKT(UNI_CAUSE_REASON_IEMISS, ie-missing),
917 MKT(UNI_CAUSE_REASON_IESUFF, ie-not-suff),
918 EOT()
919 };
920 char buf[100], *s;
921 u_int i;
922
923 if (uni_print_iehdr("cause", &ie->h, cx))
924 return;
925
926 if (ie->cause < 128 && tab1[ie->cause].str)
927 strcpy(buf, tab1[ie->cause].str);
928 else if (ie->cause < 128 && tab2 != NULL && tab2[ie->cause].str != NULL)
929 strcpy(buf, tab2[ie->cause].str);
930 else {
931 sprintf(buf, "UNKNOWN-%u", ie->cause);
932 }
933
934 for (s = buf; *s != '\0'; s++)
935 if (*s == ' ')
936 *s = '_';
937 uni_print_entry(cx, "cause", "%s", buf);
938
939 uni_print_tbl("loc", ie->loc, loc_tbl, cx);
940
941 if (ie->h.present & UNI_CAUSE_COND_P) {
942 uni_print_tbl("pu", ie->u.cond.pu, pu_tbl, cx);
943 uni_print_tbl("na", ie->u.cond.na, na_tbl, cx);
944 uni_print_tbl("condition", ie->u.cond.cond, cond_tbl, cx);
945 }
946 if (ie->h.present & UNI_CAUSE_REJ_P) {
947 uni_print_tbl("reject", ie->u.rej.reason, rej_tbl, cx);
948 }
949 if (ie->h.present & UNI_CAUSE_REJ_USER_P) {
950 uni_print_entry(cx, "user", "%u", ie->u.rej.user);
951 }
952 if (ie->h.present & UNI_CAUSE_REJ_IE_P) {
953 uni_print_entry(cx, "ie", "%u", ie->u.rej.ie);
954 }
955 if (ie->h.present & UNI_CAUSE_IE_P) {
956 uni_print_entry(cx, "ie", "(");
957 for (i = 0; i < ie->u.ie.len; i++) {
958 if (i)
959 uni_putc(',', cx);
960 uni_printf(cx, "0x%02x", ie->u.ie.ie[i]);
961 }
962 uni_putc(')', cx);
963 }
964 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
965 uni_print_entry(cx, "traffic", "(");
966 for (i = 0; i < ie->u.traffic.len; i++) {
967 if (i)
968 uni_putc(',', cx);
969 uni_printf(cx, "0x%02x", ie->u.traffic.traffic[i]);
970 }
971 uni_putc(')', cx);
972 }
973 if (ie->h.present & UNI_CAUSE_VPCI_P) {
974 uni_print_entry(cx, "vpci", "(%u,%u)", ie->u.vpci.vpci, ie->u.vpci.vci);
975 }
976 if (ie->h.present & UNI_CAUSE_MTYPE_P) {
977 uni_print_entry(cx, "mtype", "%u", ie->u.mtype);
978 }
979 if (ie->h.present & UNI_CAUSE_TIMER_P) {
980 for (i = 0, s = buf; i < 3; i++) {
981 if (ie->u.timer[i] < ' ') {
982 *s++ = '^';
983 *s++ = ie->u.timer[i] + '@';
984 } else if (ie->u.timer[i] <= '~')
985 *s++ = ie->u.timer[i];
986 else {
987 *s++ = '\\';
988 *s++ = ie->u.timer[i] / 0100 + '0';
989 *s++ = (ie->u.timer[i] % 0100) / 010 + '0';
990 *s++ = ie->u.timer[i] % 010 + '0';
991 }
992 }
993 *s++ = '\0';
994 uni_print_entry(cx, "timer", "\"%s\"", buf);
995 }
996 if (ie->h.present & UNI_CAUSE_TNS_P) {
997 uni_print_eol(cx);
998 uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx);
999 }
1000 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1001 uni_print_eol(cx);
1002 uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx);
1003 }
1004 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1005 uni_print_entry(cx, "attr", "(");
1006 for (i = 0; i < ie->u.attr.nattr; i++) {
1007 uni_printf(cx, "(%u", ie->u.attr.attr[i][0]);
1008 if (!(ie->u.attr.attr[i][0] & 0x80)) {
1009 uni_printf(cx, ",%u", ie->u.attr.attr[i][1]);
1010 if (!(ie->u.attr.attr[i][1] & 0x80))
1011 uni_printf(cx, ",%u",
1012 ie->u.attr.attr[i][2]);
1013 }
1014 uni_putc(')', cx);
1015 }
1016 }
1017
1018 uni_print_ieend(cx);
1019}
1020
1021DEF_IE_PRINT(itu, cause)
1022{
1023 print_cause(cx, ie, itu_causes, NULL);
1024}
1025DEF_IE_PRINT(net, cause)
1026{
1027 print_cause(cx, ie, net_causes, itu_causes);
1028}
1029
1030const char *
1031uni_ie_cause2str(enum uni_coding coding, u_int cause)
1032{
1033 if (cause < 128) {
1034 if (coding == UNI_CODING_ITU)
1035 return (itu_causes[cause].str);
1036 if (coding == UNI_CODING_NET) {
1037 if (net_causes[cause].str != NULL)
1038 return (net_causes[cause].str);
1039 return (itu_causes[cause].str);
1040 }
1041 }
1042 return (NULL);
1043}
1044
1045/**********************************************************************/
1046
1047static int
1048check_cause(struct uni_ie_cause *ie, struct unicx *cx,
1049 const struct causetab *tab1, const struct causetab *tab2)
1050{
1051 static const u_int mask =
1052 UNI_CAUSE_COND_P | UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P |
1053 UNI_CAUSE_REJ_IE_P | UNI_CAUSE_IE_P | UNI_CAUSE_TRAFFIC_P |
1054 UNI_CAUSE_VPCI_P | UNI_CAUSE_MTYPE_P | UNI_CAUSE_TIMER_P |
1055 UNI_CAUSE_TNS_P | UNI_CAUSE_NUMBER_P | UNI_CAUSE_ATTR_P |
1056 UNI_CAUSE_PARAM_P;
1057
1058 const struct causetab *ptr;
1059
1060 if (ie->cause >= 128)
1061 return (-1);
1062
1063 switch (ie->loc) {
1064 default:
1065 return (-1);
1066
1067 case UNI_CAUSE_LOC_USER:
1068 case UNI_CAUSE_LOC_PRIVLOC:
1069 case UNI_CAUSE_LOC_PUBLOC:
1070 case UNI_CAUSE_LOC_TRANSIT:
1071 case UNI_CAUSE_LOC_PUBREM:
1072 case UNI_CAUSE_LOC_PRIVREM:
1073 case UNI_CAUSE_LOC_INTERNAT:
1074 case UNI_CAUSE_LOC_BEYOND:
1075 break;
1076 }
1077
1078 if (tab1[ie->cause].str != NULL)
1079 ptr = &tab1[ie->cause];
1080 else if (tab2 != NULL && tab2[ie->cause].str != NULL)
1081 ptr = &tab2[ie->cause];
1082 else
1083 return (cx->cause_hard ? -1 : 0);
1084
1085 switch (ptr->diag) {
1086
1087 case UNI_DIAG_NONE:
1088 switch (ie->h.present & mask) {
1089 default:
1090 if (cx->cause_hard)
1091 return (-1);
1092 break;
1093
1094 case 0:
1095 break;
1096 }
1097 break;
1098
1099 case UNI_DIAG_COND:
1100 switch (ie->h.present & mask) {
1101 default:
1102 if (cx->cause_hard)
1103 return (-1);
1104 break;
1105
1106 case 0:
1107 case UNI_CAUSE_COND_P:
1108 break;
1109 }
1110 break;
1111
1112 case UNI_DIAG_REJ:
1113 switch (ie->h.present & mask) {
1114 default:
1115 if (cx->cause_hard)
1116 return (-1);
1117 break;
1118
1119 case 0:
1120 case UNI_CAUSE_REJ_P:
1121 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1122 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1123 break;
1124 }
1125 break;
1126
1127 case UNI_DIAG_CRATE:
1128 switch (ie->h.present & mask) {
1129 default:
1130 if (cx->cause_hard)
1131 return (-1);
1132 break;
1133
1134 case 0:
1135 case UNI_CAUSE_TRAFFIC_P:
1136 break;
1137 }
1138 break;
1139
1140 case UNI_DIAG_IE:
1141 switch (ie->h.present & mask) {
1142 default:
1143 if (cx->cause_hard)
1144 return (-1);
1145 break;
1146
1147 case 0:
1148 case UNI_CAUSE_IE_P:
1149 break;
1150 }
1151 break;
1152
1153 case UNI_DIAG_CHANID:
1154 switch (ie->h.present & mask) {
1155 default:
1156 if (cx->cause_hard)
1157 return (-1);
1158 break;
1159
1160 case 0:
1161 case UNI_CAUSE_VPCI_P:
1162 break;
1163 }
1164 break;
1165
1166 case UNI_DIAG_MTYPE:
1167 switch (ie->h.present & mask) {
1168 default:
1169 if (cx->cause_hard)
1170 return (-1);
1171 break;
1172
1173 case 0:
1174 case UNI_CAUSE_MTYPE_P:
1175 break;
1176 }
1177 break;
1178
1179 case UNI_DIAG_TIMER:
1180 switch (ie->h.present & mask) {
1181 default:
1182 if (cx->cause_hard)
1183 return (-1);
1184 break;
1185
1186 case 0:
1187 case UNI_CAUSE_TIMER_P:
1188 break;
1189 }
1190 break;
1191
1192 case UNI_DIAG_TNS:
1193 switch (ie->h.present & mask) {
1194 default:
1195 if (cx->cause_hard)
1196 return (-1);
1197 break;
1198
1199 case 0:
1200 case UNI_CAUSE_TNS_P:
1201 break;
1202 }
1203 break;
1204
1205 case UNI_DIAG_NUMBER:
1206 switch (ie->h.present & mask) {
1207 default:
1208 if (cx->cause_hard)
1209 return (-1);
1210 break;
1211
1212 case 0:
1213 case UNI_CAUSE_NUMBER_P:
1214 break;
1215 }
1216 break;
1217
1218 case UNI_DIAG_ATTR:
1219 switch (ie->h.present & mask) {
1220 default:
1221 if (cx->cause_hard)
1222 return (-1);
1223 break;
1224
1225 case 0:
1226 case UNI_CAUSE_ATTR_P:
1227 break;
1228 }
1229 break;
1230
1231 case UNI_DIAG_PARAM:
1232 switch (ie->h.present & mask) {
1233 default:
1234 if (cx->cause_hard)
1235 return (-1);
1236 break;
1237
1238 case 0:
1239 case UNI_CAUSE_PARAM_P:
1240 break;
1241 }
1242 break;
1243 }
1244
1245 if (ie->h.present & UNI_CAUSE_COND_P) {
1246 switch (ie->u.cond.pu) {
1247 default:
1248 return (-1);
1249
1250 case UNI_CAUSE_PU_PROVIDER:
1251 case UNI_CAUSE_PU_USER:
1252 break;
1253 }
1254 switch (ie->u.cond.na) {
1255 default:
1256 return (-1);
1257
1258 case UNI_CAUSE_NA_NORMAL:
1259 case UNI_CAUSE_NA_ABNORMAL:
1260 break;
1261 }
1262 switch (ie->u.cond.cond) {
1263 default:
1264 return (-1);
1265
1266 case UNI_CAUSE_COND_UNKNOWN:
1267 case UNI_CAUSE_COND_PERM:
1268 case UNI_CAUSE_COND_TRANS:
1269 break;
1270 }
1271 }
1272 if (ie->h.present & UNI_CAUSE_REJ_P) {
1273 switch (ie->u.rej.reason) {
1274 default:
1275 return (-1);
1276
1277 case UNI_CAUSE_REASON_USER:
1278 switch (ie->h.present & mask) {
1279 default:
1280 return (-1);
1281
1282 case UNI_CAUSE_REJ_P:
1283 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1284 break;
1285 }
1286 break;
1287
1288 case UNI_CAUSE_REASON_IEMISS:
1289 case UNI_CAUSE_REASON_IESUFF:
1290 switch (ie->h.present & mask) {
1291 default:
1292 return (-1);
1293
1294 case UNI_CAUSE_REJ_P:
1295 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1296 break;
1297 }
1298 break;
1299 }
1300 }
1301 if (ie->h.present & UNI_CAUSE_IE_P) {
1302 if (ie->u.ie.len == 0 || ie->u.ie.len > UNI_CAUSE_IE_N)
1303 return (-1);
1304 }
1305 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
1306 if (ie->u.traffic.len == 0 ||
1307 ie->u.traffic.len > UNI_CAUSE_TRAFFIC_N)
1308 return (-1);
1309 }
1310
1311 if (ie->h.present & UNI_CAUSE_TNS_P) {
1312 if (uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx))
1313 return (-1);
1314 }
1315 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1316 if(uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx))
1317 return (-1);
1318 }
1319 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1320 if(ie->u.attr.nattr > UNI_CAUSE_ATTR_N || ie->u.attr.nattr == 0)
1321 return (-1);
1322 }
1323 if (ie->h.present & UNI_CAUSE_PARAM_P) {
1324 cx = cx;
1325 }
1326
1327 return (0);
1328}
1329
1330DEF_IE_CHECK(itu, cause)
1331{
1332 return (check_cause(ie, cx, itu_causes, NULL));
1333}
1334DEF_IE_CHECK(net, cause)
1335{
1336 return (check_cause(ie, cx, net_causes, itu_causes));
1337}
1338/**********************************************************************/
1339
1340static int
1341encode_cause(struct uni_msg *msg, struct uni_ie_cause *ie, struct unicx *cx)
1342{
1343 u_int i;
1344
1345 START_IE(cause, UNI_IE_CAUSE, 30);
1346
1347 if (IE_ISERROR(*ie)) {
1348 APP_BYTE(msg, 0x00 | ie->loc);
1349 } else {
1350 APP_BYTE(msg, 0x80 | ie->loc);
1351 }
1352 APP_BYTE(msg, 0x80 | ie->cause);
1353
1354 if (ie->h.present & UNI_CAUSE_COND_P)
1355 APP_BYTE(msg, 0x80 | (ie->u.cond.pu << 3) |
1356 (ie->u.cond.na << 2) | ie->u.cond.cond);
1357
1358 else if (ie->h.present & UNI_CAUSE_REJ_P) {
1359 APP_BYTE(msg, 0x80 | (ie->u.rej.reason << 2) | ie->u.rej.cond);
1360 if (ie->h.present & UNI_CAUSE_REJ_USER_P)
1361 APP_BYTE(msg, ie->u.rej.user);
1362 else if (ie->h.present & UNI_CAUSE_REJ_IE_P)
1363 APP_BYTE(msg, ie->u.rej.ie);
1364
1365 } else if(ie->h.present & UNI_CAUSE_IE_P)
1366 APP_BUF(msg, ie->u.ie.ie, ie->u.ie.len);
1367
1368 else if (ie->h.present & UNI_CAUSE_TRAFFIC_P)
1369 APP_BUF(msg, ie->u.traffic.traffic, ie->u.traffic.len);
1370
1371 else if (ie->h.present & UNI_CAUSE_VPCI_P) {
1372 APP_BYTE(msg, (ie->u.vpci.vpci >> 8));
1373 APP_BYTE(msg, (ie->u.vpci.vpci >> 0));
1374 APP_BYTE(msg, (ie->u.vpci.vci >> 8));
1375 APP_BYTE(msg, (ie->u.vpci.vci >> 0));
1376
1377 } else if (ie->h.present & UNI_CAUSE_MTYPE_P)
1378 APP_BYTE(msg, ie->u.mtype);
1379
1380 else if (ie->h.present & UNI_CAUSE_TIMER_P) {
1381 APP_BYTE(msg, ie->u.timer[0]);
1382 APP_BYTE(msg, ie->u.timer[1]);
1383 APP_BYTE(msg, ie->u.timer[2]);
1384
1385 } else if (ie->h.present & UNI_CAUSE_TNS_P)
1386 uni_encode_ie(UNI_IE_TNS, msg,
1387 (union uni_ieall *)&ie->u.tns, cx);
1388
1389 else if (ie->h.present & UNI_CAUSE_NUMBER_P)
1390 uni_encode_ie(UNI_IE_CALLED, msg,
1391 (union uni_ieall *)&ie->u.number, cx);
1392
1393 else if (ie->h.present & UNI_CAUSE_ATTR_P) {
1394 for (i = 0; i < ie->u.attr.nattr; i++) {
1395 APP_BYTE(msg, ie->u.attr.attr[i][0]);
1396 if (!ie->u.attr.attr[i][0]) {
1397 APP_BYTE(msg, ie->u.attr.attr[i][1]);
1398 if (!ie->u.attr.attr[i][1])
1399 APP_BYTE(msg, ie->u.attr.attr[i][2]);
1400 }
1401 }
1402 } else if (ie->h.present & UNI_CAUSE_PARAM_P)
1403 APP_BYTE(msg, ie->u.param);
1404
1405 SET_IE_LEN(msg);
1406
1407 return (0);
1408}
1409
1410DEF_IE_ENCODE(itu, cause)
1411{
1412 return encode_cause(msg, ie, cx);
1413}
1414DEF_IE_ENCODE(net, cause)
1415{
1416 return encode_cause(msg, ie, cx);
1417}
1418
1419/**********************************************************************/
1420
1421static int
1422decode_cause(struct uni_ie_cause *ie, struct uni_msg *msg, u_int ielen,
1423 struct unicx *cx, const struct causetab *tab1, const struct causetab *tab2)
1424{
1425 u_char c;
1426 const struct causetab *ptr;
1427 enum uni_ietype ietype;
1428 u_int xielen;
1429
1430 IE_START(;);
1431
1432 if(ielen < 2 || ielen > 30)
1433 goto rej;
1434
1435 c = *msg->b_rptr++;
1436 ielen--;
1437 if(!(c & 0x80))
1438 goto rej;
1439 ie->loc = c & 0xf;
1440
1441 c = *msg->b_rptr++;
1442 ielen--;
1443 if(!(c & 0x80))
1444 goto rej;
1445 ie->cause = c & 0x7f;
1446
1447 if(tab1[ie->cause].str != NULL)
1448 ptr = &tab1[ie->cause];
1449 else if(tab2 != NULL && tab2[ie->cause].str != NULL)
1450 ptr = &tab2[ie->cause];
1451 else {
1452 ptr = NULL;
1453 ielen = 0; /* ignore diags */
1454 }
1455
1456 if(ielen) {
1457 switch(ptr->diag) {
1458
1459 case UNI_DIAG_NONE:
1460 break;
1461
1462 case UNI_DIAG_COND:
1463 if(ielen < 1)
1464 goto rej;
1465 c = *msg->b_rptr++;
1466 ielen--;
1467
1468 ie->h.present |= UNI_CAUSE_COND_P;
1469 ie->u.cond.pu = (c >> 3) & 1;
1470 ie->u.cond.na = (c >> 2) & 1;
1471 ie->u.cond.cond = c & 3;
1472
1473 if(!(c & 0x80))
1474 goto rej;
1475 break;
1476
1477 case UNI_DIAG_REJ:
1478 if(ielen < 1)
1479 goto rej;
1480 c = *msg->b_rptr++;
1481 ielen--;
1482
1483 ie->h.present |= UNI_CAUSE_REJ_P;
1484 ie->u.rej.reason = (c >> 2) & 0x1f;
1485 ie->u.rej.cond = c & 3;
1486
1487 if(!(c & 0x80))
1488 goto rej;
1489
1490 if(ielen > 0) {
1491 c = *msg->b_rptr++;
1492 ielen--;
1493
1494 switch(ie->u.rej.reason) {
1495
1496 case UNI_CAUSE_REASON_USER:
1497 ie->h.present |= UNI_CAUSE_REJ_USER_P;
1498 ie->u.rej.user = c;
1499 break;
1500
1501 case UNI_CAUSE_REASON_IEMISS:
1502 case UNI_CAUSE_REASON_IESUFF:
1503 ie->h.present |= UNI_CAUSE_REJ_IE_P;
1504 ie->u.rej.ie = c;
1505 break;
1506 }
1507 }
1508 break;
1509
1510 case UNI_DIAG_CRATE:
1511 ie->h.present |= UNI_CAUSE_TRAFFIC_P;
1512 while(ielen && ie->u.traffic.len < UNI_CAUSE_TRAFFIC_N) {
1513 ie->u.traffic.traffic[ie->u.traffic.len++] =
1514 *msg->b_rptr++;
1515 ielen--;
1516 }
1517 break;
1518
1519 case UNI_DIAG_IE:
1520 ie->h.present |= UNI_CAUSE_IE_P;
1521 while(ielen && ie->u.ie.len < UNI_CAUSE_IE_N) {
1522 ie->u.ie.ie[ie->u.ie.len++] = *msg->b_rptr++;
1523 ielen--;
1524 }
1525 break;
1526
1527 case UNI_DIAG_CHANID:
1528 if(ielen < 4)
1529 break;
1530 ie->h.present |= UNI_CAUSE_VPCI_P;
1531 ie->u.vpci.vpci = *msg->b_rptr++ << 8;
1532 ie->u.vpci.vpci |= *msg->b_rptr++;
1533 ie->u.vpci.vci = *msg->b_rptr++ << 8;
1534 ie->u.vpci.vci |= *msg->b_rptr++;
1535 ielen -= 4;
1536 break;
1537
1538 case UNI_DIAG_MTYPE:
1539 ie->h.present |= UNI_CAUSE_MTYPE_P;
1540 ie->u.mtype = *msg->b_rptr++;
1541 ielen--;
1542 break;
1543
1544 case UNI_DIAG_TIMER:
1545 if(ielen < 3)
1546 break;
1547 ie->h.present |= UNI_CAUSE_TIMER_P;
1548 ie->u.timer[0] = *msg->b_rptr++;
1549 ie->u.timer[1] = *msg->b_rptr++;
1550 ie->u.timer[2] = *msg->b_rptr++;
1551 ielen -= 3;
1552 break;
1553
1554 case UNI_DIAG_TNS:
1555 if(ielen < 4)
1556 break;
1557 if(uni_decode_ie_hdr(&ietype, &ie->u.tns.h, msg, cx, &xielen))
1558 break;
1559 if(ietype != UNI_IE_TNS)
1560 break;
1561 if(uni_decode_ie_body(ietype,
1562 (union uni_ieall *)&ie->u.tns, msg, xielen, cx))
1563 break;
1564 ie->h.present |= UNI_CAUSE_TNS_P;
1565 break;
1566
1567 case UNI_DIAG_NUMBER:
1568 if(ielen < 4)
1569 break;
1570 if(uni_decode_ie_hdr(&ietype, &ie->u.number.h, msg, cx, &xielen))
1571 break;
1572 if(ietype != UNI_IE_CALLED)
1573 break;
1574 if(uni_decode_ie_body(ietype,
1575 (union uni_ieall *)&ie->u.number, msg, xielen, cx))
1576 break;
1577 ie->h.present |= UNI_CAUSE_NUMBER_P;
1578 break;
1579
1580 case UNI_DIAG_ATTR:
1581 ie->h.present |= UNI_CAUSE_ATTR_P;
1582 while(ielen > 0 && ie->u.attr.nattr < UNI_CAUSE_ATTR_N) {
1583 c = *msg->b_rptr++;
1584 ie->u.attr.attr[ie->u.attr.nattr][0] = c;
1585 ielen--;
1586 if(ielen > 0 && !(c & 0x80)) {
1587 c = *msg->b_rptr++;
1588 ie->u.attr.attr[ie->u.attr.nattr][1] = c;
1589 ielen--;
1590 if(ielen > 0 && !(c & 0x80)) {
1591 c = *msg->b_rptr++;
1592 ie->u.attr.attr[ie->u.attr.nattr][2] = c;
1593 ielen--;
1594 }
1595 }
1596 }
1597 break;
1598
1599 case UNI_DIAG_PARAM:
1600 ie->h.present |= UNI_CAUSE_PARAM_P;
1601 ie->u.param = *msg->b_rptr++;
1602 ielen--;
1603 break;
1604 }
1605 }
1606
1607 IE_END(CAUSE);
1608}
1609
1610DEF_IE_DECODE(itu, cause)
1611{
1612 return decode_cause(ie, msg, ielen, cx, itu_causes, NULL);
1613}
1614DEF_IE_DECODE(net, cause)
1615{
1616 return decode_cause(ie, msg, ielen, cx, net_causes, itu_causes);
1617}
1618
1619/*********************************************************************
1620 *
1621 * Callstate
1622 *
1623 * References for this IE are:
1624 *
1625 * Q.2931 pp. 59...60
1626 * UNI4.0 pp. 14
1627 *
1628 * Only ITU-T coding allowed.
1629 */
1630DEF_IE_PRINT(itu, callstate)
1631{
1632 static const struct uni_print_tbl tbl[] = {
1633 MKT(UNI_CALLSTATE_U0, U0/N0/REST0),
1634 MKT(UNI_CALLSTATE_U1, U1/N1),
1635 MKT(UNI_CALLSTATE_U3, U3/N3),
1636 MKT(UNI_CALLSTATE_U4, U4/N4),
1637 MKT(UNI_CALLSTATE_U6, U6/N6),
1638 MKT(UNI_CALLSTATE_U7, U7/N7),
1639 MKT(UNI_CALLSTATE_U8, U8/N8),
1640 MKT(UNI_CALLSTATE_U9, U9/N9),
1641 MKT(UNI_CALLSTATE_U10, U10/N10),
1642 MKT(UNI_CALLSTATE_U11, U11/N11),
1643 MKT(UNI_CALLSTATE_U12, U12/N12),
1644 MKT(UNI_CALLSTATE_REST1,REST1),
1645 MKT(UNI_CALLSTATE_REST2,REST2),
1646 MKT(UNI_CALLSTATE_U13, U13/N13),
1647 MKT(UNI_CALLSTATE_U14, U14/N14),
1648 EOT()
1649 };
1650
1651 if(uni_print_iehdr("callstate", &ie->h, cx))
1652 return;
1653 uni_print_tbl("state", ie->state, tbl, cx);
1654 uni_print_ieend(cx);
1655}
1656
1657DEF_IE_CHECK(itu, callstate)
1658{
1659 cx = cx;
1660
1661 switch(ie->state) {
1662 default:
1663 return -1;
1664
1665 case UNI_CALLSTATE_U0:
1666 case UNI_CALLSTATE_U1:
1667 case UNI_CALLSTATE_U3:
1668 case UNI_CALLSTATE_U4:
1669 case UNI_CALLSTATE_U6:
1670 case UNI_CALLSTATE_U7:
1671 case UNI_CALLSTATE_U8:
1672 case UNI_CALLSTATE_U9:
1673 case UNI_CALLSTATE_U10:
1674 case UNI_CALLSTATE_U11:
1675 case UNI_CALLSTATE_U12:
1676 case UNI_CALLSTATE_REST1:
1677 case UNI_CALLSTATE_REST2:
1678 case UNI_CALLSTATE_U13:
1679 case UNI_CALLSTATE_U14:
1680 break;
1681 }
1682
1683 return 0;
1684}
1685
1686DEF_IE_ENCODE(itu, callstate)
1687{
1688 START_IE(callstate, UNI_IE_CALLSTATE, 1);
1689
1690 APP_BYTE(msg, ie->state);
1691
1692 SET_IE_LEN(msg);
1693 return 0;
1694}
1695
1696DEF_IE_DECODE(itu, callstate)
1697{
1698 IE_START(;);
1699
1700 if(ielen != 1)
1701 goto rej;
1702
1703 ie->state = *msg->b_rptr++ & 0x3f;
1704 ielen--;
1705
1706 IE_END(CALLSTATE);
1707}
1708
1709/*********************************************************************
1710 *
1711 * Facility Information.
1712 *
1713 * References for this IE are:
1714 *
1715 * Q.2932.1
1716 *
1717 * The standard allows only ROSE as protocol. We allow everything up to the
1718 * maximum size.
1719 *
1720 * Only ITU-T coding allowed.
1721 */
1722DEF_IE_PRINT(itu, facility)
1723{
1724 u_int i;
1725
1726 if(uni_print_iehdr("facility", &ie->h, cx))
1727 return;
1728
1729 if(ie->proto == UNI_FACILITY_ROSE)
1730 uni_print_entry(cx, "proto", "rose");
1731 else
1732 uni_print_entry(cx, "proto", "0x%02x", ie->proto);
1733
1734 uni_print_entry(cx, "len", "%u", ie->len);
1735 uni_print_entry(cx, "info", "(");
1736 for(i = 0; i < ie->len; i++)
1737 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->apdu[i]);
1738 uni_printf(cx, ")");
1739
1740 uni_print_ieend(cx);
1741}
1742
1743DEF_IE_CHECK(itu, facility)
1744{
1745 cx = cx;
1746
1747 if(ie->len > UNI_FACILITY_MAXAPDU)
1748 return -1;
1749
1750 return 0;
1751}
1752
1753DEF_IE_ENCODE(itu, facility)
1754{
1755 START_IE(facility, UNI_IE_FACILITY, 1 + ie->len);
1756
1757 APP_BYTE(msg, ie->proto | 0x80);
1758 APP_BUF(msg, ie->apdu, ie->len);
1759
1760 SET_IE_LEN(msg);
1761 return 0;
1762}
1763
1764DEF_IE_DECODE(itu, facility)
1765{
1766 u_char c;
1767
1768 IE_START(;);
1769
1770 if(ielen > UNI_FACILITY_MAXAPDU + 1 || ielen < 1)
1771 goto rej;
1772
1773 ie->proto = (c = *msg->b_rptr++) & 0x1f;
1774 ielen--;
1775 if((c & 0xe0) != 0x80)
1776 goto rej;
1777
1778 ie->len = ielen;
1779 ielen = 0;
1780 (void)memcpy(ie->apdu, msg->b_rptr, ie->len);
1781 msg->b_rptr += ie->len;
1782
1783 IE_END(FACILITY);
1784}
1785
1786/*********************************************************************
1787 *
1788 * Notification Indicator
1789 *
1790 * References for this IE are:
1791 *
1792 * Q.2931 p. 76
1793 * UNI4.0 p. 17
1794 *
1795 * Only ITU-T coding allowed.
1796 */
1797
1798DEF_IE_PRINT(itu, notify)
1799{
1800 u_int i;
1801
1802 if(uni_print_iehdr("notify", &ie->h, cx))
1803 return;
1804 uni_print_entry(cx, "len", "%u", ie->len);
1805 uni_print_entry(cx, "info", "(");
1806 for(i = 0; i < ie->len; i++)
1807 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->notify[i]);
1808 uni_printf(cx, ")");
1809 uni_print_ieend(cx);
1810}
1811
1812DEF_IE_CHECK(itu, notify)
1813{
1814 cx = cx;
1815
1816 if(ie->len > UNI_NOTIFY_MAXLEN)
1817 return -1;
1818
1819 return 0;
1820}
1821
1822DEF_IE_ENCODE(itu, notify)
1823{
1824 START_IE(notify, UNI_IE_NOTIFY, ie->len);
1825
1826 APP_BUF(msg, ie->notify, ie->len);
1827 if (IE_ISERROR(*ie)) {
1828 /* make it too long */
1829 u_int i = ie->len;
1830
1831 while (i < UNI_NOTIFY_MAXLEN + 1) {
1832 APP_BYTE(msg, 0x00);
1833 i++;
1834 }
1835 }
1836
1837 SET_IE_LEN(msg);
1838 return (0);
1839}
1840
1841DEF_IE_DECODE(itu, notify)
1842{
1843 IE_START(;);
1844
1845 if (ielen > UNI_NOTIFY_MAXLEN || ielen < 1)
1846 goto rej;
1847
1848 ie->len = ielen;
1849 ielen = 0;
1850 (void)memcpy(ie->notify, msg->b_rptr, ie->len);
1851 msg->b_rptr += ie->len;
1852
1853 IE_END(NOTIFY);
1854}
1855
1856/*********************************************************************
1857 *
1858 * End-to-end transit delay.
1859 *
1860 * References for this IE are:
1861 *
1862 * Q.2931 pp. 70...71
1863 * UNI4.0 pp. 69...70
1864 * PNNI1.0 pp. 198...200
1865 *
1866 * Not clear, whether the new indicator should be used with NET coding or
1867 * not.
1868 *
1869 * Only ITU-T coding allowed.
1870 */
1871
1872static void
1873print_eetd(struct uni_ie_eetd *ie, struct unicx *cx)
1874{
1875 if (uni_print_iehdr("eetd", &ie->h, cx))
1876 return;
1877
1878 if (ie->h.present & UNI_EETD_CUM_P)
1879 uni_print_entry(cx, "cum", "%u", ie->cumulative);
1880 if (ie->h.present & UNI_EETD_MAX_P) {
1881 if (ie->maximum == UNI_EETD_ANYMAX)
1882 uni_print_entry(cx, "max", "any");
1883 else
1884 uni_print_entry(cx, "max", "%u", ie->maximum);
1885 }
1886 if (ie->h.present & UNI_EETD_PCTD_P)
1887 uni_print_entry(cx, "pnni_cum", "%u", ie->pctd);
1888 if (ie->h.present & UNI_EETD_PMTD_P)
1889 uni_print_entry(cx, "pnni_max", "%u", ie->pmtd);
1890 if (ie->h.present & UNI_EETD_NET_P)
1891 uni_print_flag("netgen", cx);
1892
1893 uni_print_ieend(cx);
1894}
1895DEF_IE_PRINT(itu, eetd)
1896{
1897 print_eetd(ie, cx);
1898}
1899DEF_IE_PRINT(net, eetd)
1900{
1901 print_eetd(ie, cx);
1902}
1903
1904DEF_IE_CHECK(itu, eetd)
1905{
1906
1907 cx = cx;
1908
1909 if (!(ie->h.present & UNI_EETD_CUM_P))
1910 return (-1);
1911 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1912 return (-1);
1913 return (0);
1914}
1915
1916DEF_IE_CHECK(net, eetd)
1917{
1918
1919 if (!cx->pnni) {
1920 if (!(ie->h.present & UNI_EETD_CUM_P))
1921 return (-1);
1922 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1923 return (-1);
1924 } else {
1925 if (ie->h.present & UNI_EETD_MAX_P)
1926 return (-1);
1927 if ((ie->h.present & UNI_EETD_CUM_P) &&
1928 (ie->h.present & UNI_EETD_PCTD_P))
1929 return (-1);
1930 }
1931 return (0);
1932}
1933
1934DEF_IE_ENCODE(itu, eetd)
1935{
1936 START_IE(eetd, UNI_IE_EETD, 9);
1937
1938 if (ie->h.present & UNI_EETD_CUM_P) {
1939 APP_BYTE(msg, UNI_EETD_CTD_ID);
1940 APP_16BIT(msg, ie->cumulative);
1941 }
1942 if (ie->h.present & UNI_EETD_MAX_P) {
1943 APP_BYTE(msg, UNI_EETD_MTD_ID);
1944 APP_16BIT(msg, ie->maximum);
1945 }
1946 if (ie->h.present & UNI_EETD_PMTD_P) {
1947 APP_BYTE(msg, UNI_EETD_PMTD_ID);
1948 APP_24BIT(msg, ie->pmtd);
1949 }
1950 if (ie->h.present & UNI_EETD_PCTD_P) {
1951 APP_BYTE(msg, UNI_EETD_PCTD_ID);
1952 APP_24BIT(msg, ie->pctd);
1953 }
1954 if (ie->h.present & UNI_EETD_NET_P) {
1955 APP_BYTE(msg, UNI_EETD_NET_ID);
1956 }
1957
1958 SET_IE_LEN(msg);
1959 return (0);
1960}
1961
1962DEF_IE_ENCODE(net, eetd)
1963{
1964 return (uni_ie_encode_itu_eetd(msg, ie, cx));
1965}
1966
1967DEF_IE_DECODE(itu, eetd)
1968{
1969 IE_START(;);
1970
1971 while (ielen > 0) {
1972 switch (ielen--, *msg->b_rptr++) {
1973
1974 case UNI_EETD_CTD_ID:
1975 if (ielen < 2)
1976 goto rej;
1977 ie->h.present |= UNI_EETD_CUM_P;
1978 ie->cumulative = *msg->b_rptr++ << 8;
1979 ie->cumulative |= *msg->b_rptr++;
1980 ielen -= 2;
1981 break;
1982
1983 case UNI_EETD_MTD_ID:
1984 if (ielen < 2)
1985 goto rej;
1986 ie->h.present |= UNI_EETD_MAX_P;
1987 ie->maximum = *msg->b_rptr++ << 8;
1988 ie->maximum |= *msg->b_rptr++;
1989 ielen -= 2;
1990 break;
1991
1992 case UNI_EETD_PCTD_ID:
1993 if (ielen < 3)
1994 goto rej;
1995 ie->h.present |= UNI_EETD_PCTD_P;
1996 ie->pctd = *msg->b_rptr++ << 16;
1997 ie->pctd |= *msg->b_rptr++ << 8;
1998 ie->pctd |= *msg->b_rptr++;
1999 ielen -= 3;
2000 break;
2001
2002 case UNI_EETD_PMTD_ID:
2003 if (ielen < 3)
2004 goto rej;
2005 ie->h.present |= UNI_EETD_PMTD_P;
2006 ie->pmtd = *msg->b_rptr++ << 16;
2007 ie->pmtd |= *msg->b_rptr++ << 8;
2008 ie->pmtd |= *msg->b_rptr++;
2009 ielen -= 3;
2010 break;
2011
2012 case UNI_EETD_NET_ID:
2013 ie->h.present |= UNI_EETD_NET_P;
2014 break;
2015
2016 default:
2017 goto rej;
2018 }
2019 }
2020
2021 IE_END(EETD);
2022}
2023DEF_IE_DECODE(net, eetd)
2024{
2025 return (uni_ie_decode_itu_eetd(ie, msg, ielen, cx));
2026}
2027
2028/*********************************************************************
2029 *
2030 * Called address
2031 * Called subaddress
2032 * Calling address
2033 * Calling subaddress
2034 * Connected address
2035 * Connected subaddress
2036 *
2037 * References for this IE are:
2038 *
2039 * Q.2931 pp. 60...68
2040 * ...A4 pp. 27...36
2041 * UNI4.0 pp. 14...15
2042 * Q.2951 pp. 28...40
2043 *
2044 * It is assumed, that the coding of the addr arrays is ok.
2045 *
2046 * Only ITU-T coding allowed.
2047 */
2048
2049static const struct uni_print_tbl screen_tbl[] = {
2050 MKT(UNI_ADDR_SCREEN_NOT, no),
2051 MKT(UNI_ADDR_SCREEN_PASSED, passed),
2052 MKT(UNI_ADDR_SCREEN_FAILED, failed),
2053 MKT(UNI_ADDR_SCREEN_NET, network),
2054 EOT()
2055};
2056static const struct uni_print_tbl pres_tbl[] = {
2057 MKT(UNI_ADDR_PRES, allowed),
2058 MKT(UNI_ADDR_RESTRICT, restricted),
2059 MKT(UNI_ADDR_NONUMBER, no-number),
2060 EOT()
2061};
2062
2063
2064static void
2065print_addr(struct unicx *cx, struct uni_addr *addr)
2066{
2067 static const struct uni_print_tbl plan_tbl[] = {
2068 MKT(UNI_ADDR_UNKNOWN, unknown),
2069 MKT(UNI_ADDR_E164, E164),
2070 MKT(UNI_ADDR_ATME, ATME),
2071 MKT(UNI_ADDR_DATA, data),
2072 MKT(UNI_ADDR_PRIVATE, private),
2073 EOT()
2074 };
2075 static const struct uni_print_tbl type_tbl[] = {
2076 MKT(UNI_ADDR_UNKNOWN, unknown),
2077 MKT(UNI_ADDR_INTERNATIONAL, international),
2078 MKT(UNI_ADDR_NATIONAL, national),
2079 MKT(UNI_ADDR_NETWORK, network),
2080 MKT(UNI_ADDR_SUBSCR, subscriber),
2081 MKT(UNI_ADDR_ABBR, abbreviated),
2082 EOT()
2083 };
2084 u_int i;
2085
2086 uni_print_entry(cx, "addr", "(");
2087 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2088 uni_putc(',', cx);
2089 uni_print_tbl(NULL, addr->plan, plan_tbl, cx);
2090 uni_putc(',', cx);
2091 if(addr->plan == UNI_ADDR_E164) {
2092 uni_putc('"', cx);
2093 for(i = 0; i < addr->len; i++) {
2094 if(addr->addr[i] < ' ')
2095 uni_printf(cx, "^%c", addr->addr[i] + '@');
2096 else if(addr->addr[i] <= '~')
2097 uni_putc(addr->addr[i], cx);
2098 else
2099 uni_printf(cx, "\\%03o", addr->addr[i]);
2100 }
2101 uni_putc('"', cx);
2102
2103 } else if(addr->plan == UNI_ADDR_ATME) {
2104 for(i = 0; i < addr->len; i++)
2105 uni_printf(cx, "%02x", addr->addr[i]);
2106 }
2107 uni_putc(')', cx);
2108}
2109
2110static void
2111print_addrsub(struct unicx *cx, struct uni_subaddr *addr)
2112{
2113 static const struct uni_print_tbl type_tbl[] = {
2114 MKT(UNI_SUBADDR_NSAP, NSAP),
2115 MKT(UNI_SUBADDR_ATME, ATME),
2116 MKT(UNI_SUBADDR_USER, USER),
2117 EOT()
2118 };
2119 u_int i;
2120
2121 uni_print_entry(cx, "addr", "(");
2122 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2123 uni_putc(',', cx);
2124
2125 for(i = 0; i < addr->len; i++)
2126 uni_printf(cx, "%02x", addr->addr[i]);
2127
2128 uni_putc(')', cx);
2129}
2130
2131static int
2132check_addr(struct uni_addr *addr)
2133{
2134 u_int i;
2135
2136 switch(addr->plan) {
2137 default:
2138 return -1;
2139
2140 case UNI_ADDR_E164:
2141 if(addr->type != UNI_ADDR_INTERNATIONAL)
2142 return -1;
2143 if(addr->len > 15 || addr->len == 0)
2144 return -1;
2145 for(i = 0; i < addr->len; i++)
2146 if(addr->addr[i] == 0 || (addr->addr[i] & 0x80))
2147 return -1;
2148 break;
2149
2150 case UNI_ADDR_ATME:
2151 if(addr->type != UNI_ADDR_UNKNOWN)
2152 return -1;
2153 if(addr->len != 20)
2154 return -1;
2155 break;
2156 }
2157
2158 return 0;
2159}
2160
2161static int
2162check_subaddr(struct uni_subaddr *addr)
2163{
2164 switch(addr->type) {
2165 default:
2166 return -1;
2167
2168 case UNI_SUBADDR_NSAP:
2169 if(addr->len != 20)
2170 return -1;
2171 break;
2172
2173 case UNI_SUBADDR_ATME:
2174 if(addr->len > 20)
2175 return -1;
2176 break;
2177 }
2178 return 0;
2179}
2180
2181static int
2182check_screen(enum uni_addr_screen screen, enum uni_addr_pres pres)
2183{
2184 switch(pres) {
2185 default:
2186 return -1;
2187
2188 case UNI_ADDR_PRES:
2189 case UNI_ADDR_RESTRICT:
2190 case UNI_ADDR_NONUMBER:
2191 break;
2192 }
2193 switch(screen) {
2194 default:
2195 return -1;
2196
2197 case UNI_ADDR_SCREEN_NOT:
2198 case UNI_ADDR_SCREEN_PASSED:
2199 case UNI_ADDR_SCREEN_FAILED:
2200 case UNI_ADDR_SCREEN_NET:
2201 break;
2202 }
2203
2204 return 0;
2205}
2206
2207static void
2208encode_addr(struct uni_msg *msg, struct uni_addr *addr, u_int flag,
2209 enum uni_addr_screen screen, enum uni_addr_pres pres, int err)
2210{
2211 u_char ext = err ? 0x00 : 0x80;
2212
2213 if (flag) {
2214 APP_BYTE(msg, (addr->type << 4) | addr->plan);
2215 APP_BYTE(msg, ext | (pres << 5) | (screen));
2216 } else {
2217 APP_BYTE(msg, ext | (addr->type << 4) | addr->plan);
2218 }
2219 APP_BUF(msg, addr->addr, addr->len);
2220}
2221
2222static void
2223encode_subaddr(struct uni_msg *msg, struct uni_subaddr *addr)
2224{
2225 APP_BYTE(msg, 0x80|(addr->type<<4));
2226 APP_BUF(msg, addr->addr, addr->len);
2227}
2228
2229static int
2230decode_addr(struct uni_addr *addr, u_int ielen, struct uni_msg *msg, u_int plan)
2231{
2232 addr->plan = plan & 0xf;
2233 addr->type = (plan >> 4) & 0x7;
2234
2235 switch(addr->plan) {
2236
2237 case UNI_ADDR_E164:
2238 if(ielen > 15 || ielen == 0)
2239 return -1;
2240 addr->addr[ielen] = 0;
2241 break;
2242
2243 case UNI_ADDR_ATME:
2244 if(ielen != 20)
2245 return -1;
2246 break;
2247
2248 default:
2249 return -1;
2250 }
2251 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2252 addr->len = ielen;
2253 msg->b_rptr += ielen;
2254
2255 return 0;
2256}
2257
2258static int
2259decode_subaddr(struct uni_subaddr *addr, u_int ielen, struct uni_msg *msg,
2260 u_int type)
2261{
2262 switch(addr->type = (type >> 4) & 0x7) {
2263
2264 case UNI_SUBADDR_NSAP:
2265 if(ielen == 0 || ielen > 20)
2266 return -1;
2267 break;
2268
2269 case UNI_SUBADDR_ATME:
2270 if(ielen != 20)
2271 return -1;
2272 break;
2273
2274 default:
2275 return -1;
2276 }
2277 if(!(type & 0x80))
2278 return -1;
2279 if((type & 0x7) != 0)
2280 return -1;
2281
2282 addr->len = ielen;
2283 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2284 msg->b_rptr += ielen;
2285
2286 return 0;
2287}
2288
2289/**********************************************************************/
2290
2291DEF_IE_PRINT(itu, called)
2292{
2293 if (uni_print_iehdr("called", &ie->h, cx))
2294 return;
2295 print_addr(cx, &ie->addr);
2296 uni_print_ieend(cx);
2297}
2298
2299DEF_IE_CHECK(itu, called)
2300{
2301 cx = cx;
2302
2303 if (check_addr(&ie->addr))
2304 return (-1);
2305 return (0);
2306}
2307
2308DEF_IE_ENCODE(itu, called)
2309{
2310 START_IE(called, UNI_IE_CALLED, 21);
2311 encode_addr(msg, &ie->addr, 0, 0, 0, IE_ISERROR(*ie));
2312 SET_IE_LEN(msg);
2313 return (0);
2314}
2315
2316DEF_IE_DECODE(itu, called)
2317{
2318 u_char c;
2319 IE_START(;);
2320
2321 if (ielen > 21 || ielen < 1)
2322 goto rej;
2323
2324 c = *msg->b_rptr++;
2325 ielen--;
2326
2327 if (!(c & 0x80))
2328 goto rej;
2329
2330 if (decode_addr(&ie->addr, ielen, msg, c))
2331 goto rej;
2332
2333 IE_END(CALLED);
2334}
2335
2336/**********************************************************************/
2337
2338DEF_IE_PRINT(itu, calledsub)
2339{
2340 if(uni_print_iehdr("calledsub", &ie->h, cx))
2341 return;
2342 print_addrsub(cx, &ie->addr);
2343 uni_print_ieend(cx);
2344}
2345
2346DEF_IE_CHECK(itu, calledsub)
2347{
2348 cx = cx;
2349
2350 if(check_subaddr(&ie->addr))
2351 return -1;
2352 return 0;
2353}
2354
2355DEF_IE_ENCODE(itu, calledsub)
2356{
2357 START_IE(calledsub, UNI_IE_CALLEDSUB, 21);
2358 encode_subaddr(msg, &ie->addr);
2359 SET_IE_LEN(msg);
2360 return 0;
2361}
2362
2363DEF_IE_DECODE(itu, calledsub)
2364{
2365 u_char c;
2366
2367 IE_START(;);
2368
2369 if(ielen > 21)
2370 goto rej;
2371
2372 c = *msg->b_rptr++;
2373 ielen--;
2374
2375 if(decode_subaddr(&ie->addr, ielen, msg, c))
2376 goto rej;
2377
2378 IE_END(CALLEDSUB);
2379}
2380
2381/**********************************************************************/
2382
2383DEF_IE_PRINT(itu, calling)
2384{
2385 if(uni_print_iehdr("calling", &ie->h, cx))
2386 return;
2387 print_addr(cx, &ie->addr);
2388
2389 if(ie->h.present & UNI_CALLING_SCREEN_P) {
2390 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2391 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2392 }
2393
2394 uni_print_ieend(cx);
2395}
2396
2397DEF_IE_CHECK(itu, calling)
2398{
2399 cx = cx;
2400
2401 if(check_addr(&ie->addr))
2402 return -1;
2403
2404 if(ie->h.present & UNI_CALLING_SCREEN_P)
2405 if(check_screen(ie->screen, ie->pres))
2406 return -1;
2407 return 0;
2408}
2409
2410DEF_IE_ENCODE(itu, calling)
2411{
2412 START_IE(calling, UNI_IE_CALLING, 22);
2413 encode_addr(msg, &ie->addr, ie->h.present & UNI_CALLING_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2414 SET_IE_LEN(msg);
2415 return 0;
2416}
2417
2418DEF_IE_DECODE(itu, calling)
2419{
2420 u_char c, plan;
2421
2422 IE_START(;);
2423
2424 if(ielen > 22 || ielen < 1)
2425 goto rej;
2426
2427 plan = *msg->b_rptr++;
2428 ielen--;
2429
2430 if(!(plan & 0x80)) {
2431 if(ielen == 0)
2432 goto rej;
2433 ielen--;
2434 c = *msg->b_rptr++;
2435
2436 ie->h.present |= UNI_CALLING_SCREEN_P;
2437 ie->pres = (c >> 5) & 0x3;
2438 ie->screen = c & 0x3;
2439
2440 if(!(c & 0x80))
2441 goto rej;
2442 }
2443
2444 if(decode_addr(&ie->addr, ielen, msg, plan))
2445 goto rej;
2446
2447 IE_END(CALLING);
2448}
2449
2450/**********************************************************************/
2451
2452DEF_IE_PRINT(itu, callingsub)
2453{
2454 if(uni_print_iehdr("callingsub", &ie->h, cx))
2455 return;
2456 print_addrsub(cx, &ie->addr);
2457 uni_print_ieend(cx);
2458}
2459
2460DEF_IE_CHECK(itu, callingsub)
2461{
2462 cx = cx;
2463
2464 if(check_subaddr(&ie->addr))
2465 return -1;
2466 return 0;
2467}
2468
2469DEF_IE_ENCODE(itu, callingsub)
2470{
2471 START_IE(callingsub, UNI_IE_CALLINGSUB, 21);
2472 encode_subaddr(msg, &ie->addr);
2473 SET_IE_LEN(msg);
2474 return 0;
2475}
2476
2477DEF_IE_DECODE(itu, callingsub)
2478{
2479 u_char c;
2480
2481 IE_START(;);
2482
2483 if(ielen > 21)
2484 goto rej;
2485
2486 c = *msg->b_rptr++;
2487 ielen--;
2488
2489 if(decode_subaddr(&ie->addr, ielen, msg, c))
2490 goto rej;
2491
2492 IE_END(CALLINGSUB);
2493}
2494
2495/**********************************************************************/
2496
2497DEF_IE_PRINT(itu, conned)
2498{
2499 if(uni_print_iehdr("conned", &ie->h, cx))
2500 return;
2501 print_addr(cx, &ie->addr);
2502
2503 if(ie->h.present & UNI_CONNED_SCREEN_P) {
2504 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2505 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2506 }
2507
2508 uni_print_ieend(cx);
2509}
2510
2511DEF_IE_CHECK(itu, conned)
2512{
2513 cx = cx;
2514
2515 if(check_addr(&ie->addr))
2516 return -1;
2517
2518 if(ie->h.present & UNI_CONNED_SCREEN_P)
2519 if(check_screen(ie->screen, ie->pres))
2520 return -1;
2521 return 0;
2522}
2523
2524DEF_IE_ENCODE(itu, conned)
2525{
2526 START_IE(conned, UNI_IE_CONNED, 22);
2527 encode_addr(msg, &ie->addr, ie->h.present & UNI_CONNED_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2528 SET_IE_LEN(msg);
2529 return 0;
2530}
2531
2532DEF_IE_DECODE(itu, conned)
2533{
2534 u_char c, plan;
2535
2536 IE_START(;);
2537
2538 if(ielen > 22 || ielen < 1)
2539 goto rej;
2540
2541 plan = *msg->b_rptr++;
2542 ielen--;
2543
2544 if(!(plan & 0x80)) {
2545 if(ielen == 0)
2546 goto rej;
2547 ielen--;
2548 c = *msg->b_rptr++;
2549
2550 ie->h.present |= UNI_CONNED_SCREEN_P;
2551 ie->pres = (c >> 5) & 0x3;
2552 ie->screen = c & 0x3;
2553
2554 if(!(c & 0x80))
2555 goto rej;
2556 }
2557
2558 if(decode_addr(&ie->addr, ielen, msg, plan))
2559 goto rej;
2560
2561 IE_END(CONNED);
2562}
2563
2564/**********************************************************************/
2565
2566DEF_IE_PRINT(itu, connedsub)
2567{
2568 if(uni_print_iehdr("connedsub", &ie->h, cx))
2569 return;
2570 print_addrsub(cx, &ie->addr);
2571 uni_print_ieend(cx);
2572}
2573
2574DEF_IE_CHECK(itu, connedsub)
2575{
2576 cx = cx;
2577
2578 if(check_subaddr(&ie->addr))
2579 return -1;
2580 return 0;
2581}
2582
2583DEF_IE_ENCODE(itu, connedsub)
2584{
2585 START_IE(connedsub, UNI_IE_CONNEDSUB, 21);
2586 encode_subaddr(msg, &ie->addr);
2587 SET_IE_LEN(msg);
2588 return 0;
2589}
2590
2591DEF_IE_DECODE(itu, connedsub)
2592{
2593 u_char c;
2594
2595 IE_START(;);
2596
2597 if(ielen > 21)
2598 goto rej;
2599
2600 c = *msg->b_rptr++;
2601 ielen--;
2602
2603 if(decode_subaddr(&ie->addr, ielen, msg, c))
2604 goto rej;
2605
2606 IE_END(CONNEDSUB);
2607}
2608
2609/*********************************************************************
2610 *
2611 * Endpoint reference.
2612 *
2613 * References for this IE are:
2614 *
2615 * Q.2971 p. 14
2616 *
2617 * Only ITU-T coding allowed.
2618 */
2619
2620DEF_IE_PRINT(itu, epref)
2621{
2622 if(uni_print_iehdr("epref", &ie->h, cx))
2623 return;
2624 uni_print_entry(cx, "epref", "(%u,%u)", ie->flag, ie->epref);
2625 uni_print_ieend(cx);
2626}
2627
2628DEF_IE_CHECK(itu, epref)
2629{
2630 cx = cx;
2631
2632 if(ie->epref >= (2<<15))
2633 return -1;
2634
2635 return 0;
2636}
2637
2638DEF_IE_ENCODE(itu, epref)
2639{
2640 START_IE(epref, UNI_IE_EPREF, 3);
2641
2642 if (IE_ISERROR(*ie))
2643 APP_BYTE(msg, 0xff);
2644 else
2645 APP_BYTE(msg, 0);
2646 APP_BYTE(msg, (ie->flag << 7) | ((ie->epref >> 8) & 0x7f));
2647 APP_BYTE(msg, (ie->epref & 0xff));
2648
2649 SET_IE_LEN(msg);
2650 return 0;
2651}
2652
2653DEF_IE_DECODE(itu, epref)
2654{
2655 u_char c;
2656
2657 IE_START(;);
2658
2659 if(ielen != 3)
2660 goto rej;
2661 if(*msg->b_rptr++ != 0)
2662 goto rej;
2663
2664 c = *msg->b_rptr++;
2665 ie->flag = (c & 0x80) ? 1 : 0;
2666 ie->epref = (c & 0x7f) << 8;
2667 ie->epref |= *msg->b_rptr++;
2668
2669 IE_END(EPREF);
2670}
2671
2672/*********************************************************************
2673 *
2674 * Endpoint state.
2675 *
2676 * References for this IE are:
2677 *
2678 * Q.2971 pp. 14...15
2679 *
2680 * Only ITU-T coding allowed.
2681 */
2682
2683DEF_IE_PRINT(itu, epstate)
2684{
2685 static const struct uni_print_tbl tbl[] = {
2686 MKT(UNI_EPSTATE_NULL, null),
2687 MKT(UNI_EPSTATE_ADD_INIT, add-initiated),
2688 MKT(UNI_EPSTATE_ALERT_DLVD, alerting-delivered),
2689 MKT(UNI_EPSTATE_ADD_RCVD, add-received),
2690 MKT(UNI_EPSTATE_ALERT_RCVD, alerting-received),
2691 MKT(UNI_EPSTATE_ACTIVE, active),
2692 MKT(UNI_EPSTATE_DROP_INIT, drop-initiated),
2693 MKT(UNI_EPSTATE_DROP_RCVD, drop-received),
2694 EOT()
2695 };
2696
2697 if(uni_print_iehdr("epstate", &ie->h, cx))
2698 return;
2699 uni_print_tbl("state", ie->state, tbl, cx);
2700 uni_print_ieend(cx);
2701}
2702
2703DEF_IE_CHECK(itu, epstate)
2704{
2705 cx = cx;
2706
2707 switch(ie->state) {
2708 default:
2709 return -1;
2710
2711 case UNI_EPSTATE_NULL:
2712 case UNI_EPSTATE_ADD_INIT:
2713 case UNI_EPSTATE_ALERT_DLVD:
2714 case UNI_EPSTATE_ADD_RCVD:
2715 case UNI_EPSTATE_ALERT_RCVD:
2716 case UNI_EPSTATE_DROP_INIT:
2717 case UNI_EPSTATE_DROP_RCVD:
2718 case UNI_EPSTATE_ACTIVE:
2719 break;
2720 }
2721
2722 return 0;
2723}
2724
2725DEF_IE_ENCODE(itu, epstate)
2726{
2727 START_IE(epstate, UNI_IE_EPSTATE, 1);
2728
2729 APP_BYTE(msg, ie->state);
2730
2731 SET_IE_LEN(msg);
2732 return 0;
2733}
2734
2735DEF_IE_DECODE(itu, epstate)
2736{
2737 IE_START(;);
2738
2739 if(ielen != 1)
2740 goto rej;
2741
2742 ie->state = *msg->b_rptr++ & 0x3f;
2743
2744 IE_END(EPSTATE);
2745}
2746
2747/*********************************************************************
2748 *
2749 * ATM adaptation layer parameters
2750 *
2751 * References for this IE are:
2752 *
2753 * Q.2931 pp. 43...49
2754 * Q.2931 Amd 2
2755 * UNI4.0 p. 9
2756 *
2757 * UNI4.0 states, that AAL2 is not supported. However we keep it. No
2758 * parameters are associated with AAL2.
2759 *
2760 * Amd2 not checked. XXX
2761 *
2762 * Only ITU-T coding allowed.
2763 */
2764DEF_IE_PRINT(itu, aal)
2765{
2766 static const struct uni_print_tbl aal_tbl[] = {
2767 MKT(UNI_AAL_0, VOICE),
2768 MKT(UNI_AAL_1, 1),
2769 MKT(UNI_AAL_2, 2),
2770 MKT(UNI_AAL_4, 3/4),
2771 MKT(UNI_AAL_5, 5),
2772 MKT(UNI_AAL_USER, USER),
2773 EOT()
2774 };
2775 static const struct uni_print_tbl subtype_tbl[] = {
2776 MKT(UNI_AAL1_SUB_NULL, null),
2777 MKT(UNI_AAL1_SUB_VOICE, voice),
2778 MKT(UNI_AAL1_SUB_CIRCUIT, circuit),
2779 MKT(UNI_AAL1_SUB_HQAUDIO, hqaudio),
2780 MKT(UNI_AAL1_SUB_VIDEO, video),
2781 EOT()
2782 };
2783 static const struct uni_print_tbl cbr_rate_tbl[] = {
2784 MKT(UNI_AAL1_CBR_64, 64),
2785 MKT(UNI_AAL1_CBR_1544, 1544(DS1)),
2786 MKT(UNI_AAL1_CBR_6312, 6312(DS2)),
2787 MKT(UNI_AAL1_CBR_32064, 32064),
2788 MKT(UNI_AAL1_CBR_44736, 44736(DS3)),
2789 MKT(UNI_AAL1_CBR_97728, 97728),
2790 MKT(UNI_AAL1_CBR_2048, 2048(E1)),
2791 MKT(UNI_AAL1_CBR_8448, 8448(E2)),
2792 MKT(UNI_AAL1_CBR_34368, 34368(E3)),
2793 MKT(UNI_AAL1_CBR_139264, 139264),
2794 MKT(UNI_AAL1_CBR_N64, Nx64),
2795 MKT(UNI_AAL1_CBR_N8, Nx8),
2796 EOT()
2797 };
2798 static const struct uni_print_tbl screc_tbl[] = {
2799 MKT(UNI_AAL1_SCREC_NULL, null),
2800 MKT(UNI_AAL1_SCREC_SRTS, srts),
2801 MKT(UNI_AAL1_SCREC_ACLK, aclk),
2802 EOT()
2803 };
2804 static const struct uni_print_tbl ecm_tbl[] = {
2805 MKT(UNI_AAL1_ECM_NULL, null),
2806 MKT(UNI_AAL1_ECM_LOSS, loss),
2807 MKT(UNI_AAL1_ECM_DELAY, delay),
2808 EOT()
2809 };
2810 static const struct uni_print_tbl sscs_tbl[] = {
2811 MKT(UNI_AAL_SSCS_NULL, null),
2812 MKT(UNI_AAL_SSCS_SSCOPA, sscopa),
2813 MKT(UNI_AAL_SSCS_SSCOPU, sscopu),
2814 MKT(UNI_AAL_SSCS_FRAME, frame),
2815 EOT()
2816 };
2817
2818 if(uni_print_iehdr("aal", &ie->h, cx))
2819 return;
2820 uni_print_tbl("type", ie->type, aal_tbl, cx);
2821
2822 switch(ie->type) {
2823
2824 case UNI_AAL_0:
2825 uni_print_push_prefix("0", cx);
2826 cx->indent++;
2827 break;
2828
2829 case UNI_AAL_2:
2830 uni_print_push_prefix("2", cx);
2831 cx->indent++;
2832 break;
2833
2834 case UNI_AAL_1:
2835 uni_print_push_prefix("1", cx);
2836 cx->indent++;
2837 uni_print_tbl("subtype", ie->u.aal1.subtype, subtype_tbl, cx);
2838 uni_print_tbl("cbr_rate", ie->u.aal1.cbr_rate, cbr_rate_tbl, cx);
2839 if(ie->h.present & UNI_AAL1_MULT_P)
2840 uni_print_entry(cx, "mult", "%u", ie->u.aal1.mult);
2841 if(ie->h.present & UNI_AAL1_SCREC_P)
2842 uni_print_tbl("screc", ie->u.aal1.screc, screc_tbl, cx);
2843 if(ie->h.present & UNI_AAL1_ECM_P)
2844 uni_print_tbl("ecm", ie->u.aal1.ecm, ecm_tbl, cx);
2845 if(ie->h.present & UNI_AAL1_BSIZE_P)
2846 uni_print_entry(cx, "bsize", "%u", ie->u.aal1.bsize);
2847 if(ie->h.present & UNI_AAL1_PART_P)
2848 uni_print_entry(cx, "part", "%u", ie->u.aal1.part);
2849 break;
2850
2851 case UNI_AAL_4:
2852 uni_print_push_prefix("4", cx);
2853 cx->indent++;
2854 if(ie->h.present & UNI_AAL4_CPCS_P)
2855 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal4.fwd_cpcs,
2856 ie->u.aal4.bwd_cpcs);
2857 if(ie->h.present & UNI_AAL4_MID_P)
2858 uni_print_entry(cx, "mid", "(%u,%u)", ie->u.aal4.mid_low,
2859 ie->u.aal4.mid_high);
2860 if(ie->h.present & UNI_AAL4_SSCS_P)
2861 uni_print_tbl("sscs", ie->u.aal4.sscs, sscs_tbl, cx);
2862 break;
2863
2864 case UNI_AAL_5:
2865 uni_print_push_prefix("5", cx);
2866 cx->indent++;
2867 if(ie->h.present & UNI_AAL5_CPCS_P)
2868 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal5.fwd_cpcs,
2869 ie->u.aal5.bwd_cpcs);
2870 if(ie->h.present & UNI_AAL5_SSCS_P)
2871 uni_print_tbl("sscs", ie->u.aal5.sscs, sscs_tbl, cx);
2872 break;
2873
2874 case UNI_AAL_USER:
2875 uni_print_push_prefix("user", cx);
2876 cx->indent++;
2877 if(ie->u.aalu.len > 4) {
2878 uni_print_entry(cx, "info", "ERROR(len=%u)", ie->u.aalu.len);
2879 } else {
2880 u_int i;
2881
2882 uni_print_entry(cx, "info", "(");
2883 for(i = 0; i < ie->u.aalu.len; i++)
2884 uni_printf(cx, "%s%u", !i?"":",", ie->u.aalu.user[i]);
2885 uni_printf(cx, ")");
2886 }
2887 break;
2888 }
2889 cx->indent--;
2890 uni_print_pop_prefix(cx);
2891 uni_print_eol(cx);
2892
2893 uni_print_ieend(cx);
2894}
2895
2896DEF_IE_CHECK(itu, aal)
2897{
2898 cx = cx;
2899
2900 if(ie->type == UNI_AAL_0) {
2901 ;
2902 } else if(ie->type == UNI_AAL_1) {
2903 switch(ie->u.aal1.subtype) {
2904
2905 default:
2906 return -1;
2907
2908 case UNI_AAL1_SUB_NULL:
2909 case UNI_AAL1_SUB_VOICE:
2910 case UNI_AAL1_SUB_CIRCUIT:
2911 case UNI_AAL1_SUB_HQAUDIO:
2912 case UNI_AAL1_SUB_VIDEO:
2913 break;
2914 }
2915 switch(ie->u.aal1.cbr_rate) {
2916
2917 default:
2918 return -1;
2919
2920 case UNI_AAL1_CBR_64:
2921 case UNI_AAL1_CBR_1544:
2922 case UNI_AAL1_CBR_6312:
2923 case UNI_AAL1_CBR_32064:
2924 case UNI_AAL1_CBR_44736:
2925 case UNI_AAL1_CBR_97728:
2926 case UNI_AAL1_CBR_2048:
2927 case UNI_AAL1_CBR_8448:
2928 case UNI_AAL1_CBR_34368:
2929 case UNI_AAL1_CBR_139264:
2930 if((ie->h.present & UNI_AAL1_MULT_P))
2931 return -1;
2932 break;
2933
2934 case UNI_AAL1_CBR_N64:
2935 if(!(ie->h.present & UNI_AAL1_MULT_P))
2936 return -1;
2937 if(ie->u.aal1.mult < 2)
2938 return -1;
2939 break;
2940
2941 case UNI_AAL1_CBR_N8:
2942 if(!(ie->h.present & UNI_AAL1_MULT_P))
2943 return -1;
2944 if(ie->u.aal1.mult == 0 || ie->u.aal1.mult > 7)
2945 return -1;
2946 break;
2947 }
2948 if(ie->h.present & UNI_AAL1_SCREC_P) {
2949 switch(ie->u.aal1.screc) {
2950
2951 default:
2952 return -1;
2953
2954 case UNI_AAL1_SCREC_NULL:
2955 case UNI_AAL1_SCREC_SRTS:
2956 case UNI_AAL1_SCREC_ACLK:
2957 break;
2958 }
2959 }
2960 if(ie->h.present & UNI_AAL1_ECM_P) {
2961 switch(ie->u.aal1.ecm) {
2962
2963 default:
2964 return -1;
2965
2966 case UNI_AAL1_ECM_NULL:
2967 case UNI_AAL1_ECM_LOSS:
2968 case UNI_AAL1_ECM_DELAY:
2969 break;
2970 }
2971 }
2972 if(ie->h.present & UNI_AAL1_BSIZE_P) {
2973 if(ie->u.aal1.bsize == 0)
2974 return -1;
2975 }
2976 if(ie->h.present & UNI_AAL1_PART_P) {
2977 if(ie->u.aal1.part == 0 || ie->u.aal1.part > 47)
2978 return -1;
2979 }
2980
2981 } else if(ie->type == UNI_AAL_2) {
2982 ;
2983
2984 } else if(ie->type == UNI_AAL_4) {
2985 if(ie->h.present & UNI_AAL4_MID_P) {
2986 if(ie->u.aal4.mid_low >= 1024)
2987 return -1;
2988 if(ie->u.aal4.mid_high >= 1024)
2989 return -1;
2990 if(ie->u.aal4.mid_low > ie->u.aal4.mid_high)
2991 return -1;
2992 }
2993 if(ie->h.present & UNI_AAL4_SSCS_P) {
2994 switch(ie->u.aal4.sscs) {
2995
2996 default:
2997 return -1;
2998
2999 case UNI_AAL_SSCS_NULL:
3000 case UNI_AAL_SSCS_SSCOPA:
3001 case UNI_AAL_SSCS_SSCOPU:
3002 case UNI_AAL_SSCS_FRAME:
3003 break;
3004 }
3005 }
3006
3007 } else if(ie->type == UNI_AAL_5) {
3008 if(ie->h.present & UNI_AAL5_SSCS_P) {
3009 switch(ie->u.aal5.sscs) {
3010
3011 default:
3012 return -1;
3013
3014 case UNI_AAL_SSCS_NULL:
3015 case UNI_AAL_SSCS_SSCOPA:
3016 case UNI_AAL_SSCS_SSCOPU:
3017 case UNI_AAL_SSCS_FRAME:
3018 break;
3019 }
3020 }
3021
3022 } else if(ie->type == UNI_AAL_USER) {
3023 if(ie->u.aalu.len > 4)
3024 return -1;
3025
3026 } else
3027 return -1;
3028
3029 return 0;
3030}
3031
3032DEF_IE_ENCODE(itu, aal)
3033{
3034 START_IE(aal, UNI_IE_AAL, 16);
3035
3036 APP_BYTE(msg, ie->type);
3037 switch(ie->type) {
3038
3039 case UNI_AAL_0:
3040 break;
3041
3042 case UNI_AAL_1:
3043 APP_SUB_BYTE(msg,
3044 UNI_AAL_SUB_ID, ie->u.aal1.subtype);
3045 APP_SUB_BYTE(msg,
3046 UNI_AAL_CBR_ID, ie->u.aal1.cbr_rate);
3047 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_MULT_P,
3048 UNI_AAL_MULT_ID, ie->u.aal1.mult);
3049 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_SCREC_P,
3050 UNI_AAL_SCREC_ID, ie->u.aal1.screc);
3051 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_ECM_P,
3052 UNI_AAL_ECM_ID, ie->u.aal1.ecm);
3053 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_BSIZE_P,
3054 UNI_AAL_BSIZE_ID, ie->u.aal1.bsize);
3055 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_PART_P,
3056 UNI_AAL_PART_ID, ie->u.aal1.part);
3057 break;
3058
3059 case UNI_AAL_2:
3060 break;
3061
3062 case UNI_AAL_4:
3063 if(ie->h.present & UNI_AAL4_CPCS_P) {
3064 APP_SUB_16BIT(msg,
3065 UNI_AAL_FWDCPCS_ID, ie->u.aal4.fwd_cpcs);
3066 APP_SUB_16BIT(msg,
3067 UNI_AAL_BWDCPCS_ID, ie->u.aal4.bwd_cpcs);
3068 }
3069 if(ie->h.present & UNI_AAL4_MID_P) {
3070 APP_BYTE(msg, UNI_AAL_MID_ID);
3071 APP_16BIT(msg, ie->u.aal4.mid_low);
3072 APP_16BIT(msg, ie->u.aal4.mid_high);
3073 }
3074 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL4_SSCS_P,
3075 UNI_AAL_SSCS_ID, ie->u.aal4.sscs);
3076 break;
3077
3078 case UNI_AAL_5:
3079 if(ie->h.present & UNI_AAL5_CPCS_P) {
3080 APP_SUB_16BIT(msg,
3081 UNI_AAL_FWDCPCS_ID, ie->u.aal5.fwd_cpcs);
3082 APP_SUB_16BIT(msg,
3083 UNI_AAL_BWDCPCS_ID, ie->u.aal5.bwd_cpcs);
3084 }
3085 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL5_SSCS_P,
3086 UNI_AAL_SSCS_ID, ie->u.aal5.sscs);
3087 break;
3088
3089 case UNI_AAL_USER:
3090 APP_BUF(msg, ie->u.aalu.user, ie->u.aalu.len);
3091 break;
3092
3093 default:
3094 return -1;
3095 }
3096
3097 SET_IE_LEN(msg);
3098 return 0;
3099}
3100
3101/*
3102 * XXX What should we do with multiple subtype occurences? Ignore
3103 * or reject. Currently we reject.
3104 */
3105static int
3106decode_aal_1(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3107{
3108 int subtype_p, cbr_p;
3109
3110 subtype_p = cbr_p = 0;
3111
3112 while(ielen-- > 0) {
3113 switch(*msg->b_rptr++) {
3114
3115 case UNI_AAL_SUB_ID:
3116 if(ielen == 0 || subtype_p)
3117 return -1;
3118 ielen--;
3119 subtype_p = 1;
3120 ie->u.aal1.subtype = *msg->b_rptr++;
3121 break;
3122
3123 case UNI_AAL_CBR_ID:
3124 if(ielen == 0 || cbr_p)
3125 return -1;
3126 ielen--;
3127 cbr_p = 1;
3128 ie->u.aal1.cbr_rate = *msg->b_rptr++;
3129 break;
3130
3131 case UNI_AAL_MULT_ID:
3132 if(ielen < 2 || (ie->h.present & UNI_AAL1_MULT_P))
3133 return -1;
3134 ielen -= 2;
3135 ie->h.present |= UNI_AAL1_MULT_P;
3136 ie->u.aal1.mult = *msg->b_rptr++ << 8;
3137 ie->u.aal1.mult |= *msg->b_rptr++;
3138 break;
3139
3140 case UNI_AAL_SCREC_ID:
3141 if(ielen == 0 || (ie->h.present & UNI_AAL1_SCREC_P))
3142 return -1;
3143 ielen--;
3144 ie->h.present |= UNI_AAL1_SCREC_P;
3145 ie->u.aal1.screc = *msg->b_rptr++;
3146 break;
3147
3148 case UNI_AAL_ECM_ID:
3149 if(ielen == 0 || (ie->h.present & UNI_AAL1_ECM_P))
3150 return -1;
3151 ielen--;
3152 ie->h.present |= UNI_AAL1_ECM_P;
3153 ie->u.aal1.ecm = *msg->b_rptr++;
3154 break;
3155
3156 case UNI_AAL_BSIZE_ID:
3157 if(ielen < 2 || (ie->h.present & UNI_AAL1_BSIZE_P))
3158 return -1;
3159 ielen -= 2;
3160 ie->h.present |= UNI_AAL1_BSIZE_P;
3161 ie->u.aal1.bsize = *msg->b_rptr++ << 8;
3162 ie->u.aal1.bsize |= *msg->b_rptr++;
3163 break;
3164
3165 case UNI_AAL_PART_ID:
3166 if(ielen == 0 || (ie->h.present & UNI_AAL1_PART_P))
3167 return -1;
3168 ielen--;
3169 ie->h.present |= UNI_AAL1_PART_P;
3170 ie->u.aal1.part = *msg->b_rptr++;
3171 break;
3172
3173 default:
3174 return -1;
3175 }
3176 }
3177 if(!subtype_p || !cbr_p)
3178 return -1;
3179
3180 return 0;
3181}
3182
3183static int
3184decode_aal_4(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3185{
3186 int fcpcs_p, bcpcs_p;
3187
3188 fcpcs_p = bcpcs_p = 0;
3189
3190 while(ielen-- > 0) {
3191 switch(*msg->b_rptr++) {
3192
3193 case UNI_AAL_FWDCPCS_ID:
3194 if(ielen < 2 || fcpcs_p)
3195 return -1;
3196 ielen -= 2;
3197 fcpcs_p = 1;
3198 ie->u.aal4.fwd_cpcs = *msg->b_rptr++ << 8;
3199 ie->u.aal4.fwd_cpcs |= *msg->b_rptr++;
3200 break;
3201
3202 case UNI_AAL_BWDCPCS_ID:
3203 if(ielen < 2 || bcpcs_p)
3204 return -1;
3205 ielen -= 2;
3206 bcpcs_p = 1;
3207 ie->u.aal4.bwd_cpcs = *msg->b_rptr++ << 8;
3208 ie->u.aal4.bwd_cpcs |= *msg->b_rptr++;
3209 break;
3210
3211 case UNI_AAL_MID_ID:
3212 if(ielen < 4 || (ie->h.present & UNI_AAL4_MID_P))
3213 return -1;
3214 ielen -= 4;
3215 ie->h.present |= UNI_AAL4_MID_P;
3216 ie->u.aal4.mid_low = *msg->b_rptr++ << 8;
3217 ie->u.aal4.mid_low |= *msg->b_rptr++;
3218 ie->u.aal4.mid_high = *msg->b_rptr++ << 8;
3219 ie->u.aal4.mid_high |= *msg->b_rptr++;
3220 break;
3221
3222 case UNI_AAL_SSCS_ID:
3223 if(ielen == 0 || (ie->h.present & UNI_AAL4_SSCS_P))
3224 return -1;
3225 ielen--;
3226 ie->h.present |= UNI_AAL4_SSCS_P;
3227 ie->u.aal4.sscs = *msg->b_rptr++;
3228 break;
3229
3230 default:
3231 return -1;
3232 }
3233 }
3234
3235 if(fcpcs_p ^ bcpcs_p)
3236 return -1;
3237 if(fcpcs_p)
3238 ie->h.present |= UNI_AAL4_CPCS_P;
3239
3240 return 0;
3241}
3242
3243static int
3244decode_aal_5(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3245{
3246 int fcpcs_p, bcpcs_p;
3247
3248 fcpcs_p = bcpcs_p = 0;
3249
3250 while(ielen-- > 0) {
3251 switch(*msg->b_rptr++) {
3252
3253 case UNI_AAL_FWDCPCS_ID:
3254 if(ielen < 2 || fcpcs_p)
3255 return -1;
3256 ielen -= 2;
3257 fcpcs_p = 1;
3258 ie->u.aal5.fwd_cpcs = *msg->b_rptr++ << 8;
3259 ie->u.aal5.fwd_cpcs |= *msg->b_rptr++;
3260 break;
3261
3262 case UNI_AAL_BWDCPCS_ID:
3263 if(ielen < 2 || bcpcs_p)
3264 return -1;
3265 ielen -= 2;
3266 bcpcs_p = 1;
3267 ie->u.aal5.bwd_cpcs = *msg->b_rptr++ << 8;
3268 ie->u.aal5.bwd_cpcs |= *msg->b_rptr++;
3269 break;
3270
3271 case UNI_AAL_SSCS_ID:
3272 if(ielen == 0 || (ie->h.present & UNI_AAL5_SSCS_P))
3273 return -1;
3274 ielen--;
3275 ie->h.present |= UNI_AAL5_SSCS_P;
3276 ie->u.aal5.sscs = *msg->b_rptr++;
3277 break;
3278
3279 default:
3280 return -1;
3281 }
3282 }
3283
3284 if(fcpcs_p ^ bcpcs_p)
3285 return -1;
3286 if(fcpcs_p)
3287 ie->h.present |= UNI_AAL5_CPCS_P;
3288
3289 return 0;
3290}
3291
3292static int
3293decode_aal_user(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3294{
3295 if(ielen > 4)
3296 return -1;
3297
3298 ie->u.aalu.len = 0;
3299 while(ielen--)
3300 ie->u.aalu.user[ie->u.aalu.len++] = *msg->b_rptr++;
3301
3302 return 0;
3303}
3304
3305DEF_IE_DECODE(itu, aal)
3306{
3307 u_char c;
3308
3309 IE_START(DISC_ACC_ERR(AAL));
3310
3311 if(ielen < 1 || ielen > 21)
3312 goto rej;
3313
3314 c = *msg->b_rptr++;
3315 ielen--;
3316
3317 switch(c) {
3318
3319 case UNI_AAL_0:
3320 ie->type = c;
3321 break;
3322
3323 case UNI_AAL_1:
3324 ie->type = c;
3325 if(decode_aal_1(ie, msg, ielen))
3326 goto rej;
3327 break;
3328
3329 case UNI_AAL_2:
3330 ie->type = c;
3331 break;
3332
3333 case UNI_AAL_4:
3334 ie->type = c;
3335 if(decode_aal_4(ie, msg, ielen))
3336 goto rej;
3337 break;
3338
3339 case UNI_AAL_5:
3340 ie->type = c;
3341 if(decode_aal_5(ie, msg, ielen))
3342 goto rej;
3343 break;
3344
3345 case UNI_AAL_USER:
3346 ie->type = c;
3347 if(decode_aal_user(ie, msg, ielen))
3348 goto rej;
3349 break;
3350
3351 default:
3352 goto rej;
3353 }
3354
3355 IE_END(AAL);
3356}
3357
3358/*********************************************************************
3359 *
3360 * Traffic descriptor.
3361 * Alternate traffic descriptor.
3362 * Minimum traffic descriptor.
3363 *
3364 * References for this IE are:
3365 *
3366 * Q.2931 pp. 49...51
3367 * Q.2961
3368 * Q.2962
3369 * UNI4.0 pp. 9...10, 106...109
3370 *
3371 * The Q.s specify the coding. UNI4.0 adds frame discard and best-effort.
3372 * Appendix in UNI4.0 lists the allowed combinations.
3373 *
3374 * PCR0 PCR1 SCR/MBS0 SCR/MBS1 BE TAG FDISC ABR
3375 * 1 CBR.1 - Y - - - N Y/N -
3376 * 2 CBR.2 - Y - - - N Y/N - (*)
3377 * 3 CBR.3 Y Y - - - Y Y/N - (*)
3378 * 4 rt-VBR.1 - Y - Y - N Y/N -
3379 * 5 rt-VBR.2 - Y Y - - N Y/N -
3380 * 6 rt-VBR.3 - Y Y - - Y Y/N -
3381 * 7 rt-VBR.4 Y Y - - - Y/N Y/N - (*)
3382 * 8 rt-VBR.5 - Y - - - N Y/N - (*)
3383 * 9 rt-VBR.6 - Y - Y - N Y/N - (*)
3384 * 10 nrt-VBR.1 - Y - Y - N Y/N -
3385 * 11 nrt-VBR.2 - Y Y - - N Y/N -
3386 * 12 nrt-VBR.3 - Y Y - - Y Y/N -
3387 * 13 nrt-VBR.4 Y Y - - - Y/N Y/N - (*)
3388 * 14 nrt-VBR.5 - Y - - - N Y/N - (*)
3389 * 15 nrt-VBR.6 - Y - Y - N Y/N - (*)
3390 * 16 ABR - Y - - - N Y/N O (*)
3391 * 17 UBR.1 - Y - - Y N Y/N -
3392 * 18 UBR.2 - Y - - Y Y Y/N -
3393 *
3394 * Allow ITU-T and NET coding, because its not clear, whether the
3395 * new fields in UNI4.0 should be used with NET coding or not.
3396 * Does not allow for experimental codings yet.
3397 */
3398
3399static void
3400print_ie_traffic_common(struct unicx *cx, u_int present, struct uni_xtraffic *ie)
3401{
3402 uni_print_entry(cx, "fwd", "(");
3403 if(present & UNI_TRAFFIC_FPCR0_P)
3404 uni_printf(cx, "%u", ie->fpcr0);
3405 uni_putc(',', cx);
3406 if(present & UNI_TRAFFIC_FPCR1_P)
3407 uni_printf(cx, "%u", ie->fpcr1);
3408 uni_putc(',', cx);
3409 if(present & UNI_TRAFFIC_FSCR0_P)
3410 uni_printf(cx, "%u", ie->fscr0);
3411 uni_putc(',', cx);
3412 if(present & UNI_TRAFFIC_FSCR1_P)
3413 uni_printf(cx, "%u", ie->fscr1);
3414 uni_putc(',', cx);
3415 if(present & UNI_TRAFFIC_FMBS0_P)
3416 uni_printf(cx, "%u", ie->fmbs0);
3417 uni_putc(',', cx);
3418 if(present & UNI_TRAFFIC_FMBS1_P)
3419 uni_printf(cx, "%u", ie->fmbs1);
3420 uni_putc(',', cx);
3421 if(present & UNI_TRAFFIC_FABR1_P)
3422 uni_printf(cx, "%u", ie->fabr1);
3423 uni_printf(cx, ")");
3424
3425 uni_print_entry(cx, "bwd", "(");
3426 if(present & UNI_TRAFFIC_BPCR0_P)
3427 uni_printf(cx, "%u", ie->bpcr0);
3428 uni_putc(',', cx);
3429 if(present & UNI_TRAFFIC_BPCR1_P)
3430 uni_printf(cx, "%u", ie->bpcr1);
3431 uni_putc(',', cx);
3432 if(present & UNI_TRAFFIC_BSCR0_P)
3433 uni_printf(cx, "%u", ie->bscr0);
3434 uni_putc(',', cx);
3435 if(present & UNI_TRAFFIC_BSCR1_P)
3436 uni_printf(cx, "%u", ie->bscr1);
3437 uni_putc(',', cx);
3438 if(present & UNI_TRAFFIC_BMBS0_P)
3439 uni_printf(cx, "%u", ie->bmbs0);
3440 uni_putc(',', cx);
3441 if(present & UNI_TRAFFIC_BMBS1_P)
3442 uni_printf(cx, "%u", ie->bmbs1);
3443 uni_putc(',', cx);
3444 if(present & UNI_TRAFFIC_BABR1_P)
3445 uni_printf(cx, "%u", ie->babr1);
3446 uni_printf(cx, ")");
3447
3448 if(present & UNI_TRAFFIC_BEST_P)
3449 uni_print_flag("best_effort", cx);
3450 if(present & UNI_TRAFFIC_MOPT_P) {
3451 uni_print_entry(cx, "tag", "(");
3452 if(ie->ftag)
3453 uni_printf(cx, "fwd");
3454 uni_putc(',', cx);
3455 if(ie->btag)
3456 uni_printf(cx, "bwd");
3457 uni_putc(')', cx);
3458
3459 uni_print_entry(cx, "disc", "(");
3460 if(ie->fdisc)
3461 uni_printf(cx, "fwd");
3462 uni_putc(',', cx);
3463 if(ie->bdisc)
3464 uni_printf(cx, "bwd");
3465 uni_putc(')', cx);
3466 }
3467}
3468
3469struct tallow {
3470 u_int mask;
3471 int mopt_flag;
3472 u_char mopt_mask, mopt_val;
3473};
3474
3475static int
3476check_traffic(u_int mask, u_int mopt, struct tallow *a)
3477{
3478 if(mask != a->mask)
3479 return 0;
3480
3481 if(a->mopt_flag == 0) {
3482 /* not allowed */
3483 if(mopt == 0xffff)
3484 return 1;
3485 return 0;
3486 }
3487
3488 if(a->mopt_flag < 0) {
3489 /* optional */
3490 if(mopt == 0xffff)
3491 return 1;
3492 if((mopt & a->mopt_mask) == a->mopt_val)
3493 return 1;
3494 return 0;
3495 }
3496
3497 /* required */
3498 if(mopt == 0xffff)
3499 return 0;
3500 if((mopt & a->mopt_mask) == a->mopt_val)
3501 return 1;
3502 return 0;
3503}
3504
3505static int
3506check_ie_traffic_common(struct uni_xtraffic *ie, u_int present,
3507 struct unicx *cx __unused)
3508{
3509 static u_int fmask =
3510 UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
3511 UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P |
3512 UNI_TRAFFIC_FMBS0_P | UNI_TRAFFIC_FMBS1_P |
3513 UNI_TRAFFIC_FABR1_P;
3514 static u_int bmask =
3515 UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
3516 UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P |
3517 UNI_TRAFFIC_BMBS0_P | UNI_TRAFFIC_BMBS1_P |
3518 UNI_TRAFFIC_BABR1_P;
3519#define DTAB(U,X) \
3520 { U##X##PCR1_P, \
3521 -1, U##X##TAG, 0 }, /* 1, 2, 8, 14 */ \
3522 { U##X##PCR0_P | U##X##PCR1_P, \
3523 +1, U##X##TAG, U##X##TAG }, /* 3 */ \
3524 { U##X##PCR1_P | U##X##SCR1_P | U##X##MBS1_P, \
3525 -1, U##X##TAG, 0 }, /* 4, 9, 10, 15 */ \
3526 { U##X##PCR1_P | U##X##SCR0_P | U##X##MBS0_P, \
3527 -1, 0, 0 }, /* 5, 6, 11, 12 */ \
3528 { U##X##PCR0_P | U##X##PCR1_P, \
3529 -1, 0, 0 }, /* 7, 13 */ \
3530 { U##X##PCR1_P | U##X##ABR1_P, \
3531 -1, U##X##TAG, 0 }, /* 16a */
3532#define DTABSIZE 6
3533
3534 static struct tallow allow[2][DTABSIZE] = {
3535 { DTAB(UNI_TRAFFIC_, F) },
3536 { DTAB(UNI_TRAFFIC_, B) },
3537 };
3538#undef DTAB
3539
3540 u_int f, b, p, m;
3541 int i;
3542
3543 f = present & fmask;
3544 b = present & bmask;
3545 p = present & (fmask | bmask);
3546 m = (present & UNI_TRAFFIC_MOPT_P)
3547 ? ( (ie->ftag ? UNI_TRAFFIC_FTAG : 0)
3548 | (ie->btag ? UNI_TRAFFIC_BTAG : 0)
3549 | (ie->fdisc ? UNI_TRAFFIC_FDISC : 0)
3550 | (ie->bdisc ? UNI_TRAFFIC_BDISC : 0))
3551 : 0xffff;
3552
3553
3554 if(present & UNI_TRAFFIC_BEST_P) {
3555 /*
3556 * Lines 17 and 18
3557 */
3558 if(p != (UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_BPCR1_P))
3559 return -1;
3560 return 0;
3561 }
3562
3563 /*
3564 * Check forward and backward independent. There must be a higher
3565 * level checking in the CAC
3566 */
3567 for(i = 0; i < DTABSIZE; i++)
3568 if(check_traffic(f, m, &allow[0][i]))
3569 break;
3570 if(i == DTABSIZE)
3571 return -1;
3572
3573 for(i = 0; i < DTABSIZE; i++)
3574 if(check_traffic(b, m, &allow[1][i]))
3575 break;
3576 if(i == DTABSIZE)
3577 return -1;
3578
3579 return 0;
3580}
3581
3582static int
3583encode_traffic_common(struct uni_msg *msg, struct uni_xtraffic *ie,
3584 u_int present, struct unicx *cx __unused)
3585{
3586 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR0_P,
3587 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3588 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR0_P,
3589 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3590 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR1_P,
3591 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3592 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR1_P,
3593 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3594 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR0_P,
3595 UNI_TRAFFIC_FSCR0_ID, ie->fscr0);
3596 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR0_P,
3597 UNI_TRAFFIC_BSCR0_ID, ie->bscr0);
3598 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR1_P,
3599 UNI_TRAFFIC_FSCR1_ID, ie->fscr1);
3600 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR1_P,
3601 UNI_TRAFFIC_BSCR1_ID, ie->bscr1);
3602 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS0_P,
3603 UNI_TRAFFIC_FMBS0_ID, ie->fmbs0);
3604 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS0_P,
3605 UNI_TRAFFIC_BMBS0_ID, ie->bmbs0);
3606 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS1_P,
3607 UNI_TRAFFIC_FMBS1_ID, ie->fmbs1);
3608 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS1_P,
3609 UNI_TRAFFIC_BMBS1_ID, ie->bmbs1);
3610 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FABR1_P,
3611 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3612 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BABR1_P,
3613 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3614
3615 APP_OPT(msg, present, UNI_TRAFFIC_BEST_P,
3616 UNI_TRAFFIC_BEST_ID);
3617 APP_OPT_BYTE(msg, present, UNI_TRAFFIC_MOPT_P,
3618 UNI_TRAFFIC_MOPT_ID,
3619 (ie->ftag ? UNI_TRAFFIC_FTAG : 0) |
3620 (ie->btag ? UNI_TRAFFIC_BTAG : 0) |
3621 (ie->fdisc ? UNI_TRAFFIC_FDISC : 0) |
3622 (ie->fdisc ? UNI_TRAFFIC_BDISC : 0));
3623
3624 return 0;
3625}
3626
3627static int
3628decode_traffic_common(struct uni_xtraffic *ie, struct uni_msg *msg,
3629 u_int ielen, u_int *present)
3630{
3631 u_char c;
3632
3633 while(ielen--) {
3634 switch(c = *msg->b_rptr++) {
3635
3636 default:
3637 rej:
3638 return -1;
3639
3640 DEC_GETF3(TRAFFIC_FPCR0, fpcr0, *present);
3641 DEC_GETF3(TRAFFIC_BPCR0, bpcr0, *present);
3642 DEC_GETF3(TRAFFIC_FPCR1, fpcr1, *present);
3643 DEC_GETF3(TRAFFIC_BPCR1, bpcr1, *present);
3644 DEC_GETF3(TRAFFIC_FSCR0, fscr0, *present);
3645 DEC_GETF3(TRAFFIC_BSCR0, bscr0, *present);
3646 DEC_GETF3(TRAFFIC_FSCR1, fscr1, *present);
3647 DEC_GETF3(TRAFFIC_BSCR1, bscr1, *present);
3648 DEC_GETF3(TRAFFIC_FMBS0, fmbs0, *present);
3649 DEC_GETF3(TRAFFIC_BMBS0, bmbs0, *present);
3650 DEC_GETF3(TRAFFIC_BMBS1, bmbs1, *present);
3651 DEC_GETF3(TRAFFIC_FABR1, fabr1, *present);
3652 DEC_GETF3(TRAFFIC_BABR1, babr1, *present);
3653
3654 case UNI_TRAFFIC_BEST_ID:
3655 *present |= UNI_TRAFFIC_BEST_P;
3656 break;
3657
3658 case UNI_TRAFFIC_MOPT_ID:
3659 if(ielen == 0)
3660 return -1;
3661 ielen--;
3662 if(!(*present & UNI_TRAFFIC_MOPT_P)) {
3663 *present |= UNI_TRAFFIC_MOPT_P;
3664 ie->ftag = (*msg->b_rptr&UNI_TRAFFIC_FTAG)?1:0;
3665 ie->btag = (*msg->b_rptr&UNI_TRAFFIC_BTAG)?1:0;
3666 ie->fdisc = (*msg->b_rptr&UNI_TRAFFIC_FDISC)?1:0;
3667 ie->bdisc = (*msg->b_rptr&UNI_TRAFFIC_BDISC)?1:0;
3668 }
3669 msg->b_rptr++;
3670 break;
3671 }
3672 }
3673 return 0;
3674}
3675
3676
3677/*****************************************************************/
3678
3679DEF_IE_PRINT(itu, traffic)
3680{
3681 if(uni_print_iehdr("traffic", &ie->h, cx))
3682 return;
3683 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3684 uni_print_ieend(cx);
3685}
3686
3687DEF_IE_CHECK(itu, traffic)
3688{
3689 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3690}
3691
3692DEF_IE_ENCODE(itu, traffic)
3693{
3694 START_IE(traffic, UNI_IE_TRAFFIC, 26);
3695 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3696 SET_IE_LEN(msg);
3697 return 0;
3698}
3699
3700DEF_IE_DECODE(itu, traffic)
3701{
3702 IE_START(;);
3703
3704 if(ielen > 30)
3705 goto rej;
3706
3707 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3708 goto rej;
3709
3710 IE_END(TRAFFIC);
3711}
3712
3713/*****************************************************************/
3714
3715DEF_IE_PRINT(itu, atraffic)
3716{
3717 if(uni_print_iehdr("atraffic", &ie->h, cx))
3718 return;
3719 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3720 uni_print_ieend(cx);
3721}
3722
3723DEF_IE_CHECK(itu, atraffic)
3724{
3725 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3726}
3727
3728DEF_IE_ENCODE(itu, atraffic)
3729{
3730 START_IE(traffic, UNI_IE_ATRAFFIC, 26);
3731 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3732 SET_IE_LEN(msg);
3733 return 0;
3734}
3735
3736DEF_IE_DECODE(itu, atraffic)
3737{
3738 IE_START(;);
3739
3740 if(ielen > 30)
3741 goto rej;
3742
3743 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3744 goto rej;
3745
3746 IE_END(ATRAFFIC);
3747}
3748
3749/*****************************************************************/
3750
3751DEF_IE_PRINT(itu, mintraffic)
3752{
3753 if(uni_print_iehdr("mintraffic", &ie->h, cx))
3754 return;
3755
3756 uni_print_entry(cx, "pcr0", "(");
3757 if(ie->h.present & UNI_MINTRAFFIC_FPCR0_P)
3758 uni_printf(cx, "%u", ie->fpcr0);
3759 uni_putc(',', cx);
3760 if(ie->h.present & UNI_MINTRAFFIC_BPCR0_P)
3761 uni_printf(cx, "%u", ie->bpcr0);
3762 uni_putc(')', cx);
3763
3764 uni_print_entry(cx, "pcr1", "(");
3765 if(ie->h.present & UNI_MINTRAFFIC_FPCR1_P)
3766 uni_printf(cx, "%u", ie->fpcr1);
3767 uni_putc(',', cx);
3768 if(ie->h.present & UNI_MINTRAFFIC_BPCR1_P)
3769 uni_printf(cx, "%u", ie->bpcr1);
3770 uni_putc(')', cx);
3771
3772 uni_print_entry(cx, "abr1", "(");
3773 if(ie->h.present & UNI_MINTRAFFIC_FABR1_P)
3774 uni_printf(cx, "%u", ie->fabr1);
3775 uni_putc(',', cx);
3776 if(ie->h.present & UNI_MINTRAFFIC_BABR1_P)
3777 uni_printf(cx, "%u", ie->babr1);
3778 uni_printf(cx, ")");
3779
3780 uni_print_ieend(cx);
3781}
3782
3783DEF_IE_CHECK(itu, mintraffic)
3784{
3785 u_int abr;
3786 u_int xbr;
3787 cx = cx;
3788
3789 abr = ie->h.present & (UNI_MINTRAFFIC_FABR1_P|UNI_MINTRAFFIC_BABR1_P);
3790 xbr = ie->h.present & (UNI_MINTRAFFIC_FPCR0_P|UNI_MINTRAFFIC_BPCR0_P|
3791 UNI_MINTRAFFIC_FPCR1_P|UNI_MINTRAFFIC_BPCR1_P);
3792
3793 if(abr && xbr)
3794 return -1;
3795
3796 return 0;
3797}
3798
3799DEF_IE_ENCODE(itu, mintraffic)
3800{
3801 START_IE(mintraffic, UNI_IE_MINTRAFFIC, 16);
3802
3803 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR0_P,
3804 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3805 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR0_P,
3806 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3807 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR1_P,
3808 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3809 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR1_P,
3810 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3811 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FABR1_P,
3812 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3813 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BABR1_P,
3814 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3815
3816 SET_IE_LEN(msg);
3817 return 0;
3818}
3819
3820DEF_IE_DECODE(itu, mintraffic)
3821{
3822 u_char c;
3823
3824 IE_START(;);
3825
3826 if(ielen > 20)
3827 goto rej;
3828
3829 while(ielen--) {
3830 switch(c = *msg->b_rptr++) {
3831
3832 default:
3833 goto rej;
3834
3835 DEC_GETF3(MINTRAFFIC_FPCR0, fpcr0, ie->h.present);
3836 DEC_GETF3(MINTRAFFIC_BPCR0, bpcr0, ie->h.present);
3837 DEC_GETF3(MINTRAFFIC_FPCR1, fpcr1, ie->h.present);
3838 DEC_GETF3(MINTRAFFIC_BPCR1, bpcr1, ie->h.present);
3839 DEC_GETF3(MINTRAFFIC_FABR1, fabr1, ie->h.present);
3840 DEC_GETF3(MINTRAFFIC_BABR1, babr1, ie->h.present);
3841 }
3842 }
3843
3844 IE_END(MINTRAFFIC);
3845}
3846
3847/*****************************************************************/
3848
3849DEF_IE_PRINT(net, mdcr)
3850{
3851 static const struct uni_print_tbl origin_tbl[] = {
3852 MKT(UNI_MDCR_ORIGIN_USER, user),
3853 MKT(UNI_MDCR_ORIGIN_NET, net),
3854 EOT()
3855 };
3856
3857 if(uni_print_iehdr("mdcr", &ie->h, cx))
3858 return;
3859
3860 uni_print_tbl("origin", ie->origin, origin_tbl, cx);
3861 uni_print_entry(cx, "mdcr", "(");
3862 uni_printf(cx, "%u", ie->fmdcr);
3863 uni_putc(',', cx);
3864 uni_printf(cx, "%u", ie->bmdcr);
3865 uni_putc(')', cx);
3866
3867 uni_print_ieend(cx);
3868}
3869
3870DEF_IE_CHECK(net, mdcr)
3871{
3872 cx = cx;
3873
3874 if ((ie->origin != UNI_MDCR_ORIGIN_USER &&
3875 ie->origin != UNI_MDCR_ORIGIN_NET) ||
3876 ie->fmdcr >= (1 << 24) || ie->bmdcr >= (1 << 24))
3877 return (-1);
3878
3879 return (0);
3880}
3881
3882DEF_IE_ENCODE(net, mdcr)
3883{
3884 START_IE(mdcr, UNI_IE_MDCR, 9);
3885
3886 APP_BYTE(msg, ie->origin);
3887 APP_SUB_24BIT(msg, UNI_TRAFFIC_FMDCR_ID, ie->fmdcr);
3888 APP_SUB_24BIT(msg, UNI_TRAFFIC_BMDCR_ID, ie->bmdcr);
3889
3890 SET_IE_LEN(msg);
3891 return (0);
3892}
3893
3894DEF_IE_DECODE(net, mdcr)
3895{
3896 u_char c;
3897#define UNI_TRAFFIC_FMDCR_P 0x01
3898#define UNI_TRAFFIC_BMDCR_P 0x02
3899 u_int p = 0;
3900
3901 IE_START(;);
3902
3903 if(ielen != 9)
3904 goto rej;
3905
3906 ie->origin = *msg->b_rptr++;
3907 ielen--;
3908
3909 while(ielen--) {
3910 switch(c = *msg->b_rptr++) {
3911
3912 default:
3913 goto rej;
3914
3915 DEC_GETF3(TRAFFIC_FMDCR, fmdcr, p);
3916 DEC_GETF3(TRAFFIC_BMDCR, bmdcr, p);
3917 }
3918 }
3919 if (p != (UNI_TRAFFIC_FMDCR_P | UNI_TRAFFIC_BMDCR_P))
3920 goto rej;
3921
3922 IE_END(MDCR);
3923}
3924
3925/*********************************************************************
3926 *
3927 * Connection identifier
3928 *
3929 * References for this IE are:
3930 *
3931 * Q.2931 pp. 69...70
3932 * UNI4.0 pp. 15...16
3933 * PNNI1.0 p. 198
3934 *
3935 * Only ITU-T coding allowed.
3936 */
3937
3938DEF_IE_PRINT(itu, connid)
3939{
3940 static const struct uni_print_tbl tbl[] = {
3941 MKT(UNI_CONNID_VCI, exclusive),
3942 MKT(UNI_CONNID_ANYVCI, any),
3943 MKT(UNI_CONNID_NOVCI, no),
3944 EOT()
3945 };
3946 static const struct uni_print_tbl assoc_tbl[] = {
3947 MKT(UNI_CONNID_ASSOC, associated),
3948 MKT(UNI_CONNID_NONASSOC,non-associated),
3949 EOT()
3950 };
3951
3952 if(uni_print_iehdr("connid", &ie->h, cx))
3953 return;
3954
3955 uni_print_tbl("mode", ie->assoc, assoc_tbl, cx);
3956 uni_print_entry(cx, "connid", "(%u,", ie->vpci);
3957 if(ie->type == UNI_CONNID_VCI)
3958 uni_printf(cx, "%u", ie->vci);
3959 else
3960 uni_print_tbl(NULL, ie->type, tbl, cx);
3961 uni_printf(cx, ")");
3962
3963 uni_print_ieend(cx);
3964}
3965
3966DEF_IE_CHECK(itu, connid)
3967{
3968 cx = cx;
3969 switch(ie->type) {
3970 default:
3971 return -1;
3972 case UNI_CONNID_VCI:
3973 case UNI_CONNID_ANYVCI:
3974 case UNI_CONNID_NOVCI:
3975 break;
3976 }
3977
3978#if 0
3979 /*
3980 * This field must be checked by the application to fulfil
3981 * Q.2931Amd4 27) 5.2.3 last sentence
3982 */
3983 switch(ie->assoc) {
3984
3985 case UNI_CONNID_ASSOC:
3986 if(!cx->cx.pnni)
3987 return -1;
3988 break;
3989
3990 case UNI_CONNID_NONASSOC:
3991 break;
3992
3993 default:
3994 return -1;
3995 }
3996#endif
3997 return 0;
3998}
3999
4000DEF_IE_ENCODE(itu, connid)
4001{
4002 START_IE(connid, UNI_IE_CONNID, 5);
4003
4004 APP_BYTE(msg, 0x80 | (ie->assoc << 3) | ie->type);
4005 APP_BYTE(msg, ie->vpci >> 8);
4006 APP_BYTE(msg, ie->vpci >> 0);
4007 APP_BYTE(msg, ie->vci >> 8);
4008 APP_BYTE(msg, ie->vci >> 0);
4009
4010 SET_IE_LEN(msg);
4011 return 0;
4012}
4013
4014DEF_IE_DECODE(itu, connid)
4015{
4016 u_char c;
4017
4018 IE_START(;);
4019
4020 if(ielen != 5)
4021 goto rej;
4022
4023 c = *msg->b_rptr++;
4024 if((c & 0x80) == 0)
4025 goto rej;
4026 ie->assoc = (c >> 3) & 3;
4027 ie->type = c & 7;
4028 ie->vpci = *msg->b_rptr++ << 8;
4029 ie->vpci |= *msg->b_rptr++;
4030 ie->vci = *msg->b_rptr++ << 8;
4031 ie->vci |= *msg->b_rptr++;
4032
4033 IE_END(CONNID);
4034}
4035
4036/*********************************************************************
4037 *
4038 * Quality of Service
4039 *
4040 * References for this IE are:
4041 *
4042 * Q.2931 pp. 72
4043 * UNI4.0 pp. 16...17
4044 */
4045
4046static void
4047print_qos(struct unicx *cx, struct uni_ie_qos *ie)
4048{
4049 static const struct uni_print_tbl class_tbl[] = {
4050 MKT(UNI_QOS_CLASS0, Class0),
4051 MKT(UNI_QOS_CLASS1, Class1),
4052 MKT(UNI_QOS_CLASS2, Class2),
4053 MKT(UNI_QOS_CLASS3, Class3),
4054 MKT(UNI_QOS_CLASS4, Class4),
4055 EOT()
4056 };
4057
4058 if(uni_print_iehdr("qos", &ie->h, cx))
4059 return;
4060
4061 uni_print_tbl("fwd", ie->fwd, class_tbl, cx);
4062 uni_print_tbl("bwd", ie->bwd, class_tbl, cx);
4063
4064 uni_print_ieend(cx);
4065}
4066
4067DEF_IE_PRINT(itu, qos)
4068{
4069 print_qos(cx, ie);
4070}
4071DEF_IE_PRINT(net, qos)
4072{
4073 print_qos(cx, ie);
4074}
4075
4076DEF_IE_CHECK(itu, qos)
4077{
4078 cx = cx;
4079
4080 switch(ie->fwd) {
4081 default:
4082 return -1;
4083
4084 case UNI_QOS_CLASS0:
4085 break;
4086 }
4087 switch(ie->bwd) {
4088 default:
4089 return -1;
4090
4091 case UNI_QOS_CLASS0:
4092 break;
4093 }
4094 return 0;
4095}
4096
4097DEF_IE_CHECK(net, qos)
4098{
4099 cx = cx;
4100
4101 switch(ie->fwd) {
4102 default:
4103 return -1;
4104
4105 case UNI_QOS_CLASS1:
4106 case UNI_QOS_CLASS2:
4107 case UNI_QOS_CLASS3:
4108 case UNI_QOS_CLASS4:
4109 break;
4110 }
4111 switch(ie->bwd) {
4112 default:
4113 return -1;
4114
4115 case UNI_QOS_CLASS1:
4116 case UNI_QOS_CLASS2:
4117 case UNI_QOS_CLASS3:
4118 case UNI_QOS_CLASS4:
4119 break;
4120 }
4121 return 0;
4122}
4123
4124DEF_IE_ENCODE(itu, qos)
4125{
4126 START_IE(qos, UNI_IE_QOS, 2);
4127
4128 APP_BYTE(msg, ie->fwd);
4129 APP_BYTE(msg, ie->bwd);
4130
4131 SET_IE_LEN(msg);
4132 return 0;
4133}
4134DEF_IE_ENCODE(net, qos)
4135{
4136 START_IE(qos, UNI_IE_QOS, 2);
4137
4138 APP_BYTE(msg, ie->fwd);
4139 APP_BYTE(msg, ie->bwd);
4140
4141 SET_IE_LEN(msg);
4142 return 0;
4143}
4144
4145DEF_IE_DECODE(itu, qos)
4146{
4147 IE_START(;);
4148
4149 if(ielen != 2)
4150 goto rej;
4151
4152 ie->fwd = *msg->b_rptr++;
4153 ie->bwd = *msg->b_rptr++;
4154
4155 IE_END(QOS);
4156}
4157
4158DEF_IE_DECODE(net, qos)
4159{
4160 IE_START(;);
4161
4162 if(ielen != 2)
4163 goto rej;
4164
4165 ie->fwd = *msg->b_rptr++;
4166 ie->bwd = *msg->b_rptr++;
4167
4168 IE_END(QOS);
4169}
4170
4171/*********************************************************************
4172 *
4173 * Broadband Lower Layer Information
4174 *
4175 * References for this IE are:
4176 *
4177 * Q.2931 pp. 53...54
4178 * UNI4.0 p. 12
4179 *
4180 * Only ITU-T coding allowed.
4181 */
4182
4183DEF_IE_PRINT(itu, bhli)
4184{
4185 static const struct uni_print_tbl type_tbl[] = {
4186 MKT(UNI_BHLI_ISO, iso),
4187 MKT(UNI_BHLI_USER, user),
4188 MKT(UNI_BHLI_VENDOR, vendor),
4189 EOT()
4190 };
4191 u_int i;
4192
4193 if(uni_print_iehdr("bhli", &ie->h, cx))
4194 return;
4195
4196 uni_print_tbl("type", ie->type, type_tbl, cx);
4197 uni_print_entry(cx, "len", "%d", ie->len);
4198 uni_print_entry(cx, "info", "(");
4199 for(i = 0; i < ie->len; i++)
4200 uni_printf(cx, ",0x%02x", ie->info[i]);
4201 uni_printf(cx, ")");
4202
4203 uni_print_ieend(cx);
4204}
4205
4206DEF_IE_CHECK(itu, bhli)
4207{
4208 cx = cx;
4209
4210 switch(ie->type) {
4211 default:
4212 return -1;
4213
4214 case UNI_BHLI_ISO:
4215 case UNI_BHLI_USER:
4216 case UNI_BHLI_VENDOR:
4217 break;
4218 }
4219 if(ie->len > 8)
4220 return -1;
4221
4222 return 0;
4223}
4224
4225DEF_IE_ENCODE(itu, bhli)
4226{
4227 START_IE(bhli, UNI_IE_BHLI, 9);
4228
4229 APP_BYTE(msg, 0x80 | ie->type);
4230 APP_BUF(msg, ie->info, ie->len);
4231
4232 SET_IE_LEN(msg);
4233 return 0;
4234}
4235
4236DEF_IE_DECODE(itu, bhli)
4237{
4238 u_char c;
4239
4240 IE_START(;);
4241
4242 if(ielen > 9)
4243 goto rej;
4244
4245 c = *msg->b_rptr++;
4246 ielen--;
4247
4248 if(!(c & 0x80))
4249 goto rej;
4250 ie->type = c & 0x7f;
4251 ie->len = ielen;
4252 (void)memcpy(ie->info, msg->b_rptr, ielen);
4253 msg->b_rptr += ielen;
4254
4255 IE_END(BHLI);
4256}
4257
4258/*********************************************************************
4259 *
4260 * Broadband bearer capabilities
4261 *
4262 * References for this IE are:
4263 *
4264 * Q.2931 pp. 51...52
4265 * Q.2931 Amd 1
4266 * UNI4.0 pp. 10...12, 106...109
4267 *
4268 * UNI4.0 changed the meaning of byte 5a. Instead of 3 bit traffic type and
4269 * 2 bit timing requirements there are now 7 bits ATM transfer capabilities.
4270 * However the old format is still supported: it should be recognized on
4271 * input, but never be generated on output. Mapping is left to the user of
4272 * UNI.
4273 *
4274 * Amd 1 not checked XXX.
4275 *
4276 * The Appendix in UNI4.0 lists all the supported combinations of various
4277 * traffic IE's. The check function implements part of it.
4278 *
4279 * A C X VP
4280 * 1 CBR.1 7 . 7 7
4281 * 2 CBR.2 - . 4,5,6 5 (*)
4282 * 3 CBR.3 - . 4,5,6 5 (*)
4283 * 4 rt-VBR.1 . 19 19 19
4284 * 5 rt-VBR.2 . 9 1,9 9
4285 * 6 rt-VBR.3 . 9 1,9 9
4286 * 7 rt-VBR.4 . . 1,9 . (*)
4287 * 8 rt-VBR.5 . . 1,9 . (*)
4288 * 9 rt-VBR.6 . 9 1,9 9 (*)
4289 * 10 nrt-VBR.1 . 11 11 11
4290 * 11 nrt-VBR.2 . - -,0,2,8,10 -,10
4291 * 12 nrt-VBR.3 . - -,0,2,8,10 -,10
4292 * 13 nrt-VBR.4 . - -,0,2,8,10 . (*)
4293 * 14 nrt-VBR.5 . - -,0,2,8,10 . (*)
4294 * 15 nrt-VBR.6 . - -,0,2,8,10 -,10(*)
4295 * 16 ABR . 12 12 12
4296 * 17 UBR.1 . - -,0,2,8,10 -,10
4297 * 18 UBR.2 . - -,0,2,8,10 -,10
4298 *
4299 * (*) compatibility
4300 *
4301 * Only ITU-T coding allowed.
4302 */
4303
4304DEF_IE_PRINT(itu, bearer)
4305{
4306 static const struct uni_print_tbl bclass_tbl[] = {
4307 MKT(UNI_BEARER_A, bcob-A),
4308 MKT(UNI_BEARER_C, bcob-C),
4309 MKT(UNI_BEARER_X, bcob-X),
4310 MKT(UNI_BEARER_TVP, transparent-VP),
4311 EOT()
4312 };
4313 static const struct uni_print_tbl atc_tbl[] = {
4314 MKT(UNI_BEARER_ATC_CBR, cbr),
4315 MKT(UNI_BEARER_ATC_CBR1, cbr1),
4316 MKT(UNI_BEARER_ATC_VBR, vbr),
4317 MKT(UNI_BEARER_ATC_VBR1, vbr1),
4318 MKT(UNI_BEARER_ATC_NVBR, nvbr),
4319 MKT(UNI_BEARER_ATC_NVBR1, nvbr1),
4320 MKT(UNI_BEARER_ATC_ABR, abr),
4321
4322 MKT(UNI_BEARER_ATCX_0, x0),
4323 MKT(UNI_BEARER_ATCX_1, x1),
4324 MKT(UNI_BEARER_ATCX_2, x2),
4325 MKT(UNI_BEARER_ATCX_4, x4),
4326 MKT(UNI_BEARER_ATCX_6, x6),
4327 MKT(UNI_BEARER_ATCX_8, x8),
4328 EOT()
4329 };
4330 static const struct uni_print_tbl cfg_tbl[] = {
4331 MKT(UNI_BEARER_P2P, p2p),
4332 MKT(UNI_BEARER_MP, mp),
4333 EOT()
4334 };
4335 static const struct uni_print_tbl clip_tbl[] = {
4336 MKT(UNI_BEARER_NOCLIP, no),
4337 MKT(UNI_BEARER_CLIP, yes),
4338 EOT()
4339 };
4340
4341 if(uni_print_iehdr("bearer", &ie->h, cx))
4342 return;
4343
4344 uni_print_tbl("class", ie->bclass, bclass_tbl, cx);
4345
4346 if(ie->h.present & UNI_BEARER_ATC_P) {
4347 uni_print_tbl("atc", ie->atc, atc_tbl, cx);
4348 }
4349 uni_print_tbl("clip", ie->clip, clip_tbl, cx);
4350 uni_print_tbl("cfg", ie->cfg, cfg_tbl, cx);
4351
4352 uni_print_ieend(cx);
4353}
4354
4355#define QTYPE(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATC_##A)
4356#define QTYPEX(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATCX_##A)
4357#define QTYPE0(C) ((UNI_BEARER_##C << 8) | (1 << 16))
4358DEF_IE_CHECK(itu, bearer)
4359{
4360 cx = cx;
4361
4362 switch((ie->bclass << 8) |
4363 ((ie->h.present & UNI_BEARER_ATC_P) == 0
4364 ? (1 << 16)
4365 : ie->atc)) {
4366
4367 default:
4368 return -1;
4369
4370 case QTYPE (A, CBR1): /* 1 */
4371 case QTYPE (X, CBR1): /* 1 */
4372 case QTYPE (TVP, CBR1): /* 1 */
4373
4374 case QTYPE0(A): /* 2,3 */
4375 case QTYPEX(X, 4): /* 2,3 */
4376 case QTYPE (X, CBR): /* 2,3 */
4377 case QTYPEX(X, 6): /* 2,3 */
4378 case QTYPE (TVP, CBR): /* 2,3 */
4379
4380 case QTYPE (C, VBR1): /* 4 */
4381 case QTYPE (X, VBR1): /* 4 */
4382 case QTYPE (TVP, VBR1): /* 4 */
4383
4384 case QTYPE (C, VBR): /* 5,6,9 */
4385 case QTYPEX(X, 1): /* 5,6,7,8,9 */
4386 case QTYPE (X, VBR): /* 5,6,7,8,9 */
4387 case QTYPE (TVP, VBR): /* 5,6,9 */
4388
4389 case QTYPE (C, NVBR1): /* 10 */
4390 case QTYPE (X, NVBR1): /* 10 */
4391 case QTYPE (TVP, NVBR1): /* 10 */
4392
4393 case QTYPE0(C): /* 11,12,13,14,15,17,18 */
4394 case QTYPE0(X): /* 11,12,13,14,15,17,18 */
4395 case QTYPEX(X, 0): /* 11,12,13,14,15,17,18 */
4396 case QTYPEX(X, 2): /* 11,12,13,14,15,17,18 */
4397 case QTYPEX(X, 8): /* 11,12,13,14,15,17,18 */
4398 case QTYPE (X, NVBR): /* 11,12,13,14,15,17,18 */
4399 case QTYPE0(TVP): /* 11,12,15,17,18 */
4400 case QTYPE (TVP, NVBR): /* 11,12,15,17,18 */
4401
4402 case QTYPE (C, ABR): /* 16 */
4403 case QTYPE (X, ABR): /* 16 */
4404 case QTYPE (TVP, ABR): /* 16 */
4405 break;
4406 }
4407
4408 switch(ie->clip) {
4409 default:
4410 return -1;
4411
4412 case UNI_BEARER_NOCLIP:
4413 case UNI_BEARER_CLIP:
4414 break;
4415 }
4416 switch(ie->cfg) {
4417 default:
4418 return -1;
4419
4420 case UNI_BEARER_P2P:
4421 case UNI_BEARER_MP:
4422 break;
4423 }
4424
4425 return 0;
4426}
4427#undef QTYPE
4428#undef QTYPEX
4429#undef QTYPE0
4430
4431DEF_IE_ENCODE(itu, bearer)
4432{
4433 START_IE(bearer, UNI_IE_BEARER, 3);
4434
4435 APP_BYTE(msg, ie->bclass |
4436 ((ie->h.present & UNI_BEARER_ATC_P) ? 0:0x80));
4437 APP_OPT(msg, ie->h.present, UNI_BEARER_ATC_P,
4438 0x80 | ie->atc);
4439 APP_BYTE(msg, 0x80 | (ie->clip << 5) | ie->cfg);
4440
4441 SET_IE_LEN(msg);
4442 return 0;
4443}
4444
4445DEF_IE_DECODE(itu, bearer)
4446{
4447 u_char c;
4448
4449 IE_START(;);
4450
4451 if(ielen != 2 && ielen != 3)
4452 goto rej;
4453
4454 c = *msg->b_rptr++;
4455 ielen--;
4456 ie->bclass = c & 0x1f;
4457 if(!(c & 0x80)) {
4458 c = *msg->b_rptr++;
4459 ielen--;
4460 ie->h.present |= UNI_BEARER_ATC_P;
4461
4462 switch(c & 0x7f) {
4463 /*
4464 * Real legal values
4465 */
4466 case UNI_BEARER_ATC_CBR:
4467 case UNI_BEARER_ATC_CBR1:
4468 case UNI_BEARER_ATC_VBR:
4469 case UNI_BEARER_ATC_VBR1:
4470 case UNI_BEARER_ATC_NVBR:
4471 case UNI_BEARER_ATC_NVBR1:
4472 case UNI_BEARER_ATC_ABR:
4473 break;
4474
4475 /*
4476 * Compat values
4477 */
4478 case UNI_BEARER_ATCX_0:
4479 case UNI_BEARER_ATCX_1:
4480 case UNI_BEARER_ATCX_2:
4481 case UNI_BEARER_ATCX_4:
4482 case UNI_BEARER_ATCX_6:
4483 case UNI_BEARER_ATCX_8:
4484 break;
4485
4486 default:
4487 goto rej;
4488 }
4489
4490 if(!(c & 0x80))
4491 goto rej;
4492
4493 ie->atc = c & 0x7f;
4494 }
4495 if(ielen == 0)
4496 goto rej;
4497 c = *msg->b_rptr++;
4498 ielen--;
4499 if(!(c & 0x80))
4500 goto rej;
4501 ie->clip = (c >> 5) & 0x3;
4502 ie->cfg = c & 0x3;
4503
4504 IE_END(BEARER);
4505}
4506
4507/*********************************************************************
4508 *
4509 * Broadband Lower Layer Information
4510 *
4511 * References for this IE are:
4512 *
4513 * Q.2931 pp. 54...59
4514 * UNI4.0 pp. 12...14
4515 *
4516 * UNI4.0 states, that layer 1 info is not supported.
4517 * We allow a layer 1 protocol identifier.
4518 *
4519 * UNI4.0 states, that the layer information subelements are NOT position
4520 * dependent. We allow them in any order on input, but generate always the
4521 * definit order on output.
4522 *
4523 * Only ITU-T coding allowed.
4524 */
4525
4526DEF_IE_PRINT(itu, blli)
4527{
4528 static const struct uni_print_tbl l2_tbl[] = {
4529 MKT(UNI_BLLI_L2_BASIC, basic),
4530 MKT(UNI_BLLI_L2_Q921, Q921),
4531 MKT(UNI_BLLI_L2_X25LL, X25-LL),
4532 MKT(UNI_BLLI_L2_X25ML, X25-ML),
4533 MKT(UNI_BLLI_L2_LABP, LAPB),
4534 MKT(UNI_BLLI_L2_HDLC_ARM, HDLC-ARM),
4535 MKT(UNI_BLLI_L2_HDLC_NRM, HDLC-NRM),
4536 MKT(UNI_BLLI_L2_HDLC_ABM, HDLC-ABM),
4537 MKT(UNI_BLLI_L2_LAN, LAN),
4538 MKT(UNI_BLLI_L2_X75, X75),
4539 MKT(UNI_BLLI_L2_Q922, Q922),
4540 MKT(UNI_BLLI_L2_USER, user),
4541 MKT(UNI_BLLI_L2_ISO7776, ISO7776),
4542 EOT()
4543 };
4544 static const struct uni_print_tbl l2mode_tbl[] = {
4545 MKT(UNI_BLLI_L2NORM, normal),
4546 MKT(UNI_BLLI_L2EXT, extended),
4547 EOT()
4548 };
4549 static const struct uni_print_tbl l3_tbl[] = {
4550 MKT(UNI_BLLI_L3_X25, X25),
4551 MKT(UNI_BLLI_L3_ISO8208, ISO8208),
4552 MKT(UNI_BLLI_L3_X223, X223),
4553 MKT(UNI_BLLI_L3_CLMP, CLMP),
4554 MKT(UNI_BLLI_L3_T70, T70),
4555 MKT(UNI_BLLI_L3_TR9577, TR9577),
4556 MKT(UNI_BLLI_L3_USER, user),
4557 MKT(UNI_BLLI_L3_H310, H310),
4558 MKT(UNI_BLLI_L3_H321, H321),
4559 EOT()
4560 };
4561 static const struct uni_print_tbl l3mode_tbl[] = {
4562 MKT(UNI_BLLI_L3NSEQ, normal-seq),
4563 MKT(UNI_BLLI_L3ESEQ, extended-seq),
4564 EOT()
4565 };
4566 static const struct uni_print_tbl l3psiz_tbl[] = {
4567 MKT(UNI_BLLI_L3_16, 16),
4568 MKT(UNI_BLLI_L3_32, 32),
4569 MKT(UNI_BLLI_L3_64, 64),
4570 MKT(UNI_BLLI_L3_128, 128),
4571 MKT(UNI_BLLI_L3_256, 256),
4572 MKT(UNI_BLLI_L3_512, 512),
4573 MKT(UNI_BLLI_L3_1024, 1024),
4574 MKT(UNI_BLLI_L3_2048, 2048),
4575 MKT(UNI_BLLI_L3_4096, 4096),
4576 EOT()
4577 };
4578 static const struct uni_print_tbl l3ttype_tbl[] = {
4579 MKT(UNI_BLLI_L3_TTYPE_RECV, receive_only),
4580 MKT(UNI_BLLI_L3_TTYPE_SEND, send_only),
4581 MKT(UNI_BLLI_L3_TTYPE_BOTH, both),
4582 EOT()
4583 };
4584 static const struct uni_print_tbl l3mux_tbl[] = {
4585 MKT(UNI_BLLI_L3_MUX_NOMUX, NOMUX),
4586 MKT(UNI_BLLI_L3_MUX_TS, TS),
4587 MKT(UNI_BLLI_L3_MUX_TSFEC, TSFEC),
4588 MKT(UNI_BLLI_L3_MUX_PS, PS),
4589 MKT(UNI_BLLI_L3_MUX_PSFEC, PSFEC),
4590 MKT(UNI_BLLI_L3_MUX_H221, H221),
4591 EOT()
4592 };
4593 static const struct uni_print_tbl l3tcap_tbl[] = {
4594 MKT(UNI_BLLI_L3_TCAP_NOIND, noind),
4595 MKT(UNI_BLLI_L3_TCAP_AAL1, aal1),
4596 MKT(UNI_BLLI_L3_TCAP_AAL5, aal5),
4597 MKT(UNI_BLLI_L3_TCAP_AAL15, aal1&5),
4598 EOT()
4599 };
4600
4601 if(uni_print_iehdr("blli", &ie->h, cx))
4602 return;
4603
4604 if(ie->h.present & UNI_BLLI_L1_P) {
4605 uni_print_entry(cx, "l1", "%u", ie->l1);
4606 uni_print_eol(cx);
4607 }
4608 if(ie->h.present & UNI_BLLI_L2_P) {
4609 uni_print_tbl("l2", ie->l2, l2_tbl, cx);
4610 uni_print_push_prefix("l2", cx);
4611 cx->indent++;
4612 if(ie->h.present & UNI_BLLI_L2_USER_P)
4613 uni_print_entry(cx, "proto", "%u", ie->l2_user);
4614 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4615 uni_print_entry(cx, "q933", "%u", ie->l2_q933);
4616 uni_print_tbl("mode", ie->l2_mode, l2mode_tbl, cx);
4617 }
4618 if(ie->h.present & UNI_BLLI_L2_WSIZ_P)
4619 uni_print_entry(cx, "wsize", "%u", ie->l2_wsiz);
4620 uni_print_pop_prefix(cx);
4621 cx->indent--;
4622 uni_print_eol(cx);
4623
4624 }
4625 if(ie->h.present & UNI_BLLI_L3_P) {
4626 uni_print_tbl("l3", ie->l3, l3_tbl, cx);
4627 uni_print_push_prefix("l3", cx);
4628 cx->indent++;
4629 if(ie->h.present & UNI_BLLI_L3_USER_P)
4630 uni_print_entry(cx, "proto", "%u", ie->l3_user);
4631 if(ie->h.present & UNI_BLLI_L3_MODE_P)
4632 uni_print_tbl("mode", ie->l3_mode, l3mode_tbl, cx);
4633 if(ie->h.present & UNI_BLLI_L3_PSIZ_P)
4634 uni_print_tbl("packet-size", ie->l3_psiz, l3psiz_tbl, cx);
4635 if(ie->h.present & UNI_BLLI_L3_WSIZ_P)
4636 uni_print_entry(cx, "window-size", "%u", ie->l3_wsiz);
4637 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4638 uni_print_tbl("ttype", ie->l3_ttype, l3ttype_tbl, cx);
4639 uni_print_tbl("tcap", ie->l3_tcap, l3tcap_tbl, cx);
4640 }
4641 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4642 uni_print_tbl("fmux", ie->l3_fmux, l3mux_tbl, cx);
4643 uni_print_tbl("bmux", ie->l3_bmux, l3mux_tbl, cx);
4644 }
4645 if(ie->h.present & UNI_BLLI_L3_IPI_P)
4646 uni_print_entry(cx, "ipi", "0x%02x", ie->l3_ipi);
4647 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4648 uni_print_entry(cx, "snap", "%06x.%04x", ie->oui, ie->pid);
4649 uni_print_pop_prefix(cx);
4650 cx->indent--;
4651 uni_print_eol(cx);
4652 }
4653
4654 uni_print_ieend(cx);
4655}
4656
4657DEF_IE_CHECK(itu, blli)
4658{
4659 cx = cx;
4660/*
4661 if(ie->h.present & UNI_BLLI_L1_P)
4662 ;
4663*/
4664
4665 if(ie->h.present & UNI_BLLI_L2_P) {
4666 static u_int mask =
4667 UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P |
4668 UNI_BLLI_L2_USER_P;
4669
4670 switch(ie->l2) {
4671 default:
4672 return -1;
4673
4674 case UNI_BLLI_L2_BASIC:
4675 case UNI_BLLI_L2_Q921:
4676 case UNI_BLLI_L2_LABP:
4677 case UNI_BLLI_L2_LAN:
4678 case UNI_BLLI_L2_X75:
4679 if(ie->h.present & mask)
4680 return -1;
4681 break;
4682
4683 case UNI_BLLI_L2_X25LL:
4684 case UNI_BLLI_L2_X25ML:
4685 case UNI_BLLI_L2_HDLC_ARM:
4686 case UNI_BLLI_L2_HDLC_NRM:
4687 case UNI_BLLI_L2_HDLC_ABM:
4688 case UNI_BLLI_L2_Q922:
4689 case UNI_BLLI_L2_ISO7776:
4690 switch(ie->h.present & mask) {
4691 default:
4692 return -1;
4693
4694 case 0:
4695 case UNI_BLLI_L2_Q933_P:
4696 case UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P:
4697 break;
4698 }
4699 break;
4700
4701 case UNI_BLLI_L2_USER:
4702 switch(ie->h.present & mask) {
4703 default:
4704 return -1;
4705
4706 case 0: /* XXX ? */
4707 case UNI_BLLI_L2_USER_P:
4708 break;
4709 }
4710 break;
4711 }
4712 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4713 if(ie->l2_q933 != 0)
4714 return -1;
4715
4716 switch(ie->l2_mode) {
4717 default:
4718 return -1;
4719
4720 case UNI_BLLI_L2NORM:
4721 case UNI_BLLI_L2EXT:
4722 break;
4723 }
4724 }
4725 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4726 if(ie->l2_wsiz == 0 || ie->l2_wsiz > 127)
4727 return -1;
4728 }
4729 if(ie->h.present & UNI_BLLI_L2_USER_P) {
4730 if(ie->l2_user > 127)
4731 return -1;
4732 }
4733 }
4734 if(ie->h.present & UNI_BLLI_L3_P) {
4735 static u_int mask =
4736 UNI_BLLI_L3_MODE_P | UNI_BLLI_L3_PSIZ_P |
4737 UNI_BLLI_L3_WSIZ_P | UNI_BLLI_L3_USER_P |
4738 UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P |
4739 UNI_BLLI_L3_TTYPE_P | UNI_BLLI_L3_MUX_P;
4740
4741 switch(ie->l3) {
4742 default:
4743 return -1;
4744
4745 case UNI_BLLI_L3_X25:
4746 case UNI_BLLI_L3_ISO8208:
4747 case UNI_BLLI_L3_X223:
4748 switch(ie->h.present & mask) {
4749 default:
4750 return -1;
4751
4752 case 0:
4753 case UNI_BLLI_L3_MODE_P:
4754 case UNI_BLLI_L3_MODE_P |
4755 UNI_BLLI_L3_PSIZ_P:
4756 case UNI_BLLI_L3_MODE_P |
4757 UNI_BLLI_L3_PSIZ_P |
4758 UNI_BLLI_L3_WSIZ_P:
4759 break;
4760 }
4761 break;
4762
4763 case UNI_BLLI_L3_CLMP:
4764 case UNI_BLLI_L3_T70:
4765 if(ie->h.present & mask)
4766 return -1;
4767 break;
4768
4769 case UNI_BLLI_L3_TR9577:
4770 switch(ie->h.present & mask) {
4771 default:
4772 return -1;
4773
4774 case 0:
4775 case UNI_BLLI_L3_IPI_P:
4776 case UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P:
4777 break;
4778 }
4779 break;
4780
4781 case UNI_BLLI_L3_H310:
4782 switch(ie->h.present & mask) {
4783 default:
4784 return -1;
4785
4786 case 0:
4787 case UNI_BLLI_L3_TTYPE_P:
4788 case UNI_BLLI_L3_TTYPE_P|UNI_BLLI_L3_MUX_P:
4789 break;
4790 }
4791 break;
4792
4793 case UNI_BLLI_L3_USER:
4794 switch(ie->h.present & mask) {
4795 default:
4796 return -1;
4797
4798 case 0: /* XXX ? */
4799 case UNI_BLLI_L3_USER_P:
4800 break;
4801 }
4802 break;
4803 }
4804 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4805 switch(ie->l3_mode) {
4806 default:
4807 return -1;
4808
4809 case UNI_BLLI_L3NSEQ:
4810 case UNI_BLLI_L3ESEQ:
4811 break;
4812 }
4813 }
4814 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4815 switch(ie->l3_psiz) {
4816 default:
4817 return -1;
4818
4819 case UNI_BLLI_L3_16:
4820 case UNI_BLLI_L3_32:
4821 case UNI_BLLI_L3_64:
4822 case UNI_BLLI_L3_128:
4823 case UNI_BLLI_L3_256:
4824 case UNI_BLLI_L3_512:
4825 case UNI_BLLI_L3_1024:
4826 case UNI_BLLI_L3_2048:
4827 case UNI_BLLI_L3_4096:
4828 break;
4829 }
4830 }
4831 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4832 if(ie->l3_wsiz == 0 || ie->l3_wsiz > 127)
4833 return -1;
4834 }
4835 if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4836 if(ie->l3_ipi == UNI_BLLI_L3_SNAP) {
4837 if(!(ie->h.present & UNI_BLLI_L3_SNAP_P))
4838 return -1;
4839 } else {
4840 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4841 return -1;
4842 }
4843 }
4844 if(ie->h.present & UNI_BLLI_L3_USER_P) {
4845 if(ie->l3_user > 127)
4846 return -1;
4847 }
4848 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4849 if(ie->oui >= (1<<24))
4850 return -1;
4851 if(ie->pid >= (1<<16))
4852 return -1;
4853 }
4854 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4855 switch(ie->l3_ttype) {
4856 default:
4857 return -1;
4858
4859 case UNI_BLLI_L3_TTYPE_RECV:
4860 case UNI_BLLI_L3_TTYPE_SEND:
4861 case UNI_BLLI_L3_TTYPE_BOTH:
4862 break;
4863 }
4864 switch(ie->l3_tcap) {
4865 default:
4866 return -1;
4867
4868 case UNI_BLLI_L3_TCAP_NOIND:
4869 case UNI_BLLI_L3_TCAP_AAL1:
4870 case UNI_BLLI_L3_TCAP_AAL5:
4871 case UNI_BLLI_L3_TCAP_AAL15:
4872 break;
4873 }
4874 }
4875 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4876 switch(ie->l3_fmux) {
4877 default:
4878 return -1;
4879
4880 case UNI_BLLI_L3_MUX_NOMUX:
4881 case UNI_BLLI_L3_MUX_TS:
4882 case UNI_BLLI_L3_MUX_TSFEC:
4883 case UNI_BLLI_L3_MUX_PS:
4884 case UNI_BLLI_L3_MUX_PSFEC:
4885 case UNI_BLLI_L3_MUX_H221:
4886 break;
4887 }
4888 switch(ie->l3_bmux) {
4889 default:
4890 return -1;
4891
4892 case UNI_BLLI_L3_MUX_NOMUX:
4893 case UNI_BLLI_L3_MUX_TS:
4894 case UNI_BLLI_L3_MUX_TSFEC:
4895 case UNI_BLLI_L3_MUX_PS:
4896 case UNI_BLLI_L3_MUX_PSFEC:
4897 case UNI_BLLI_L3_MUX_H221:
4898 break;
4899 }
4900 }
4901 }
4902
4903 return 0;
4904}
4905
4906DEF_IE_ENCODE(itu, blli)
4907{
4908 START_IE(blli, UNI_IE_BLLI, 13);
4909
4910 if (IE_ISERROR(*ie)) {
4911 APP_BYTE(msg, 0xff);
4912 APP_BYTE(msg, 0xff);
4913 goto out;
4914 }
4915
4916 if(ie->h.present & UNI_BLLI_L1_P)
4917 APP_BYTE(msg, (UNI_BLLI_L1_ID<<5)|ie->l1|0x80);
4918
4919 if(ie->h.present & UNI_BLLI_L2_P) {
4920 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4921 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4922 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4923 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933);
4924 APP_BYTE(msg, ie->l2_wsiz | 0x80);
4925 } else {
4926 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933|0x80);
4927 }
4928 } else if(ie->h.present & UNI_BLLI_L2_USER_P) {
4929 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4930 APP_BYTE(msg, ie->l2_user | 0x80);
4931 } else {
4932 APP_BYTE(msg, (UNI_BLLI_L2_ID << 5) | ie->l2 | 0x80);
4933 }
4934 }
4935
4936 if(ie->h.present & UNI_BLLI_L3_P) {
4937 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4938 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4939 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4940 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4941 APP_BYTE(msg,(ie->l3_mode<<5));
4942 APP_BYTE(msg,ie->l3_psiz);
4943 APP_BYTE(msg,ie->l3_wsiz|0x80);
4944 } else {
4945 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4946 APP_BYTE(msg,(ie->l3_mode<<5));
4947 APP_BYTE(msg,(ie->l3_psiz|0x80));
4948 }
4949 } else {
4950 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4951 APP_BYTE(msg, (ie->l3_mode<<5)|0x80);
4952 }
4953 } else if(ie->h.present & UNI_BLLI_L3_USER_P) {
4954 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4955 APP_BYTE(msg,(ie->l3_user|0x80));
4956 } else if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4957 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4958 APP_BYTE(msg,((ie->l3_ipi>>1) & 0x7f));
4959 APP_BYTE(msg,(((ie->l3_ipi&1)<<6)|0x80));
4960 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4961 APP_BYTE(msg, 0x80);
4962 APP_BYTE(msg, (ie->oui >> 16));
4963 APP_BYTE(msg, (ie->oui >> 8));
4964 APP_BYTE(msg, (ie->oui >> 0));
4965 APP_BYTE(msg, (ie->pid >> 8));
4966 APP_BYTE(msg, (ie->pid >> 0));
4967 }
4968 } else if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4969 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4970 APP_BYTE(msg, ie->l3_ttype | (ie->l3_tcap << 4));
4971 APP_BYTE(msg, 0x80 | (ie->l3_fmux << 3) | ie->l3_bmux);
4972 } else {
4973 APP_BYTE(msg, 0x80 | ie->l3_ttype | (ie->l3_tcap << 4));
4974 }
4975 } else {
4976 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3|0x80);
4977 }
4978 }
4979
4980 out:
4981 SET_IE_LEN(msg);
4982 return 0;
4983}
4984
4985DEF_IE_DECODE(itu, blli)
4986{
4987 u_char c;
4988
4989 IE_START(;);
4990
4991 if(ielen > 17)
4992 goto rej;
4993
4994 while(ielen--) {
4995 switch(((c = *msg->b_rptr++) >> 5) & 0x3) {
4996 default:
4997 goto rej;
4998
4999 case UNI_BLLI_L1_ID:
5000 ie->h.present |= UNI_BLLI_L1_P;
5001 ie->l1 = c & 0x1f;
5002 if(!(c & 0x80))
5003 goto rej;
5004 break;
5005
5006 case UNI_BLLI_L2_ID:
5007 ie->h.present |= UNI_BLLI_L2_P;
5008 ie->l2 = c & 0x1f;
5009 if(!(c & 0x80)) {
5010 if(ielen == 0)
5011 goto rej;
5012 ielen--;
5013 c = *msg->b_rptr++;
5014 if(ie->l2 == UNI_BLLI_L2_USER) {
5015 ie->h.present |= UNI_BLLI_L2_USER_P;
5016 ie->l2_user = c & 0x7f;
5017 if(!(c & 0x80))
5018 goto rej;
5019 } else {
5020 ie->h.present |= UNI_BLLI_L2_Q933_P;
5021 ie->l2_q933 = c & 0x3;
5022 ie->l2_mode = (c >> 5) & 0x3;
5023 if(!(c & 0x80)) {
5024 if(ielen == 0)
5025 goto rej;
5026 ielen--;
5027 c = *msg->b_rptr++;
5028 ie->h.present |= UNI_BLLI_L2_WSIZ_P;
5029 ie->l2_wsiz = c & 0x7f;
5030 if(!(c & 0x80))
5031 goto rej;
5032 }
5033 }
5034 }
5035 break;
5036
5037 case UNI_BLLI_L3_ID:
5038 ie->h.present |= UNI_BLLI_L3_P;
5039 ie->l3 = c & 0x1f;
5040 if(!(c & 0x80)) {
5041 switch(ie->l3) {
5042 default:
5043 case UNI_BLLI_L3_CLMP:
5044 case UNI_BLLI_L3_T70:
5045 goto rej;
5046
5047 case UNI_BLLI_L3_X25:
5048 case UNI_BLLI_L3_ISO8208:
5049 case UNI_BLLI_L3_X223:
5050 if(ielen == 0)
5051 goto rej;
5052 ielen--;
5053 c = *msg->b_rptr++;
5054 ie->l3_mode = (c >> 5) & 0x3;
5055 ie->h.present |= UNI_BLLI_L3_MODE_P;
5056
5057 if(c & 0x80)
5058 break;
5059
5060 if(ielen == 0)
5061 goto rej;
5062 ielen--;
5063 c = *msg->b_rptr++;
5064 ie->l3_psiz = c & 0xf;
5065 ie->h.present |= UNI_BLLI_L3_PSIZ_P;
5066
5067 if(c & 0x80)
5068 break;
5069
5070 if(ielen == 0)
5071 goto rej;
5072 ielen--;
5073 c = *msg->b_rptr++;
5074 ie->l3_wsiz = c & 0x7f;
5075 ie->h.present |= UNI_BLLI_L3_WSIZ_P;
5076
5077 if(!(c & 0x80))
5078 goto rej;
5079 break;
5080
5081 case UNI_BLLI_L3_TR9577:
5082 if(ielen < 2)
5083 goto rej;
5084 ielen -= 2;
5085 c = *msg->b_rptr++;
5086 ie->l3_ipi = (c << 1) & 0xfe;
5087 if(c & 0x80)
5088 goto rej;
5089 c = *msg->b_rptr++;
5090 ie->l3_ipi |= c & 1;
5091 if(!(c & 0x80))
5092 goto rej;
5093 ie->h.present |= UNI_BLLI_L3_IPI_P;
5094
5095 if(ie->l3_ipi != UNI_BLLI_L3_SNAP)
5096 break;
5097 if(ielen < 6)
5098 goto rej;
5099 ielen -= 6;
5100 if(*msg->b_rptr++ != 0x80)
5101 goto rej;
5102 ie->h.present |= UNI_BLLI_L3_SNAP_P;
5103 ie->oui = *msg->b_rptr++ << 16;
5104 ie->oui |= *msg->b_rptr++ << 8;
5105 ie->oui |= *msg->b_rptr++;
5106 ie->pid = *msg->b_rptr++ << 8;
5107 ie->pid |= *msg->b_rptr++;
5108 break;
5109
5110 case UNI_BLLI_L3_H310:
5111 if(ielen == 0)
5112 goto rej;
5113 ielen--;
5114 c = *msg->b_rptr++;
5115 ie->l3_ttype = c & 0xf;
5116 ie->l3_tcap = (c >> 4) & 0x7;
5117 ie->h.present |= UNI_BLLI_L3_TTYPE_P;
5118 if(c & 0x80)
5119 break;
5120 if(ielen == 0)
5121 goto rej;
5122 ielen--;
5123 c = *msg->b_rptr++;
5124 ie->l3_fmux = (c >> 3) & 7;
5125 ie->l3_bmux = c & 7;
5126 ie->h.present |= UNI_BLLI_L3_MUX_P;
5127 if(!(c & 0x80))
5128 goto rej;
5129 break;
5130
5131 case UNI_BLLI_L3_USER:
5132 if(ielen == 0)
5133 goto rej;
5134 ielen--;
5135 c = *msg->b_rptr++;
5136 ie->l3_user = c & 0x7f;
5137 ie->h.present |= UNI_BLLI_L3_USER_P;
5138 if(!(c & 0x80))
5139 goto rej;
5140 break;
5141 }
5142 }
5143 break;
5144 }
5145 }
5146
5147 IE_END(BLLI);
5148}
5149
5150/*********************************************************************
5151 *
5152 * Broadband locking shift
5153 * Broadband non-locking shift.
5154 *
5155 * References for this IE are:
5156 *
5157 * Q.2931 pp. 41...42
5158 * UNI4.0 pp. 9
5159 *
5160 * Procedure not supported in UNI4.0, but IE's must be recognized.
5161 *
5162 * Only ITU-T coding allowed.
5163 */
5164
5165DEF_IE_PRINT(itu, lshift)
5166{
5167 if(uni_print_iehdr("locking_shift", &ie->h, cx))
5168 return;
5169 uni_print_ieend(cx);
5170}
5171
5172DEF_IE_CHECK(itu, lshift)
5173{
5174 cx = cx; ie = ie;
5175 return -1;
5176}
5177
5178DEF_IE_ENCODE(itu, lshift)
5179{
5180 START_IE(lshift, UNI_IE_LSHIFT, 1);
5181 APP_BYTE(msg, 0x80 | ie->set);
5182 SET_IE_LEN(msg);
5183 return 0;
5184}
5185
5186DEF_IE_DECODE(itu, lshift)
5187{
5188 u_char c;
5189
5190 IE_START(;);
5191
5192 if(ielen != 1)
5193 goto rej;
5194
5195 c = *msg->b_rptr++;
5196
5197 if(!(c & 0x80))
5198 goto rej;
5199 ie->set = c & 7;
5200
5201 IE_END(LSHIFT);
5202}
5203
5204/***********************************************************************/
5205
5206DEF_IE_PRINT(itu, nlshift)
5207{
5208 if(uni_print_iehdr("nonlocking_shift", &ie->h, cx))
5209 return;
5210 uni_print_ieend(cx);
5211}
5212
5213DEF_IE_CHECK(itu, nlshift)
5214{
5215 cx = cx; ie = ie;
5216 return -1;
5217}
5218
5219DEF_IE_ENCODE(itu, nlshift)
5220{
5221 START_IE(nlshift, UNI_IE_NLSHIFT, 1);
5222 APP_BYTE(msg, 0x80 | ie->set);
5223 SET_IE_LEN(msg);
5224 return 0;
5225}
5226
5227DEF_IE_DECODE(itu, nlshift)
5228{
5229 u_char c;
5230
5231 IE_START(;);
5232
5233 if(ielen != 1)
5234 goto rej;
5235
5236 c = *msg->b_rptr++;
5237
5238 if(!(c & 0x80))
5239 goto rej;
5240 ie->set = c & 7;
5241
5242 IE_END(NLSHIFT);
5243}
5244
5245/*********************************************************************
5246 *
5247 * Broadband Sending Complete Indicator
5248 *
5249 * References for this IE are:
5250 *
5251 * Q.2931 pp. 74-75
5252 *
5253 * Only ITU-T coding allowed.
5254 */
5255DEF_IE_PRINT(itu, scompl)
5256{
5257 if(uni_print_iehdr("sending_complete", &ie->h, cx))
5258 return;
5259 uni_print_ieend(cx);
5260}
5261
5262DEF_IE_CHECK(itu, scompl)
5263{
5264 ie = ie; cx = cx;
5265 return 0;
5266}
5267
5268DEF_IE_ENCODE(itu, scompl)
5269{
5270 START_IE(scompl, UNI_IE_SCOMPL, 1);
5271
5272 APP_BYTE(msg, 0x80 | 0x21);
5273
5274 SET_IE_LEN(msg);
5275 return 0;
5276}
5277
5278DEF_IE_DECODE(itu, scompl)
5279{
5280 IE_START(;);
5281
5282 if(ielen != 1)
5283 goto rej;
5284
5285 if(*msg->b_rptr++ != (0x80 | 0x21))
5286 goto rej;
5287
5288 IE_END(SCOMPL);
5289}
5290
5291/*********************************************************************
5292 *
5293 * Broadband Repeat Indicator
5294 *
5295 * References for this IE are:
5296 *
5297 * Q.2931 p. 73
5298 * PNNI1.0 p. 196
5299 *
5300 * Q.2931 has table 4-19. Only codepoints 0x2 and 0xa (for PNNI) supported.
5301 *
5302 * Only ITU-T coding allowed.
5303 */
5304DEF_IE_PRINT(itu, repeat)
5305{
5306 static const struct uni_print_tbl tbl[] = {
5307 MKT(UNI_REPEAT_PRIDESC, desc),
5308 MKT(UNI_REPEAT_STACK, stack),
5309 EOT()
5310 };
5311
5312 if(uni_print_iehdr("repeat", &ie->h, cx))
5313 return;
5314 uni_print_tbl("type", ie->type, tbl, cx);
5315 uni_print_ieend(cx);
5316}
5317
5318DEF_IE_CHECK(itu, repeat)
5319{
5320 switch(ie->type) {
5321
5322 case UNI_REPEAT_PRIDESC:
5323 break;
5324
5325 case UNI_REPEAT_STACK:
5326 if(!cx->pnni)
5327 return -1;
5328 break;
5329
5330 default:
5331 return -1;
5332 }
5333 return 0;
5334}
5335
5336DEF_IE_ENCODE(itu, repeat)
5337{
5338 START_IE(repeat, UNI_IE_REPEAT, 1);
5339
5340 APP_BYTE(msg, 0x80 | ie->type);
5341
5342 SET_IE_LEN(msg);
5343 return 0;
5344}
5345
5346DEF_IE_DECODE(itu, repeat)
5347{
5348 u_char c;
5349
5350 IE_START(;);
5351
5352 if(ielen != 1)
5353 goto rej;
5354
5355 c = *msg->b_rptr++;
5356 if(!(c & 0x80))
5357 goto rej;
5358 ie->type = c & 0xf;
5359
5360 IE_END(REPEAT);
5361}
5362
5363/*********************************************************************
5364 *
5365 * Transit Network Selection
5366 *
5367 * References for this IE are:
5368 *
5369 * Q.2931 pp. 75...76
5370 * UNI4.0 pp. 17
5371 *
5372 * According to UNI4.0 this is always National Network Id/Carried Id.
5373 *
5374 * ITU-T/Net coding allowed.
5375 */
5376
5377DEF_IE_PRINT(itu, tns)
5378{
5379 u_int i;
5380
5381 if(uni_print_iehdr("tns", &ie->h, cx))
5382 return;
5383 uni_print_entry(cx, "net", "%u,\"", ie->len);
5384 uni_putc('"', cx);
5385 for(i = 0; i < ie->len; i++) {
5386 if(ie->net[i] < ' ')
5387 uni_printf(cx, "^%c", ie->net[i] + '@');
5388 else if(ie->net[i] < '~')
5389 uni_putc(ie->net[i], cx);
5390 else
5391 uni_printf(cx, "\\%03o", ie->net[i]);
5392 }
5393 uni_putc('"', cx);
5394 uni_print_ieend(cx);
5395}
5396
5397DEF_IE_CHECK(itu, tns)
5398{
5399 u_int i;
5400
5401 cx = cx;
5402
5403 if(ie->len == 0 || ie->len > UNI_TNS_MAXLEN)
5404 return -1;
5405 for(i = 0; i < ie->len; i++)
5406 if(ie->net[i] < ' ' || ie->net[i] > '~')
5407 return -1;
5408 return 0;
5409}
5410
5411DEF_IE_ENCODE(itu, tns)
5412{
5413 START_IE(tns, UNI_IE_TNS, ie->len + 1);
5414
5415 APP_BYTE(msg, 0x80 | (0x2 << 4) | 0x1);
5416 APP_BUF(msg, ie->net, ie->len);
5417
5418 SET_IE_LEN(msg);
5419 return 0;
5420}
5421
5422DEF_IE_DECODE(itu, tns)
5423{
5424 IE_START(;);
5425
5426 if(ielen < 2 || ielen > 5)
5427 goto rej;
5428
5429 if(*msg->b_rptr++ != (0x80 | (0x2 << 4) | 0x1))
5430 goto rej;
5431 ielen--;
5432
5433 ie->len = 0;
5434 while(ielen--)
5435 ie->net[ie->len++] = *msg->b_rptr++;
5436
5437 IE_END(TNS);
5438}
5439
5440/*********************************************************************
5441 *
5442 * Restart indicator
5443 *
5444 * References for this IE are:
5445 *
5446 * Q.2931 pp. 73...74
5447 * UNI4.0 p. 17
5448 *
5449 * Only ITU-T coding allowed.
5450 */
5451
5452DEF_IE_PRINT(itu, restart)
5453{
5454 static const struct uni_print_tbl tbl[] = {
5455 MKT(UNI_RESTART_CHANNEL, channel),
5456 MKT(UNI_RESTART_PATH, path),
5457 MKT(UNI_RESTART_ALL, all),
5458 EOT()
5459 };
5460
5461 if(uni_print_iehdr("restart", &ie->h, cx))
5462 return;
5463 uni_print_tbl("class", ie->rclass, tbl, cx);
5464 uni_print_ieend(cx);
5465}
5466
5467DEF_IE_CHECK(itu, restart)
5468{
5469 cx = cx;
5470
5471 switch(ie->rclass) {
5472 default:
5473 return -1;
5474
5475 case UNI_RESTART_CHANNEL:
5476 case UNI_RESTART_PATH:
5477 case UNI_RESTART_ALL:
5478 break;
5479 }
5480
5481 return 0;
5482}
5483
5484DEF_IE_ENCODE(itu, restart)
5485{
5486 START_IE(restart, UNI_IE_RESTART, 1);
5487
5488 APP_BYTE(msg, 0x80 | ie->rclass);
5489
5490 SET_IE_LEN(msg);
5491 return 0;
5492}
5493
5494DEF_IE_DECODE(itu, restart)
5495{
5496 u_char c;
5497
5498 IE_START(;);
5499
5500 if(ielen != 1)
5501 goto rej;
5502
5503 ie->rclass = (c = *msg->b_rptr++) & 0x7;
5504
5505 if(!(c & 0x80))
5506 goto rej;
5507
5508 IE_END(RESTART);
5509}
5510
5511/*********************************************************************
5512 *
5513 * User-to-user info.
5514 *
5515 * References for this IE are:
5516 *
5517 * Q.2957
5518 *
5519 * Only ITU-T coding allowed.
5520 */
5521
5522DEF_IE_PRINT(itu, uu)
5523{
5524 u_int i;
5525
5526 if(uni_print_iehdr("uu", &ie->h, cx))
5527 return;
5528 uni_print_entry(cx, "len", "%u", ie->len);
5529 uni_print_entry(cx, "info", "(");
5530 for(i = 0; i < ie->len; i++)
5531 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->uu[i]);
5532 uni_printf(cx, ")");
5533 uni_print_ieend(cx);
5534}
5535
5536DEF_IE_CHECK(itu, uu)
5537{
5538 cx = cx;
5539
5540 if(ie->len > UNI_UU_MAXLEN)
5541 return -1;
5542
5543 return 0;
5544}
5545
5546DEF_IE_ENCODE(itu, uu)
5547{
5548 START_IE(uu, UNI_IE_UU, ie->len);
5549
5550 APP_BUF(msg, ie->uu, ie->len);
5551
5552 SET_IE_LEN(msg);
5553 return 0;
5554}
5555
5556DEF_IE_DECODE(itu, uu)
5557{
5558 IE_START(;);
5559
5560 if(ielen > UNI_UU_MAXLEN || ielen < 1)
5561 goto rej;
5562
5563 ie->len = ielen;
5564 ielen = 0;
5565 (void)memcpy(ie->uu, msg->b_rptr, ie->len);
5566 msg->b_rptr += ie->len;
5567
5568 IE_END(UU);
5569}
5570
5571/*********************************************************************
5572 *
5573 * Generic Identifier Transport
5574 *
5575 * References for this IE are:
5576 *
5577 * UNI4.0 pp. 26...28
5578 *
5579 * UNI4.0 prescribes a fixed format for this IE. We have a flag in the
5580 * context structur, which tells us whether the check of this IE should be
5581 * hard or soft. Probably it should be hard for end systems and soft for
5582 * network nodes.
5583 *
5584 * Only Net Coding allowed. (XXX)
5585 */
5586
5587DEF_IE_PRINT(net, git)
5588{
5589 static const struct uni_print_tbl std_tbl[] = {
5590 MKT(UNI_GIT_STD_DSMCC, dsmcc),
5591 MKT(UNI_GIT_STD_H245, H.245),
5592 EOT()
5593 };
5594 static const struct uni_print_tbl type_tbl[] = {
5595 MKT(UNI_GIT_TYPE_SESS, sess),
5596 MKT(UNI_GIT_TYPE_RES, res),
5597 EOT()
5598 };
5599 u_int i, j;
5600 char buf[20];
5601
5602 if(uni_print_iehdr("git", &ie->h, cx))
5603 return;
5604
5605 uni_print_tbl("std", ie->std, std_tbl, cx);
5606
5607 uni_print_eol(cx);
5608 uni_print_push_prefix("id", cx);
5609 cx->indent++;
5610 for(i = 0; i < ie->numsub; i++) {
5611 sprintf(buf, "%u", i);
5612 uni_print_entry(cx, buf, "(");
5613 uni_print_tbl(NULL, ie->sub[i].type, type_tbl, cx);
5614 for(j = 0; j < ie->sub[i].len; j++)
5615 uni_printf(cx, ",0x%02x", ie->sub[i].val[j]);
5616 uni_printf(cx, ")");
5617 uni_print_eol(cx);
5618 }
5619 cx->indent--;
5620 uni_print_pop_prefix(cx);
5621
5622 uni_print_ieend(cx);
5623}
5624
5625DEF_IE_CHECK(net, git)
5626{
5627 u_int i;
5628
5629 if(cx->git_hard) {
5630 switch(ie->std) {
5631 case UNI_GIT_STD_DSMCC:
5632 case UNI_GIT_STD_H245:
5633 break;
5634 default:
5635 return -1;
5636 }
5637 if(ie->numsub != 2)
5638 return -1;
5639 if(ie->sub[0].type != UNI_GIT_TYPE_SESS)
5640 return -1;
5641 if(ie->sub[0].len > UNI_GIT_MAXSESS)
5642 return -1;
5643 if(ie->sub[1].type != UNI_GIT_TYPE_RES)
5644 return -1;
5645 if(ie->sub[1].len > UNI_GIT_MAXRES)
5646 return -1;
5647 } else {
5648 if(ie->numsub > UNI_GIT_MAXSUB)
5649 return -1;
5650 for(i = 0; i < ie->numsub; i++)
5651 if(ie->sub[i].len > UNI_GIT_MAXVAL)
5652 return -1;
5653 }
5654 return 0;
5655}
5656
5657DEF_IE_ENCODE(net, git)
5658{
5659 u_int i;
5660
5661 START_IE(git, UNI_IE_GIT, 1 + ie->numsub * (1 + UNI_GIT_MAXVAL));
5662
5663 APP_BYTE(msg, ie->std);
5664 for(i = 0; i < ie->numsub; i++) {
5665 APP_BYTE(msg, ie->sub[i].type);
5666 APP_BYTE(msg, ie->sub[i].len);
5667 APP_BUF(msg, ie->sub[i].val, ie->sub[i].len);
5668 }
5669
5670 SET_IE_LEN(msg);
5671 return 0;
5672}
5673
5674DEF_IE_DECODE(net, git)
5675{
5676 IE_START(;);
5677
5678 if(ielen > 1 + UNI_GIT_MAXSUB * (1 + UNI_GIT_MAXVAL) || ielen < 1)
5679 goto rej;
5680
5681 ie->std = *msg->b_rptr++;
5682 ielen--;
5683
5684 ie->numsub = 0;
5685 while(ielen > 0) {
5686 if(ie->numsub >= UNI_GIT_MAXSUB)
5687 goto rej;
5688
5689 ie->sub[ie->numsub].type = *msg->b_rptr++;
5690 ielen--;
5691
5692 if(ielen == 0)
5693 goto rej;
5694 ie->sub[ie->numsub].len = *msg->b_rptr++;
5695 ielen--;
5696
5697 if(ie->sub[ie->numsub].len > UNI_GIT_MAXVAL)
5698 goto rej;
5699 if(ie->sub[ie->numsub].len > (u_int)ielen)
5700 goto rej;
5701
5702 (void)memcpy(ie->sub[ie->numsub].val, msg->b_rptr, ie->sub[ie->numsub].len);
5703 ielen -= ie->sub[ie->numsub].len;
5704 msg->b_rptr += ie->sub[ie->numsub].len;
5705
5706 ie->numsub++;
5707 }
5708
5709 IE_END(GIT);
5710}
5711
5712/*********************************************************************
5713 *
5714 * Additional ABR Parameters
5715 * ABR Setup parameters
5716 *
5717 * References for this IE are:
5718 *
5719 * UNI4.0 pp. 78...82
5720 * PNNI1.0 p. 195
5721 *
5722 * Notes:
5723 * Only NET coding.
5724 */
5725
5726static void
5727print_abr_rec(struct unicx *cx, struct uni_abr_rec *rec)
5728{
5729 if(rec->present & UNI_ABR_REC_NRM_P)
5730 uni_print_entry(cx, "nrm", "%d", rec->nrm);
5731 if(rec->present & UNI_ABR_REC_TRM_P)
5732 uni_print_entry(cx, "trm", "%d", rec->trm);
5733 if(rec->present & UNI_ABR_REC_CDF_P)
5734 uni_print_entry(cx, "cdf", "%d", rec->cdf);
5735 if(rec->present & UNI_ABR_REC_ADTF_P)
5736 uni_print_entry(cx, "adtf", "%d", rec->adtf);
5737}
5738
5739DEF_IE_PRINT(net, abradd)
5740{
5741 if(uni_print_iehdr("abradd", &ie->h, cx))
5742 return;
5743
5744 uni_print_push_prefix("fwd", cx);
5745 print_abr_rec(cx, &ie->fwd);
5746 uni_print_pop_prefix(cx);
5747
5748 uni_print_push_prefix("bwd", cx);
5749 print_abr_rec(cx, &ie->bwd);
5750 uni_print_pop_prefix(cx);
5751
5752 uni_print_ieend(cx);
5753}
5754
5755DEF_IE_CHECK(net, abradd)
5756{
5757 cx = cx;
5758 ie = ie;
5759
5760 return 0;
5761}
5762
5763static u_int
5764encode_abr_rec(struct uni_abr_rec *rec)
5765{
5766 u_int ret = rec->present & 0xf000;
5767
5768 if(ret & UNI_ABR_REC_NRM_P)
5769 ret |= (rec->nrm & 0x7) << 25;
5770 if(ret & UNI_ABR_REC_TRM_P)
5771 ret |= (rec->trm & 0x7) << 22;
5772 if(ret & UNI_ABR_REC_CDF_P)
5773 ret |= (rec->cdf & 0x7) << 19;
5774 if(ret & UNI_ABR_REC_ADTF_P)
5775 ret |= (rec->adtf & 0x3ff) << 9;
5776
5777 return ret;
5778}
5779
5780DEF_IE_ENCODE(net, abradd)
5781{
5782 START_IE(abradd, UNI_IE_ABRADD, 10);
5783
5784 APP_SUB_32BIT(msg, UNI_ABRADD_FADD_ID, encode_abr_rec(&ie->fwd));
5785 APP_SUB_32BIT(msg, UNI_ABRADD_BADD_ID, encode_abr_rec(&ie->bwd));
5786
5787 SET_IE_LEN(msg);
5788 return 0;
5789}
5790
5791static int
5792decode_abr_rec(struct uni_msg *msg, struct uni_abr_rec *rec)
5793{
5794 u_int val;
5795
5796 val = *msg->b_rptr++ << 24;
5797 val |= *msg->b_rptr++ << 16;
5798 val |= *msg->b_rptr++ << 8;
5799 val |= *msg->b_rptr++ << 0;
5800
5801 rec->present = val & 0xf000;
5802
5803 rec->nrm = (val & UNI_ABR_REC_NRM_P) ? ((val >> 25) & 0x7) : 0;
5804 rec->trm = (val & UNI_ABR_REC_TRM_P) ? ((val >> 22) & 0x7) : 0;
5805 rec->cdf = (val & UNI_ABR_REC_CDF_P) ? ((val >> 19) & 0x7) : 0;
5806 rec->adtf = (val & UNI_ABR_REC_ADTF_P)? ((val >> 9) & 0x3ff) : 0;
5807
5808 return 0;
5809}
5810
5811DEF_IE_DECODE(net, abradd)
5812{
5813 IE_START(;);
5814
5815 if(ielen != 10)
5816 goto rej;
5817
5818
5819 while(ielen--) {
5820 switch(*msg->b_rptr++) {
5821
5822 default:
5823 goto rej;
5824
5825 case UNI_ABRADD_FADD_ID:
5826 if(decode_abr_rec(msg, &ie->fwd))
5827 goto rej;
5828 ielen -= 4;
5829 break;
5830
5831 case UNI_ABRADD_BADD_ID:
5832 if(decode_abr_rec(msg, &ie->bwd))
5833 goto rej;
5834 ielen -= 4;
5835 break;
5836 }
5837 }
5838 IE_END(ABRADD);
5839}
5840
5841/*********************************************************************/
5842
5843DEF_IE_PRINT(net, abrsetup)
5844{
5845 if(uni_print_iehdr("abrsetup", &ie->h, cx))
5846 return;
5847
5848 uni_print_entry(cx, "rm_frt", "%d", ie->rmfrt);
5849
5850 uni_print_push_prefix("fwd", cx);
5851 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5852 uni_print_entry(cx, "icr", "%d", ie->ficr);
5853 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5854 uni_print_entry(cx, "tbe", "%d", ie->ftbe);
5855 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5856 uni_print_entry(cx, "rif", "%d", ie->frif);
5857 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5858 uni_print_entry(cx, "rdf", "%d", ie->frdf);
5859 uni_print_pop_prefix(cx);
5860
5861 uni_print_push_prefix("bwd", cx);
5862 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5863 uni_print_entry(cx, "icr", "%d", ie->bicr);
5864 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5865 uni_print_entry(cx, "tbe", "%d", ie->btbe);
5866 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5867 uni_print_entry(cx, "rif", "%d", ie->brif);
5868 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5869 uni_print_entry(cx, "rdf", "%d", ie->brdf);
5870 uni_print_pop_prefix(cx);
5871
5872 uni_print_ieend(cx);
5873}
5874
5875DEF_IE_CHECK(net, abrsetup)
5876{
5877 if(cx->pnni) {
5878 if(!(ie->h.present & UNI_ABRSETUP_FICR_P))
5879 return -1;
5880 if(!(ie->h.present & UNI_ABRSETUP_BICR_P))
5881 return -1;
5882 if(!(ie->h.present & UNI_ABRSETUP_FTBE_P))
5883 return -1;
5884 if(!(ie->h.present & UNI_ABRSETUP_BTBE_P))
5885 return -1;
5886 if(!(ie->h.present & UNI_ABRSETUP_FRIF_P))
5887 return -1;
5888 if(!(ie->h.present & UNI_ABRSETUP_BRIF_P))
5889 return -1;
5890 if(!(ie->h.present & UNI_ABRSETUP_FRDF_P))
5891 return -1;
5892 if(!(ie->h.present & UNI_ABRSETUP_BRDF_P))
5893 return -1;
5894 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5895 return -1;
5896 }
5897
5898 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5899 return -1;
5900
5901 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5902 if(ie->ficr >= 1 << 24)
5903 return -1;
5904 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5905 if(ie->bicr >= 1 << 24)
5906 return -1;
5907
5908 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5909 if(ie->ftbe >= 1 << 24 || ie->ftbe == 0)
5910 return -1;
5911 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5912 if(ie->btbe >= 1 << 24 || ie->btbe == 0)
5913 return -1;
5914
5915 if(ie->rmfrt >= 1 << 24)
5916 return -1;
5917
5918 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5919 if(ie->frif > 15)
5920 return -1;
5921 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5922 if(ie->frdf > 15)
5923 return -1;
5924 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5925 if(ie->brif > 15)
5926 return -1;
5927 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5928 if(ie->brdf > 15)
5929 return -1;
5930 return 0;
5931}
5932
5933DEF_IE_ENCODE(net, abrsetup)
5934{
5935 START_IE(abrsetup, UNI_IE_ABRSETUP, 32);
5936
5937 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FICR_P,
5938 UNI_ABRSETUP_FICR_ID, ie->ficr);
5939 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BICR_P,
5940 UNI_ABRSETUP_BICR_ID, ie->bicr);
5941 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FTBE_P,
5942 UNI_ABRSETUP_FTBE_ID, ie->ftbe);
5943 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BTBE_P,
5944 UNI_ABRSETUP_BTBE_ID, ie->btbe);
5945 APP_SUB_24BIT(msg, UNI_ABRSETUP_RMFRT_ID, ie->rmfrt);
5946 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRIF_P,
5947 UNI_ABRSETUP_FRIF_ID, ie->frif);
5948 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRIF_P,
5949 UNI_ABRSETUP_BRIF_ID, ie->brif);
5950 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRDF_P,
5951 UNI_ABRSETUP_FRDF_ID, ie->frdf);
5952 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRDF_P,
5953 UNI_ABRSETUP_BRDF_ID, ie->brdf);
5954
5955 SET_IE_LEN(msg);
5956 return 0;
5957}
5958
5959DEF_IE_DECODE(net, abrsetup)
5960{
5961 IE_START(;);
5962
5963 if(ielen < 4 || ielen > 32)
5964 goto rej;
5965
5966
5967 while(ielen--) {
5968 switch(*msg->b_rptr++) {
5969
5970 default:
5971 goto rej;
5972
5973
5974 DEC_GETF3(ABRSETUP_FICR, ficr, ie->h.present);
5975 DEC_GETF3(ABRSETUP_BICR, bicr, ie->h.present);
5976 DEC_GETF3(ABRSETUP_FTBE, ftbe, ie->h.present);
5977 DEC_GETF3(ABRSETUP_BTBE, btbe, ie->h.present);
5978 DEC_GETF1(ABRSETUP_FRIF, frif, ie->h.present);
5979 DEC_GETF1(ABRSETUP_BRIF, brif, ie->h.present);
5980 DEC_GETF1(ABRSETUP_FRDF, frdf, ie->h.present);
5981 DEC_GETF1(ABRSETUP_BRDF, brdf, ie->h.present);
5982 DEC_GETF3(ABRSETUP_RMFRT, frif, ie->h.present);
5983 }
5984 }
5985 IE_END(ABRSETUP);
5986}
5987
5988/*********************************************************************
5989 *
5990 * Broadband report type
5991 *
5992 * References for this IE are:
5993 *
5994 * Q.2963.1 pp. 7...8
5995 *
5996 * Only ITU-T coding allowed.
5997 */
5998
5999DEF_IE_PRINT(itu, report)
6000{
6001 static const struct uni_print_tbl tbl[] = {
6002 MKT(UNI_REPORT_MODCONF, modconf),
6003 MKT(UNI_REPORT_CLOCK, clock),
6004 MKT(UNI_REPORT_EEAVAIL, eeavail),
6005 MKT(UNI_REPORT_EEREQ, eereq),
6006 MKT(UNI_REPORT_EECOMPL, eecompl),
6007 EOT()
6008 };
6009
6010 if(uni_print_iehdr("report", &ie->h, cx))
6011 return;
6012 uni_print_tbl("type", ie->report, tbl, cx);
6013 uni_print_ieend(cx);
6014}
6015
6016DEF_IE_CHECK(itu, report)
6017{
6018 cx = cx;
6019
6020 switch(ie->report) {
6021
6022 default:
6023 return -1;
6024
6025 case UNI_REPORT_MODCONF:
6026 case UNI_REPORT_CLOCK:
6027 case UNI_REPORT_EEAVAIL:
6028 case UNI_REPORT_EEREQ:
6029 case UNI_REPORT_EECOMPL:
6030 break;
6031 }
6032 return 0;
6033}
6034
6035DEF_IE_ENCODE(itu, report)
6036{
6037 START_IE(report, UNI_IE_REPORT, 1);
6038
6039 APP_BYTE(msg, ie->report);
6040
6041 SET_IE_LEN(msg);
6042 return 0;
6043}
6044
6045DEF_IE_DECODE(itu, report)
6046{
6047 IE_START(;);
6048 if(ielen != 1)
6049 goto rej;
6050
6051 ie->report = *msg->b_rptr++;
6052
6053 IE_END(REPORT);
6054}
6055
6056/*********************************************************************
6057 *
6058 * Soft PVPC/PVCC
6059 *
6060 * References for this IE are:
6061 *
6062 * PNNI1.0 pp. 201...203
6063 *
6064 * Only NET coding allowed.
6065 */
6066DEF_IE_PRINT(net, calling_soft)
6067{
6068 if(uni_print_iehdr("calling_soft", &ie->h, cx))
6069 return;
6070
6071 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6072 if(ie->h.present & UNI_CALLING_SOFT_VCI_P)
6073 uni_print_entry(cx, "vci", "%d", ie->vci);
6074
6075 uni_print_ieend(cx);
6076}
6077
6078DEF_IE_PRINT(net, called_soft)
6079{
6080 static const struct uni_print_tbl tab[] = {
6081 MKT(UNI_SOFT_SEL_ANY, any),
6082 MKT(UNI_SOFT_SEL_REQ, required),
6083 MKT(UNI_SOFT_SEL_ASS, assigned),
6084 EOT()
6085 };
6086
6087 if(uni_print_iehdr("called_soft", &ie->h, cx))
6088 return;
6089
6090 uni_print_tbl("selection", ie->sel, tab, cx);
6091 if(ie->h.present & UNI_CALLED_SOFT_VPI_P)
6092 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6093 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6094 uni_print_entry(cx, "vci", "%d", ie->vci);
6095
6096 uni_print_ieend(cx);
6097}
6098
6099DEF_IE_CHECK(net, calling_soft)
6100{
6101 cx = cx;
6102
6103 if(ie->vpi >= 1 << 12)
6104 return -1;
6105 return 0;
6106}
6107
6108DEF_IE_CHECK(net, called_soft)
6109{
6110 cx = cx;
6111
6112 switch(ie->sel) {
6113
6114 case UNI_SOFT_SEL_ANY:
6115 case UNI_SOFT_SEL_REQ:
6116 case UNI_SOFT_SEL_ASS:
6117 break;
6118
6119 default:
6120 return -1;
6121 }
6122 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6123 if(ie->vpi >= 1 << 12)
6124 return -1;
6125 } else {
6126 if(ie->sel != UNI_SOFT_SEL_ANY)
6127 return -1;
6128 }
6129
6130 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6131 if(!(ie->h.present & UNI_CALLED_SOFT_VPI_P))
6132 return -1;
6133
6134
6135 return 0;
6136}
6137
6138DEF_IE_ENCODE(net, calling_soft)
6139{
6140 START_IE(calling_soft, UNI_IE_CALLING_SOFT, 6);
6141
6142 APP_BYTE(msg, 0x81);
6143 APP_16BIT(msg, ie->vpi);
6144
6145 if(ie->h.present & UNI_CALLING_SOFT_VCI_P) {
6146 APP_BYTE(msg, 0x82);
6147 APP_16BIT(msg, ie->vci);
6148 }
6149
6150 SET_IE_LEN(msg);
6151 return 0;
6152}
6153
6154DEF_IE_ENCODE(net, called_soft)
6155{
6156 START_IE(called_soft, UNI_IE_CALLED_SOFT, 7);
6157
6158 APP_BYTE(msg, ie->sel);
6159
6160 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6161 APP_BYTE(msg, 0x81);
6162 APP_16BIT(msg, ie->vpi);
6163 }
6164
6165 if(ie->h.present & UNI_CALLED_SOFT_VCI_P) {
6166 APP_BYTE(msg, 0x82);
6167 APP_16BIT(msg, ie->vci);
6168 }
6169
6170 SET_IE_LEN(msg);
6171 return 0;
6172}
6173
6174DEF_IE_DECODE(net, calling_soft)
6175{
6176 int vci_seen, vpi_seen;
6177
6178 IE_START(;);
6179 if(ielen < 3)
6180 goto rej;
6181
6182 vci_seen = 0;
6183 vpi_seen = 0;
6184
6185 while(ielen) {
6186 switch(*msg->b_rptr++) {
6187
6188 case 0x81:
6189 if(!vpi_seen) {
6190 ie->vpi = *msg->b_rptr++ << 8;
6191 ie->vpi |= *msg->b_rptr++;
6192 } else {
6193 msg->b_rptr += 2;
6194 }
6195 ielen -= 3;
6196 break;
6197
6198 case 0x82:
6199 if(!vci_seen) {
6200 ie->vci = *msg->b_rptr++ << 8;
6201 ie->vci |= *msg->b_rptr++;
6202 } else {
6203 msg->b_rptr += 2;
6204 }
6205 ie->h.present |= UNI_CALLING_SOFT_VCI_P;
6206 ielen -= 3;
6207 break;
6208
6209 default:
6210 goto rej;
6211 }
6212 }
6213
6214 if(!vpi_seen)
6215 goto rej;
6216
6217 IE_END(CALLING_SOFT);
6218}
6219
6220DEF_IE_DECODE(net, called_soft)
6221{
6222 int vci_seen, vpi_seen;
6223
6224 IE_START(;);
6225 if(ielen < 3)
6226 goto rej;
6227
6228 vci_seen = 0;
6229 vpi_seen = 0;
6230
6231 while(ielen) {
6232 switch(*msg->b_rptr++) {
6233
6234 case 0x81:
6235 if(!vpi_seen) {
6236 ie->vpi = *msg->b_rptr++ << 8;
6237 ie->vpi |= *msg->b_rptr++;
30 *
31 * Private definitions for the IE code file.
32 *
33 * This file includes the table generated automatically.
34 */
35
36#include <sys/types.h>
37#include <sys/param.h>
38
39#ifdef _KERNEL
40#include <sys/libkern.h>
41#else
42#include <string.h>
43#endif
44#include <netnatm/unimsg.h>
45#include <netnatm/msg/unistruct.h>
46#include <netnatm/msg/unimsglib.h>
47#include <netnatm/msg/uniprint.h>
48#include <netnatm/msg/priv.h>
49
50/*
51 * Define internal functions.
52 */
53#define DEF_IE_PRINT(Coding, IE) \
54 void uni_ie_print_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
55
56#define DEF_IE_CHECK(Coding, IE) \
57 int uni_ie_check_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
58
59#define DEF_IE_ENCODE(Coding, IE) \
60 int uni_ie_encode_##Coding##_##IE(struct uni_msg *msg, struct uni_ie_##IE *ie, struct unicx *cx)
61
62#define DEF_IE_DECODE(Coding, IE) \
63 int uni_ie_decode_##Coding##_##IE(struct uni_ie_##IE *ie, struct uni_msg *msg, u_int ielen, struct unicx *cx)
64
65/*
66 * This structure is used to define value->string mappings. MKT() is used
67 * to generate a table entry. EOT() to end the table.
68 */
69#define MKT(V,N) { #N, V }
70#define EOT() { NULL, 0 }
71
72/* library internal functions */
73static void uni_entry(const char *, struct unicx *);
74static int uni_print_iehdr(const char *, struct uni_iehdr *h, struct unicx *);
75static void uni_print_ieend(struct unicx *);
76static void uni_putc(int, struct unicx *);
77
78
79/*
80 * Encoding
81 */
82#define APP_BYTE(M, B) do { \
83 *(M)->b_wptr++ = (B); \
84 } while (0)
85#define APP_16BIT(M, B) do { \
86 u_int _v = (B); \
87 *(M)->b_wptr++ = _v >> 8; \
88 *(M)->b_wptr++ = _v; \
89 } while (0)
90#define APP_24BIT(M, B) do { \
91 u_int _v = (B); \
92 *(M)->b_wptr++ = _v >> 16; \
93 *(M)->b_wptr++ = _v >> 8; \
94 *(M)->b_wptr++ = _v; \
95 } while (0)
96#define APP_32BIT(M, B) do { \
97 u_int _v = (B); \
98 *(M)->b_wptr++ = _v >> 24; \
99 *(M)->b_wptr++ = _v >> 16; \
100 *(M)->b_wptr++ = _v >> 8; \
101 *(M)->b_wptr++ = _v; \
102 } while (0)
103#define APP_BUF(M, B, L) do { \
104 (void)memcpy((M)->b_wptr, (B), (L)); \
105 (M)->b_wptr += (L); \
106 } while (0)
107
108#define APP_SUB_BYTE(M, T, B) do { APP_BYTE(M, T); APP_BYTE(M, B); } while (0)
109#define APP_SUB_16BIT(M, T, B) do { APP_BYTE(M, T); APP_16BIT(M, B); } while (0)
110#define APP_SUB_24BIT(M, T, B) do { APP_BYTE(M, T); APP_24BIT(M, B); } while (0)
111#define APP_SUB_32BIT(M, T, B) do { APP_BYTE(M, T); APP_32BIT(M, B); } while (0)
112
113#define APP_OPT(M, F, P, T) do { \
114 if ((F) & (P)) \
115 APP_BYTE((M), (T)); \
116 } while (0)
117#define APP_OPT_BYTE(M, F, P, T, B) do { \
118 if ((F) & (P)) \
119 APP_SUB_BYTE((M), (T), (B)); \
120 } while (0)
121#define APP_OPT_16BIT(M, F, P, T, B) do { \
122 if ((F) & (P)) \
123 APP_SUB_16BIT((M), (T), (B)); \
124 } while (0)
125#define APP_OPT_24BIT(M, F, P, T, B) do { \
126 if ((F) & (P)) \
127 APP_SUB_24BIT((M), (T), (B)); \
128 } while (0)
129
130#define START_IE(TYPE,CODE,LEN) \
131 u_int ielen; \
132 \
133 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
134 return (-1); \
135 if (uni_encode_ie_hdr(msg, CODE, &ie->h, (LEN), cx)) \
136 return (0); \
137 \
138 ielen = msg->b_wptr - msg->b_rptr - 2;
139
140#define START_IE2(TYPE,CODE,LEN,REALCODE) \
141 u_int ielen; \
142 \
143 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
144 return (-1); \
145 if (uni_encode_ie_hdr(msg, REALCODE, &ie->h, (LEN), cx)) \
146 return (0); \
147 \
148 ielen = msg->b_wptr - msg->b_rptr - 2;
149
150#define SET_IE_LEN(M) do { \
151 (M)->b_buf[ielen + 0] = \
152 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 8; \
153 (M)->b_buf[ielen + 1] = \
154 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 0; \
155 } while (0)
156
157
158/***********************************************************************/
159/*
160 * Decoding
161 */
162#define IE_START(ERR) \
163 if (IE_ISPRESENT(*ie)) \
164 return (0); \
165 if (ielen == 0) { \
166 IE_SETEMPTY(*ie); \
167 return (0); \
168 }
169
170#define IE_END(IE) \
171 IE_SETPRESENT(*ie); \
172 if (uni_check_ie(UNI_IE_##IE, (union uni_ieall *)ie, cx) == 0) \
173 return (0); \
174 rej: \
175 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT; \
176 return (1);
177
178#define DEC_GETF3(ID, F, P) \
179 case UNI_##ID##_ID: \
180 if (ielen < 3) \
181 goto rej; \
182 ielen -= 3; \
183 if (!(P & UNI_##ID##_P)) { \
184 P |= UNI_##ID##_P; \
185 ie->F = *msg->b_rptr++ << 16; \
186 ie->F |= *msg->b_rptr++ << 8; \
187 ie->F |= *msg->b_rptr++; \
188 } else \
189 msg->b_rptr += 3; \
190 break;
191
192#define DEC_GETF1(ID, F, P) \
193 case UNI_##ID##_ID: \
194 if (ielen < 1) \
195 goto rej; \
196 ielen--; \
197 if (!(P & UNI_##ID##_P)) { \
198 P |= UNI_##ID##_P; \
199 ie->F = *msg->b_rptr++; \
200 } else \
201 msg->b_rptr++; \
202 break;
203
204
205#define PRINT_NPREFIX (sizeof(((struct unicx *)0)->prefix) / \
206 sizeof(((struct unicx *)0)->prefix[0]))
207
208/*
209 * This is rather here than in privmsg.c because we need the APP macros.
210 */
211int
212uni_encode_msg_hdr(struct uni_msg *msg, struct uni_msghdr *h,
213 enum uni_msgtype type, struct unicx *cx, int *mlen)
214{
215 u_char byte;
216
217 uni_msg_ensure(msg, 9);
218
219 APP_BYTE(msg, cx->pnni ? PNNI_PROTO : UNI_PROTO);
220 APP_BYTE(msg, 3);
221 if(h->cref.cref >= 1<<23)
222 return -1;
223 APP_24BIT(msg, h->cref.cref | (h->cref.flag ? 0x800000 : 0));
224 APP_BYTE(msg, type);
225
226 byte = 0x80;
227 if(h->act != UNI_MSGACT_DEFAULT)
228 byte |= 0x10 | (h->act & 3);
229 if(cx->pnni && h->pass)
230 byte |= 0x08;
231 APP_BYTE(msg, byte);
232
233 *mlen = msg->b_wptr - msg->b_rptr;
234 APP_16BIT(msg, 0);
235
236 return 0;
237}
238
239/*
240 * Initialize printing. This must be called by all printing routines
241 * that are exported to the user.
242 */
243void
244uni_print_init(char *buf, size_t bufsiz, struct unicx *cx)
245{
246 if (cx->dont_init)
247 return;
248
249 cx->indent = 0;
250 cx->nprefix = 0;
251 cx->doindent = 0;
252 if (cx->tabsiz == 0)
253 cx->tabsiz = 4;
254 cx->buf = buf;
255 cx->bufsiz = bufsiz;
256}
257
258/*
259 * Append a character to the buffer if there is still space
260 */
261static void
262uni_putc(int c, struct unicx *cx)
263{
264 if(cx->bufsiz > 1) {
265 *cx->buf++ = c;
266 cx->bufsiz--;
267 *cx->buf = '\0';
268 }
269}
270
271void
272uni_printf(struct unicx *cx, const char *fmt, ...)
273{
274 u_int n;
275 va_list ap;
276
277 if(cx->bufsiz > 1) {
278 va_start(ap, fmt);
279 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
280 va_end(ap);
281 if(n > 0) {
282 if(n < cx->bufsiz) {
283 cx->bufsiz -= n;
284 cx->buf += n;
285 } else {
286 cx->buf += cx->bufsiz - 1;
287 cx->bufsiz = 1;
288 }
289 }
290 *cx->buf = '\0';
291 }
292}
293
294/*
295 * Print mode:
296 * 0 - print all into one line, fully prefixed
297 * 1 - print on multiple lines, full prefixed, but equal level
298 * entries on one line
299 * 2 - like 2, but only partial prefixed
300 * 3 - like 1, but each entry onto a new line
301 * 4 - like 2 + 3
302 */
303
304/*
305 * If we are in multiline mode, end the current line and set the
306 * flag, that we need indentation. But prevent double new lines.
307 */
308void
309uni_print_eol(struct unicx *cx)
310{
311 if (cx->multiline) {
312 if (!cx->doindent) {
313 uni_putc('\n', cx);
314 cx->doindent = 1;
315 }
316 }
317}
318
319/*
320 * New entry. Do the prefixing, indentation and spacing.
321 */
322static void
323doprefix(struct unicx *cx, const char *s)
324{
325 u_int i;
326
327 if(cx->multiline == 0) {
328 uni_putc(' ', cx);
329 for(i = 0; i < cx->nprefix; i++)
330 if(cx->prefix[i])
331 uni_printf(cx, "%s.", cx->prefix[i]);
332 } else if(cx->multiline == 1) {
333 if(cx->doindent) {
334 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
335 cx->doindent = 0;
336 } else
337 uni_putc(' ', cx);
338 for(i = 0; i < cx->nprefix; i++)
339 if(cx->prefix[i])
340 uni_printf(cx, "%s.", cx->prefix[i]);
341 } else if(cx->multiline == 2) {
342 if(cx->doindent) {
343 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
344 cx->doindent = 0;
345 } else
346 uni_putc(' ', cx);
347 } else if(cx->multiline == 3) {
348 if(cx->doindent)
349 cx->doindent = 0;
350 else
351 uni_putc('\n', cx);
352 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
353 for(i = 0; i < cx->nprefix; i++)
354 if(cx->prefix[i])
355 uni_printf(cx, "%s.", cx->prefix[i]);
356 } else if(cx->multiline == 4) {
357 if(cx->doindent)
358 cx->doindent = 0;
359 else
360 uni_putc('\n', cx);
361 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
362 }
363 uni_printf(cx, "%s", s);
364}
365static void
366uni_entry(const char *s, struct unicx *cx)
367{
368 doprefix(cx, s);
369 uni_putc('=', cx);
370}
371void
372uni_print_flag(const char *s, struct unicx *cx)
373{
374 doprefix(cx, s);
375}
376
377
378/*
379 * Start a deeper level of indendation. If multiline is in effect,
380 * we end the current line.
381 */
382void
383uni_print_push_prefix(const char *prefix, struct unicx *cx)
384{
385 if (cx->nprefix < PRINT_NPREFIX)
386 cx->prefix[cx->nprefix++] = prefix;
387}
388void
389uni_print_pop_prefix(struct unicx *cx)
390{
391 if (cx->nprefix > 0)
392 cx->nprefix--;
393}
394
395void
396uni_print_tbl(const char *entry, u_int val, const struct uni_print_tbl *tbl,
397 struct unicx *cx)
398{
399 if (entry)
400 uni_entry(entry, cx);
401 while (tbl->name) {
402 if (tbl->val == val) {
403 uni_printf(cx, "%s", tbl->name);
404 return;
405 }
406 tbl++;
407 }
408 uni_printf(cx, "ERROR(0x%x)", val);
409}
410
411void
412uni_print_entry(struct unicx *cx, const char *e, const char *fmt, ...)
413{
414 u_int n;
415 va_list ap;
416
417 uni_entry(e, cx);
418
419 if (cx->bufsiz > 1) {
420 va_start(ap, fmt);
421 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
422 va_end(ap);
423 if (n > 0) {
424 if (n < cx->bufsiz) {
425 cx->bufsiz -= n;
426 cx->buf += n;
427 } else {
428 cx->buf += cx->bufsiz - 1;
429 cx->bufsiz = 1;
430 }
431 }
432 *cx->buf = '\0';
433 }
434}
435
436/**********************************************************************/
437/*
438 * Printing information elements.
439 */
440static int
441uni_print_iehdr(const char *name, struct uni_iehdr *h, struct unicx *cx)
442{
443 static const struct uni_print_tbl act_tab[] = {
444 MKT(UNI_IEACT_CLEAR, clear),
445 MKT(UNI_IEACT_IGNORE, ignore),
446 MKT(UNI_IEACT_REPORT, report),
447 MKT(UNI_IEACT_MSG_IGNORE, ignore-msg),
448 MKT(UNI_IEACT_MSG_REPORT, report-msg),
449 MKT(UNI_IEACT_DEFAULT, default),
450 EOT()
451 };
452 static const struct uni_print_tbl cod_tab[] = {
453 MKT(UNI_CODING_ITU, itut),
454 MKT(UNI_CODING_NET, atmf),
455 EOT()
456 };
457
458 uni_print_entry(cx, name, "(");
459 uni_print_tbl(NULL, h->act, act_tab, cx);
460 uni_putc(',', cx);
461 uni_print_tbl(NULL, h->coding, cod_tab, cx);
462 if(cx->pnni && h->pass)
463 uni_printf(cx, ",pass");
464 if(IE_ISEMPTY(*(struct uni_ie_aal *)h)) {
465 uni_printf(cx, ",empty)");
466 uni_print_eol(cx);
467 return 1;
468 }
469 if(IE_ISERROR(*(struct uni_ie_aal *)h)) {
470 uni_printf(cx, ",error)");
471 uni_print_eol(cx);
472 return 1;
473 }
474
475 uni_putc(')', cx);
476
477 uni_print_push_prefix(name, cx);
478 uni_print_eol(cx);
479 cx->indent++;
480
481 return 0;
482}
483
484static void
485uni_print_ieend(struct unicx *cx)
486{
487 uni_print_pop_prefix(cx);
488 uni_print_eol(cx);
489 cx->indent--;
490}
491
492void
493uni_print_ie_internal(enum uni_ietype code, const union uni_ieall *ie,
494 struct unicx *cx)
495{
496 const struct iedecl *iedecl;
497
498 if((iedecl = GET_IEDECL(code, ie->h.coding)) != NULL)
499 (*iedecl->print)(ie, cx);
500}
501
502void
503uni_print_ie(char *buf, size_t size, enum uni_ietype code,
504 const union uni_ieall *ie, struct unicx *cx)
505{
506 uni_print_init(buf, size, cx);
507 uni_print_ie_internal(code, ie, cx);
508}
509
510int
511uni_check_ie(enum uni_ietype code, union uni_ieall *ie, struct unicx *cx)
512{
513 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
514
515 if (iedecl != NULL)
516 return (iedecl->check(ie, cx));
517 else
518 return (-1);
519}
520
521/*
522 * Decode a information element header.
523 * Returns -1 if the message is too short.
524 * Strip the header from the message.
525 * The header is stripped, even if it is too short.
526 */
527int
528uni_decode_ie_hdr(enum uni_ietype *ietype, struct uni_iehdr *hdr,
529 struct uni_msg *msg, struct unicx *cx, u_int *ielen)
530{
531 u_int len;
532
533 *ietype = (enum uni_ietype)0;
534 *ielen = 0;
535 hdr->present = 0;
536 hdr->coding = UNI_CODING_ITU;
537 hdr->act = UNI_IEACT_DEFAULT;
538
539 if ((len = uni_msg_len(msg)) == 0)
540 return (-1);
541
542 *ietype = *msg->b_rptr++;
543
544 if (--len == 0)
545 return (-1);
546
547 hdr->coding = (*msg->b_rptr >> 5) & 3;
548 hdr->present = 0;
549
550 switch (*msg->b_rptr & 0x17) {
551
552 case 0x10: case 0x11: case 0x12:
553 case 0x15: case 0x16:
554 hdr->act = *msg->b_rptr & 0x7;
555 break;
556
557 case 0x00: case 0x01: case 0x02: case 0x03:
558 case 0x04: case 0x05: case 0x06: case 0x07:
559 hdr->act = UNI_IEACT_DEFAULT;
560 break;
561
562 default:
563 /* Q.2931 5.7.2 last sentence */
564 hdr->act = UNI_IEACT_REPORT;
565 break;
566 }
567 if (cx->pnni && (*msg->b_rptr & 0x08))
568 hdr->pass = 1;
569 else
570 hdr->pass = 0;
571 msg->b_rptr++;
572
573 if (--len == 0) {
574 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
575 return (-1);
576 }
577
578 if (len < 2) {
579 msg->b_rptr += len;
580 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
581 return (-1);
582 }
583
584 *ielen = *msg->b_rptr++ << 8;
585 *ielen |= *msg->b_rptr++;
586
587 return (0);
588}
589
590/*
591 * Decode the body of an information element.
592 */
593int
594uni_decode_ie_body(enum uni_ietype ietype, union uni_ieall *ie,
595 struct uni_msg *msg, u_int ielen, struct unicx *cx)
596{
597 const struct iedecl *iedecl;
598 u_char *end;
599 int ret;
600
601 if (ielen > uni_msg_len(msg)) {
602 /*
603 * Information element too long -> content error.
604 * Q.2931 5.6.8.2
605 */
606 msg->b_rptr = msg->b_wptr;
607 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
608 return (-1);
609 }
610
611 if ((iedecl = GET_IEDECL(ietype, ie->h.coding)) == NULL) {
612 /*
613 * entirly unknown IE.
614 * Q.2931 5.6.8.1
615 */
616 msg->b_rptr += ielen;
617 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
618 return (-1);
619 }
620
621 if (ielen > iedecl->maxlen) {
622 /*
623 * Information element too long -> content error.
624 * Q.2931 5.6.8.2
625 */
626 msg->b_rptr += iedecl->maxlen;
627 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
628 return (-1);
629 }
630
631 end = msg->b_rptr + ielen;
632 ret = (*iedecl->decode)(ie, msg, ielen, cx);
633 msg->b_rptr = end;
634
635 return (ret);
636}
637
638int
639uni_encode_ie(enum uni_ietype code, struct uni_msg *msg, union uni_ieall *ie,
640 struct unicx *cx)
641{
642 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
643
644 if (iedecl == NULL)
645 return (-1);
646 return (iedecl->encode(msg, ie, cx));
647}
648
649int
650uni_encode_ie_hdr(struct uni_msg *msg, enum uni_ietype type,
651 struct uni_iehdr *h, u_int len, struct unicx *cx)
652{
653 u_char byte;
654
655 uni_msg_ensure(msg, 4 + len);
656 *msg->b_wptr++ = type;
657
658 byte = 0x80 | (h->coding << 5);
659 if(h->act != UNI_IEACT_DEFAULT)
660 byte |= 0x10 | (h->act & 7);
661 if(cx->pnni)
662 byte |= h->pass << 3;
663 *msg->b_wptr++ = byte;
664
665 if(h->present & UNI_IE_EMPTY) {
666 *msg->b_wptr++ = 0;
667 *msg->b_wptr++ = 4;
668 return -1;
669 }
670 *msg->b_wptr++ = 0;
671 *msg->b_wptr++ = 0;
672
673 return 0;
674}
675
676/*
677 * Printing messages.
678 */
679static void
680uni_print_cref_internal(const struct uni_cref *cref, struct unicx *cx)
681{
682 uni_print_entry(cx, "cref", "%d.", cref->flag);
683 if (cref->cref == CREF_GLOBAL)
684 uni_printf(cx, "GLOBAL");
685 else if (cref->cref == CREF_DUMMY)
686 uni_printf(cx, "DUMMY");
687 else
688 uni_printf(cx, "%d", cref->cref);
689}
690void
691uni_print_cref(char *str, size_t len, const struct uni_cref *cref,
692 struct unicx *cx)
693{
694 uni_print_init(str, len, cx);
695 uni_print_cref_internal(cref, cx);
696}
697
698static void
699uni_print_msghdr_internal(const struct uni_msghdr *hdr, struct unicx *cx)
700{
701 static const struct uni_print_tbl tab[] = {
702 MKT(UNI_MSGACT_CLEAR, clear),
703 MKT(UNI_MSGACT_IGNORE, ignore),
704 MKT(UNI_MSGACT_REPORT, report),
705 MKT(UNI_MSGACT_DEFAULT, default),
706 EOT()
707 };
708
709 uni_print_cref_internal(&hdr->cref, cx);
710 uni_print_tbl("act", hdr->act, tab, cx);
711 if (cx->pnni)
712 uni_print_entry(cx, "pass", "%s", hdr->pass ? "yes" : "no");
713}
714
715void
716uni_print_msghdr(char *str, size_t len, const struct uni_msghdr *hdr,
717 struct unicx *cx)
718{
719 uni_print_init(str, len, cx);
720 uni_print_msghdr_internal(hdr, cx);
721}
722
723
724static void
725uni_print_internal(const struct uni_all *msg, struct unicx *cx)
726{
727 uni_entry("mtype", cx);
728 if(msg->mtype >= 256 || uni_msgtable[msg->mtype] == NULL) {
729 uni_printf(cx, "0x%02x(ERROR)", msg->mtype);
730 } else {
731 uni_printf(cx, "%s", uni_msgtable[msg->mtype]->name);
732 uni_print_msghdr_internal(&msg->u.hdr, cx);
733 cx->indent++;
734 uni_print_eol(cx);
735 (*uni_msgtable[msg->mtype]->print)(&msg->u, cx);
736 cx->indent--;
737 }
738
739 if(cx->multiline == 0)
740 uni_printf(cx, "\n");
741}
742
743void
744uni_print(char *buf, size_t size, const struct uni_all *all, struct unicx *cx)
745{
746 uni_print_init(buf, size, cx);
747 uni_print_internal(all, cx);
748}
749
750static void
751uni_print_msg_internal(u_int mtype, const union uni_msgall *msg,
752 struct unicx *cx)
753{
754
755 uni_entry("mtype", cx);
756 if (mtype >= 256 || uni_msgtable[mtype] == NULL) {
757 uni_printf(cx, "0x%02x(ERROR)", mtype);
758 } else {
759 uni_printf(cx, "%s", uni_msgtable[mtype]->name);
760 uni_print_msghdr_internal(&msg->hdr, cx);
761 cx->indent++;
762 uni_print_eol(cx);
763 (*uni_msgtable[mtype]->print)(msg, cx);
764 cx->indent--;
765 }
766
767 if(cx->multiline == 0)
768 uni_printf(cx, "\n");
769}
770
771void
772uni_print_msg(char *buf, size_t size, u_int mtype, const union uni_msgall *all,
773 struct unicx *cx)
774{
775 uni_print_init(buf, size, cx);
776 uni_print_msg_internal(mtype, all, cx);
777}
778
779void
780uni_print_cx(char *buf, size_t size, struct unicx *cx)
781{
782 static const char *acttab[] = {
783 "clr", /* 0x00 */
784 "ign", /* 0x01 */
785 "rep", /* 0x02 */
786 "x03", /* 0x03 */
787 "x04", /* 0x04 */
788 "mig", /* 0x05 */
789 "mrp", /* 0x06 */
790 "x07", /* 0x07 */
791 "def", /* 0x08 */
792 };
793
794 static const char *errtab[] = {
795 [UNI_IERR_UNK] = "unk", /* unknown IE */
796 [UNI_IERR_LEN] = "len", /* length error */
797 [UNI_IERR_BAD] = "bad", /* content error */
798 [UNI_IERR_ACC] = "acc", /* access element discarded */
799 [UNI_IERR_MIS] = "mis", /* missing IE */
800 };
801
802 u_int i;
803
804 uni_print_init(buf, size, cx);
805
806 uni_printf(cx, "q2932 %d\n", cx->q2932);
807 uni_printf(cx, "pnni %d\n", cx->pnni);
808 uni_printf(cx, "git_hard %d\n", cx->git_hard);
809 uni_printf(cx, "bearer_hard %d\n", cx->bearer_hard);
810 uni_printf(cx, "cause_hard %d\n", cx->cause_hard);
811
812 uni_printf(cx, "multiline %d\n", cx->multiline);
813 uni_printf(cx, "tabsiz %d\n", cx->tabsiz);
814
815 uni_printf(cx, "errcnt %d (", cx->errcnt);
816 for(i = 0; i < cx->errcnt; i++) {
817 uni_printf(cx, "%02x[%s,%s%s]", cx->err[i].ie,
818 errtab[cx->err[i].err], acttab[cx->err[i].act],
819 cx->err[i].man ? ",M" : "");
820 if(i != cx->errcnt - 1)
821 uni_putc(' ', cx);
822 }
823 uni_printf(cx, ")\n");
824}
825
826#include <netnatm/msg/uni_ietab.h>
827
828/*********************************************************************
829 *
830 * Cause
831 *
832 * References for this IE are:
833 *
834 * Q.2931 pp. 69 (just a pointer to Q.2610)
835 * Q.2610 (this is a small diff to Q.850)
836 * Q.850 !!
837 * UNI4.0 pp. 15
838 * PNNI1.0 p. 198
839 *
840 * ITU-T and NET coding for different values.
841 */
842static const struct causetab {
843 const char *str;
844 enum uni_diag diag;
845} itu_causes[128] = {
846
847#define D(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
848#define N(NAME,VAL,DIAG,STD,STR)
849
850UNI_DECLARE_CAUSE_VALUES
851
852#undef D
853#undef N
854
855}, net_causes[128] = {
856
857#define D(NAME,VAL,DIAG,STD,STR)
858#define N(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
859
860UNI_DECLARE_CAUSE_VALUES
861
862#undef D
863#undef N
864
865};
866
867enum uni_diag
868uni_diag(enum uni_cause cause, enum uni_coding code)
869{
870 if (cause >= 128)
871 return (UNI_DIAG_NONE);
872
873 if (code == UNI_CODING_NET)
874 if (net_causes[cause].str != NULL)
875 return (net_causes[cause].diag);
876 if (itu_causes[cause].str != NULL)
877 return (itu_causes[cause].diag);
878 return (UNI_DIAG_NONE);
879}
880
881/**********************************************************************/
882
883static void
884print_cause(struct unicx *cx, struct uni_ie_cause *ie,
885 const struct causetab *tab1, const struct causetab *tab2)
886{
887 static const struct uni_print_tbl loc_tbl[] = {
888 MKT(UNI_CAUSE_LOC_USER, user),
889 MKT(UNI_CAUSE_LOC_PRIVLOC, priv-net:loc-user),
890 MKT(UNI_CAUSE_LOC_PUBLOC, pub-net:loc-user),
891 MKT(UNI_CAUSE_LOC_TRANSIT, transit-net),
892 MKT(UNI_CAUSE_LOC_PUBREM, pub-net:rem-user),
893 MKT(UNI_CAUSE_LOC_PRIVREM, priv-net:rem-user),
894 MKT(UNI_CAUSE_LOC_INTERNAT, int-net),
895 MKT(UNI_CAUSE_LOC_BEYOND, beyond),
896 EOT()
897 };
898 static const struct uni_print_tbl pu_tbl[] = {
899 MKT(UNI_CAUSE_PU_PROVIDER, provider),
900 MKT(UNI_CAUSE_PU_USER, user),
901 EOT()
902 };
903 static const struct uni_print_tbl na_tbl[] = {
904 MKT(UNI_CAUSE_NA_NORMAL, normal),
905 MKT(UNI_CAUSE_NA_ABNORMAL, abnormal),
906 EOT()
907 };
908 static const struct uni_print_tbl cond_tbl[] = {
909 MKT(UNI_CAUSE_COND_UNKNOWN, unknown),
910 MKT(UNI_CAUSE_COND_PERM, permanent),
911 MKT(UNI_CAUSE_COND_TRANS, transient),
912 EOT()
913 };
914 static const struct uni_print_tbl rej_tbl[] = {
915 MKT(UNI_CAUSE_REASON_USER, user),
916 MKT(UNI_CAUSE_REASON_IEMISS, ie-missing),
917 MKT(UNI_CAUSE_REASON_IESUFF, ie-not-suff),
918 EOT()
919 };
920 char buf[100], *s;
921 u_int i;
922
923 if (uni_print_iehdr("cause", &ie->h, cx))
924 return;
925
926 if (ie->cause < 128 && tab1[ie->cause].str)
927 strcpy(buf, tab1[ie->cause].str);
928 else if (ie->cause < 128 && tab2 != NULL && tab2[ie->cause].str != NULL)
929 strcpy(buf, tab2[ie->cause].str);
930 else {
931 sprintf(buf, "UNKNOWN-%u", ie->cause);
932 }
933
934 for (s = buf; *s != '\0'; s++)
935 if (*s == ' ')
936 *s = '_';
937 uni_print_entry(cx, "cause", "%s", buf);
938
939 uni_print_tbl("loc", ie->loc, loc_tbl, cx);
940
941 if (ie->h.present & UNI_CAUSE_COND_P) {
942 uni_print_tbl("pu", ie->u.cond.pu, pu_tbl, cx);
943 uni_print_tbl("na", ie->u.cond.na, na_tbl, cx);
944 uni_print_tbl("condition", ie->u.cond.cond, cond_tbl, cx);
945 }
946 if (ie->h.present & UNI_CAUSE_REJ_P) {
947 uni_print_tbl("reject", ie->u.rej.reason, rej_tbl, cx);
948 }
949 if (ie->h.present & UNI_CAUSE_REJ_USER_P) {
950 uni_print_entry(cx, "user", "%u", ie->u.rej.user);
951 }
952 if (ie->h.present & UNI_CAUSE_REJ_IE_P) {
953 uni_print_entry(cx, "ie", "%u", ie->u.rej.ie);
954 }
955 if (ie->h.present & UNI_CAUSE_IE_P) {
956 uni_print_entry(cx, "ie", "(");
957 for (i = 0; i < ie->u.ie.len; i++) {
958 if (i)
959 uni_putc(',', cx);
960 uni_printf(cx, "0x%02x", ie->u.ie.ie[i]);
961 }
962 uni_putc(')', cx);
963 }
964 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
965 uni_print_entry(cx, "traffic", "(");
966 for (i = 0; i < ie->u.traffic.len; i++) {
967 if (i)
968 uni_putc(',', cx);
969 uni_printf(cx, "0x%02x", ie->u.traffic.traffic[i]);
970 }
971 uni_putc(')', cx);
972 }
973 if (ie->h.present & UNI_CAUSE_VPCI_P) {
974 uni_print_entry(cx, "vpci", "(%u,%u)", ie->u.vpci.vpci, ie->u.vpci.vci);
975 }
976 if (ie->h.present & UNI_CAUSE_MTYPE_P) {
977 uni_print_entry(cx, "mtype", "%u", ie->u.mtype);
978 }
979 if (ie->h.present & UNI_CAUSE_TIMER_P) {
980 for (i = 0, s = buf; i < 3; i++) {
981 if (ie->u.timer[i] < ' ') {
982 *s++ = '^';
983 *s++ = ie->u.timer[i] + '@';
984 } else if (ie->u.timer[i] <= '~')
985 *s++ = ie->u.timer[i];
986 else {
987 *s++ = '\\';
988 *s++ = ie->u.timer[i] / 0100 + '0';
989 *s++ = (ie->u.timer[i] % 0100) / 010 + '0';
990 *s++ = ie->u.timer[i] % 010 + '0';
991 }
992 }
993 *s++ = '\0';
994 uni_print_entry(cx, "timer", "\"%s\"", buf);
995 }
996 if (ie->h.present & UNI_CAUSE_TNS_P) {
997 uni_print_eol(cx);
998 uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx);
999 }
1000 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1001 uni_print_eol(cx);
1002 uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx);
1003 }
1004 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1005 uni_print_entry(cx, "attr", "(");
1006 for (i = 0; i < ie->u.attr.nattr; i++) {
1007 uni_printf(cx, "(%u", ie->u.attr.attr[i][0]);
1008 if (!(ie->u.attr.attr[i][0] & 0x80)) {
1009 uni_printf(cx, ",%u", ie->u.attr.attr[i][1]);
1010 if (!(ie->u.attr.attr[i][1] & 0x80))
1011 uni_printf(cx, ",%u",
1012 ie->u.attr.attr[i][2]);
1013 }
1014 uni_putc(')', cx);
1015 }
1016 }
1017
1018 uni_print_ieend(cx);
1019}
1020
1021DEF_IE_PRINT(itu, cause)
1022{
1023 print_cause(cx, ie, itu_causes, NULL);
1024}
1025DEF_IE_PRINT(net, cause)
1026{
1027 print_cause(cx, ie, net_causes, itu_causes);
1028}
1029
1030const char *
1031uni_ie_cause2str(enum uni_coding coding, u_int cause)
1032{
1033 if (cause < 128) {
1034 if (coding == UNI_CODING_ITU)
1035 return (itu_causes[cause].str);
1036 if (coding == UNI_CODING_NET) {
1037 if (net_causes[cause].str != NULL)
1038 return (net_causes[cause].str);
1039 return (itu_causes[cause].str);
1040 }
1041 }
1042 return (NULL);
1043}
1044
1045/**********************************************************************/
1046
1047static int
1048check_cause(struct uni_ie_cause *ie, struct unicx *cx,
1049 const struct causetab *tab1, const struct causetab *tab2)
1050{
1051 static const u_int mask =
1052 UNI_CAUSE_COND_P | UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P |
1053 UNI_CAUSE_REJ_IE_P | UNI_CAUSE_IE_P | UNI_CAUSE_TRAFFIC_P |
1054 UNI_CAUSE_VPCI_P | UNI_CAUSE_MTYPE_P | UNI_CAUSE_TIMER_P |
1055 UNI_CAUSE_TNS_P | UNI_CAUSE_NUMBER_P | UNI_CAUSE_ATTR_P |
1056 UNI_CAUSE_PARAM_P;
1057
1058 const struct causetab *ptr;
1059
1060 if (ie->cause >= 128)
1061 return (-1);
1062
1063 switch (ie->loc) {
1064 default:
1065 return (-1);
1066
1067 case UNI_CAUSE_LOC_USER:
1068 case UNI_CAUSE_LOC_PRIVLOC:
1069 case UNI_CAUSE_LOC_PUBLOC:
1070 case UNI_CAUSE_LOC_TRANSIT:
1071 case UNI_CAUSE_LOC_PUBREM:
1072 case UNI_CAUSE_LOC_PRIVREM:
1073 case UNI_CAUSE_LOC_INTERNAT:
1074 case UNI_CAUSE_LOC_BEYOND:
1075 break;
1076 }
1077
1078 if (tab1[ie->cause].str != NULL)
1079 ptr = &tab1[ie->cause];
1080 else if (tab2 != NULL && tab2[ie->cause].str != NULL)
1081 ptr = &tab2[ie->cause];
1082 else
1083 return (cx->cause_hard ? -1 : 0);
1084
1085 switch (ptr->diag) {
1086
1087 case UNI_DIAG_NONE:
1088 switch (ie->h.present & mask) {
1089 default:
1090 if (cx->cause_hard)
1091 return (-1);
1092 break;
1093
1094 case 0:
1095 break;
1096 }
1097 break;
1098
1099 case UNI_DIAG_COND:
1100 switch (ie->h.present & mask) {
1101 default:
1102 if (cx->cause_hard)
1103 return (-1);
1104 break;
1105
1106 case 0:
1107 case UNI_CAUSE_COND_P:
1108 break;
1109 }
1110 break;
1111
1112 case UNI_DIAG_REJ:
1113 switch (ie->h.present & mask) {
1114 default:
1115 if (cx->cause_hard)
1116 return (-1);
1117 break;
1118
1119 case 0:
1120 case UNI_CAUSE_REJ_P:
1121 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1122 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1123 break;
1124 }
1125 break;
1126
1127 case UNI_DIAG_CRATE:
1128 switch (ie->h.present & mask) {
1129 default:
1130 if (cx->cause_hard)
1131 return (-1);
1132 break;
1133
1134 case 0:
1135 case UNI_CAUSE_TRAFFIC_P:
1136 break;
1137 }
1138 break;
1139
1140 case UNI_DIAG_IE:
1141 switch (ie->h.present & mask) {
1142 default:
1143 if (cx->cause_hard)
1144 return (-1);
1145 break;
1146
1147 case 0:
1148 case UNI_CAUSE_IE_P:
1149 break;
1150 }
1151 break;
1152
1153 case UNI_DIAG_CHANID:
1154 switch (ie->h.present & mask) {
1155 default:
1156 if (cx->cause_hard)
1157 return (-1);
1158 break;
1159
1160 case 0:
1161 case UNI_CAUSE_VPCI_P:
1162 break;
1163 }
1164 break;
1165
1166 case UNI_DIAG_MTYPE:
1167 switch (ie->h.present & mask) {
1168 default:
1169 if (cx->cause_hard)
1170 return (-1);
1171 break;
1172
1173 case 0:
1174 case UNI_CAUSE_MTYPE_P:
1175 break;
1176 }
1177 break;
1178
1179 case UNI_DIAG_TIMER:
1180 switch (ie->h.present & mask) {
1181 default:
1182 if (cx->cause_hard)
1183 return (-1);
1184 break;
1185
1186 case 0:
1187 case UNI_CAUSE_TIMER_P:
1188 break;
1189 }
1190 break;
1191
1192 case UNI_DIAG_TNS:
1193 switch (ie->h.present & mask) {
1194 default:
1195 if (cx->cause_hard)
1196 return (-1);
1197 break;
1198
1199 case 0:
1200 case UNI_CAUSE_TNS_P:
1201 break;
1202 }
1203 break;
1204
1205 case UNI_DIAG_NUMBER:
1206 switch (ie->h.present & mask) {
1207 default:
1208 if (cx->cause_hard)
1209 return (-1);
1210 break;
1211
1212 case 0:
1213 case UNI_CAUSE_NUMBER_P:
1214 break;
1215 }
1216 break;
1217
1218 case UNI_DIAG_ATTR:
1219 switch (ie->h.present & mask) {
1220 default:
1221 if (cx->cause_hard)
1222 return (-1);
1223 break;
1224
1225 case 0:
1226 case UNI_CAUSE_ATTR_P:
1227 break;
1228 }
1229 break;
1230
1231 case UNI_DIAG_PARAM:
1232 switch (ie->h.present & mask) {
1233 default:
1234 if (cx->cause_hard)
1235 return (-1);
1236 break;
1237
1238 case 0:
1239 case UNI_CAUSE_PARAM_P:
1240 break;
1241 }
1242 break;
1243 }
1244
1245 if (ie->h.present & UNI_CAUSE_COND_P) {
1246 switch (ie->u.cond.pu) {
1247 default:
1248 return (-1);
1249
1250 case UNI_CAUSE_PU_PROVIDER:
1251 case UNI_CAUSE_PU_USER:
1252 break;
1253 }
1254 switch (ie->u.cond.na) {
1255 default:
1256 return (-1);
1257
1258 case UNI_CAUSE_NA_NORMAL:
1259 case UNI_CAUSE_NA_ABNORMAL:
1260 break;
1261 }
1262 switch (ie->u.cond.cond) {
1263 default:
1264 return (-1);
1265
1266 case UNI_CAUSE_COND_UNKNOWN:
1267 case UNI_CAUSE_COND_PERM:
1268 case UNI_CAUSE_COND_TRANS:
1269 break;
1270 }
1271 }
1272 if (ie->h.present & UNI_CAUSE_REJ_P) {
1273 switch (ie->u.rej.reason) {
1274 default:
1275 return (-1);
1276
1277 case UNI_CAUSE_REASON_USER:
1278 switch (ie->h.present & mask) {
1279 default:
1280 return (-1);
1281
1282 case UNI_CAUSE_REJ_P:
1283 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1284 break;
1285 }
1286 break;
1287
1288 case UNI_CAUSE_REASON_IEMISS:
1289 case UNI_CAUSE_REASON_IESUFF:
1290 switch (ie->h.present & mask) {
1291 default:
1292 return (-1);
1293
1294 case UNI_CAUSE_REJ_P:
1295 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1296 break;
1297 }
1298 break;
1299 }
1300 }
1301 if (ie->h.present & UNI_CAUSE_IE_P) {
1302 if (ie->u.ie.len == 0 || ie->u.ie.len > UNI_CAUSE_IE_N)
1303 return (-1);
1304 }
1305 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
1306 if (ie->u.traffic.len == 0 ||
1307 ie->u.traffic.len > UNI_CAUSE_TRAFFIC_N)
1308 return (-1);
1309 }
1310
1311 if (ie->h.present & UNI_CAUSE_TNS_P) {
1312 if (uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx))
1313 return (-1);
1314 }
1315 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1316 if(uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx))
1317 return (-1);
1318 }
1319 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1320 if(ie->u.attr.nattr > UNI_CAUSE_ATTR_N || ie->u.attr.nattr == 0)
1321 return (-1);
1322 }
1323 if (ie->h.present & UNI_CAUSE_PARAM_P) {
1324 cx = cx;
1325 }
1326
1327 return (0);
1328}
1329
1330DEF_IE_CHECK(itu, cause)
1331{
1332 return (check_cause(ie, cx, itu_causes, NULL));
1333}
1334DEF_IE_CHECK(net, cause)
1335{
1336 return (check_cause(ie, cx, net_causes, itu_causes));
1337}
1338/**********************************************************************/
1339
1340static int
1341encode_cause(struct uni_msg *msg, struct uni_ie_cause *ie, struct unicx *cx)
1342{
1343 u_int i;
1344
1345 START_IE(cause, UNI_IE_CAUSE, 30);
1346
1347 if (IE_ISERROR(*ie)) {
1348 APP_BYTE(msg, 0x00 | ie->loc);
1349 } else {
1350 APP_BYTE(msg, 0x80 | ie->loc);
1351 }
1352 APP_BYTE(msg, 0x80 | ie->cause);
1353
1354 if (ie->h.present & UNI_CAUSE_COND_P)
1355 APP_BYTE(msg, 0x80 | (ie->u.cond.pu << 3) |
1356 (ie->u.cond.na << 2) | ie->u.cond.cond);
1357
1358 else if (ie->h.present & UNI_CAUSE_REJ_P) {
1359 APP_BYTE(msg, 0x80 | (ie->u.rej.reason << 2) | ie->u.rej.cond);
1360 if (ie->h.present & UNI_CAUSE_REJ_USER_P)
1361 APP_BYTE(msg, ie->u.rej.user);
1362 else if (ie->h.present & UNI_CAUSE_REJ_IE_P)
1363 APP_BYTE(msg, ie->u.rej.ie);
1364
1365 } else if(ie->h.present & UNI_CAUSE_IE_P)
1366 APP_BUF(msg, ie->u.ie.ie, ie->u.ie.len);
1367
1368 else if (ie->h.present & UNI_CAUSE_TRAFFIC_P)
1369 APP_BUF(msg, ie->u.traffic.traffic, ie->u.traffic.len);
1370
1371 else if (ie->h.present & UNI_CAUSE_VPCI_P) {
1372 APP_BYTE(msg, (ie->u.vpci.vpci >> 8));
1373 APP_BYTE(msg, (ie->u.vpci.vpci >> 0));
1374 APP_BYTE(msg, (ie->u.vpci.vci >> 8));
1375 APP_BYTE(msg, (ie->u.vpci.vci >> 0));
1376
1377 } else if (ie->h.present & UNI_CAUSE_MTYPE_P)
1378 APP_BYTE(msg, ie->u.mtype);
1379
1380 else if (ie->h.present & UNI_CAUSE_TIMER_P) {
1381 APP_BYTE(msg, ie->u.timer[0]);
1382 APP_BYTE(msg, ie->u.timer[1]);
1383 APP_BYTE(msg, ie->u.timer[2]);
1384
1385 } else if (ie->h.present & UNI_CAUSE_TNS_P)
1386 uni_encode_ie(UNI_IE_TNS, msg,
1387 (union uni_ieall *)&ie->u.tns, cx);
1388
1389 else if (ie->h.present & UNI_CAUSE_NUMBER_P)
1390 uni_encode_ie(UNI_IE_CALLED, msg,
1391 (union uni_ieall *)&ie->u.number, cx);
1392
1393 else if (ie->h.present & UNI_CAUSE_ATTR_P) {
1394 for (i = 0; i < ie->u.attr.nattr; i++) {
1395 APP_BYTE(msg, ie->u.attr.attr[i][0]);
1396 if (!ie->u.attr.attr[i][0]) {
1397 APP_BYTE(msg, ie->u.attr.attr[i][1]);
1398 if (!ie->u.attr.attr[i][1])
1399 APP_BYTE(msg, ie->u.attr.attr[i][2]);
1400 }
1401 }
1402 } else if (ie->h.present & UNI_CAUSE_PARAM_P)
1403 APP_BYTE(msg, ie->u.param);
1404
1405 SET_IE_LEN(msg);
1406
1407 return (0);
1408}
1409
1410DEF_IE_ENCODE(itu, cause)
1411{
1412 return encode_cause(msg, ie, cx);
1413}
1414DEF_IE_ENCODE(net, cause)
1415{
1416 return encode_cause(msg, ie, cx);
1417}
1418
1419/**********************************************************************/
1420
1421static int
1422decode_cause(struct uni_ie_cause *ie, struct uni_msg *msg, u_int ielen,
1423 struct unicx *cx, const struct causetab *tab1, const struct causetab *tab2)
1424{
1425 u_char c;
1426 const struct causetab *ptr;
1427 enum uni_ietype ietype;
1428 u_int xielen;
1429
1430 IE_START(;);
1431
1432 if(ielen < 2 || ielen > 30)
1433 goto rej;
1434
1435 c = *msg->b_rptr++;
1436 ielen--;
1437 if(!(c & 0x80))
1438 goto rej;
1439 ie->loc = c & 0xf;
1440
1441 c = *msg->b_rptr++;
1442 ielen--;
1443 if(!(c & 0x80))
1444 goto rej;
1445 ie->cause = c & 0x7f;
1446
1447 if(tab1[ie->cause].str != NULL)
1448 ptr = &tab1[ie->cause];
1449 else if(tab2 != NULL && tab2[ie->cause].str != NULL)
1450 ptr = &tab2[ie->cause];
1451 else {
1452 ptr = NULL;
1453 ielen = 0; /* ignore diags */
1454 }
1455
1456 if(ielen) {
1457 switch(ptr->diag) {
1458
1459 case UNI_DIAG_NONE:
1460 break;
1461
1462 case UNI_DIAG_COND:
1463 if(ielen < 1)
1464 goto rej;
1465 c = *msg->b_rptr++;
1466 ielen--;
1467
1468 ie->h.present |= UNI_CAUSE_COND_P;
1469 ie->u.cond.pu = (c >> 3) & 1;
1470 ie->u.cond.na = (c >> 2) & 1;
1471 ie->u.cond.cond = c & 3;
1472
1473 if(!(c & 0x80))
1474 goto rej;
1475 break;
1476
1477 case UNI_DIAG_REJ:
1478 if(ielen < 1)
1479 goto rej;
1480 c = *msg->b_rptr++;
1481 ielen--;
1482
1483 ie->h.present |= UNI_CAUSE_REJ_P;
1484 ie->u.rej.reason = (c >> 2) & 0x1f;
1485 ie->u.rej.cond = c & 3;
1486
1487 if(!(c & 0x80))
1488 goto rej;
1489
1490 if(ielen > 0) {
1491 c = *msg->b_rptr++;
1492 ielen--;
1493
1494 switch(ie->u.rej.reason) {
1495
1496 case UNI_CAUSE_REASON_USER:
1497 ie->h.present |= UNI_CAUSE_REJ_USER_P;
1498 ie->u.rej.user = c;
1499 break;
1500
1501 case UNI_CAUSE_REASON_IEMISS:
1502 case UNI_CAUSE_REASON_IESUFF:
1503 ie->h.present |= UNI_CAUSE_REJ_IE_P;
1504 ie->u.rej.ie = c;
1505 break;
1506 }
1507 }
1508 break;
1509
1510 case UNI_DIAG_CRATE:
1511 ie->h.present |= UNI_CAUSE_TRAFFIC_P;
1512 while(ielen && ie->u.traffic.len < UNI_CAUSE_TRAFFIC_N) {
1513 ie->u.traffic.traffic[ie->u.traffic.len++] =
1514 *msg->b_rptr++;
1515 ielen--;
1516 }
1517 break;
1518
1519 case UNI_DIAG_IE:
1520 ie->h.present |= UNI_CAUSE_IE_P;
1521 while(ielen && ie->u.ie.len < UNI_CAUSE_IE_N) {
1522 ie->u.ie.ie[ie->u.ie.len++] = *msg->b_rptr++;
1523 ielen--;
1524 }
1525 break;
1526
1527 case UNI_DIAG_CHANID:
1528 if(ielen < 4)
1529 break;
1530 ie->h.present |= UNI_CAUSE_VPCI_P;
1531 ie->u.vpci.vpci = *msg->b_rptr++ << 8;
1532 ie->u.vpci.vpci |= *msg->b_rptr++;
1533 ie->u.vpci.vci = *msg->b_rptr++ << 8;
1534 ie->u.vpci.vci |= *msg->b_rptr++;
1535 ielen -= 4;
1536 break;
1537
1538 case UNI_DIAG_MTYPE:
1539 ie->h.present |= UNI_CAUSE_MTYPE_P;
1540 ie->u.mtype = *msg->b_rptr++;
1541 ielen--;
1542 break;
1543
1544 case UNI_DIAG_TIMER:
1545 if(ielen < 3)
1546 break;
1547 ie->h.present |= UNI_CAUSE_TIMER_P;
1548 ie->u.timer[0] = *msg->b_rptr++;
1549 ie->u.timer[1] = *msg->b_rptr++;
1550 ie->u.timer[2] = *msg->b_rptr++;
1551 ielen -= 3;
1552 break;
1553
1554 case UNI_DIAG_TNS:
1555 if(ielen < 4)
1556 break;
1557 if(uni_decode_ie_hdr(&ietype, &ie->u.tns.h, msg, cx, &xielen))
1558 break;
1559 if(ietype != UNI_IE_TNS)
1560 break;
1561 if(uni_decode_ie_body(ietype,
1562 (union uni_ieall *)&ie->u.tns, msg, xielen, cx))
1563 break;
1564 ie->h.present |= UNI_CAUSE_TNS_P;
1565 break;
1566
1567 case UNI_DIAG_NUMBER:
1568 if(ielen < 4)
1569 break;
1570 if(uni_decode_ie_hdr(&ietype, &ie->u.number.h, msg, cx, &xielen))
1571 break;
1572 if(ietype != UNI_IE_CALLED)
1573 break;
1574 if(uni_decode_ie_body(ietype,
1575 (union uni_ieall *)&ie->u.number, msg, xielen, cx))
1576 break;
1577 ie->h.present |= UNI_CAUSE_NUMBER_P;
1578 break;
1579
1580 case UNI_DIAG_ATTR:
1581 ie->h.present |= UNI_CAUSE_ATTR_P;
1582 while(ielen > 0 && ie->u.attr.nattr < UNI_CAUSE_ATTR_N) {
1583 c = *msg->b_rptr++;
1584 ie->u.attr.attr[ie->u.attr.nattr][0] = c;
1585 ielen--;
1586 if(ielen > 0 && !(c & 0x80)) {
1587 c = *msg->b_rptr++;
1588 ie->u.attr.attr[ie->u.attr.nattr][1] = c;
1589 ielen--;
1590 if(ielen > 0 && !(c & 0x80)) {
1591 c = *msg->b_rptr++;
1592 ie->u.attr.attr[ie->u.attr.nattr][2] = c;
1593 ielen--;
1594 }
1595 }
1596 }
1597 break;
1598
1599 case UNI_DIAG_PARAM:
1600 ie->h.present |= UNI_CAUSE_PARAM_P;
1601 ie->u.param = *msg->b_rptr++;
1602 ielen--;
1603 break;
1604 }
1605 }
1606
1607 IE_END(CAUSE);
1608}
1609
1610DEF_IE_DECODE(itu, cause)
1611{
1612 return decode_cause(ie, msg, ielen, cx, itu_causes, NULL);
1613}
1614DEF_IE_DECODE(net, cause)
1615{
1616 return decode_cause(ie, msg, ielen, cx, net_causes, itu_causes);
1617}
1618
1619/*********************************************************************
1620 *
1621 * Callstate
1622 *
1623 * References for this IE are:
1624 *
1625 * Q.2931 pp. 59...60
1626 * UNI4.0 pp. 14
1627 *
1628 * Only ITU-T coding allowed.
1629 */
1630DEF_IE_PRINT(itu, callstate)
1631{
1632 static const struct uni_print_tbl tbl[] = {
1633 MKT(UNI_CALLSTATE_U0, U0/N0/REST0),
1634 MKT(UNI_CALLSTATE_U1, U1/N1),
1635 MKT(UNI_CALLSTATE_U3, U3/N3),
1636 MKT(UNI_CALLSTATE_U4, U4/N4),
1637 MKT(UNI_CALLSTATE_U6, U6/N6),
1638 MKT(UNI_CALLSTATE_U7, U7/N7),
1639 MKT(UNI_CALLSTATE_U8, U8/N8),
1640 MKT(UNI_CALLSTATE_U9, U9/N9),
1641 MKT(UNI_CALLSTATE_U10, U10/N10),
1642 MKT(UNI_CALLSTATE_U11, U11/N11),
1643 MKT(UNI_CALLSTATE_U12, U12/N12),
1644 MKT(UNI_CALLSTATE_REST1,REST1),
1645 MKT(UNI_CALLSTATE_REST2,REST2),
1646 MKT(UNI_CALLSTATE_U13, U13/N13),
1647 MKT(UNI_CALLSTATE_U14, U14/N14),
1648 EOT()
1649 };
1650
1651 if(uni_print_iehdr("callstate", &ie->h, cx))
1652 return;
1653 uni_print_tbl("state", ie->state, tbl, cx);
1654 uni_print_ieend(cx);
1655}
1656
1657DEF_IE_CHECK(itu, callstate)
1658{
1659 cx = cx;
1660
1661 switch(ie->state) {
1662 default:
1663 return -1;
1664
1665 case UNI_CALLSTATE_U0:
1666 case UNI_CALLSTATE_U1:
1667 case UNI_CALLSTATE_U3:
1668 case UNI_CALLSTATE_U4:
1669 case UNI_CALLSTATE_U6:
1670 case UNI_CALLSTATE_U7:
1671 case UNI_CALLSTATE_U8:
1672 case UNI_CALLSTATE_U9:
1673 case UNI_CALLSTATE_U10:
1674 case UNI_CALLSTATE_U11:
1675 case UNI_CALLSTATE_U12:
1676 case UNI_CALLSTATE_REST1:
1677 case UNI_CALLSTATE_REST2:
1678 case UNI_CALLSTATE_U13:
1679 case UNI_CALLSTATE_U14:
1680 break;
1681 }
1682
1683 return 0;
1684}
1685
1686DEF_IE_ENCODE(itu, callstate)
1687{
1688 START_IE(callstate, UNI_IE_CALLSTATE, 1);
1689
1690 APP_BYTE(msg, ie->state);
1691
1692 SET_IE_LEN(msg);
1693 return 0;
1694}
1695
1696DEF_IE_DECODE(itu, callstate)
1697{
1698 IE_START(;);
1699
1700 if(ielen != 1)
1701 goto rej;
1702
1703 ie->state = *msg->b_rptr++ & 0x3f;
1704 ielen--;
1705
1706 IE_END(CALLSTATE);
1707}
1708
1709/*********************************************************************
1710 *
1711 * Facility Information.
1712 *
1713 * References for this IE are:
1714 *
1715 * Q.2932.1
1716 *
1717 * The standard allows only ROSE as protocol. We allow everything up to the
1718 * maximum size.
1719 *
1720 * Only ITU-T coding allowed.
1721 */
1722DEF_IE_PRINT(itu, facility)
1723{
1724 u_int i;
1725
1726 if(uni_print_iehdr("facility", &ie->h, cx))
1727 return;
1728
1729 if(ie->proto == UNI_FACILITY_ROSE)
1730 uni_print_entry(cx, "proto", "rose");
1731 else
1732 uni_print_entry(cx, "proto", "0x%02x", ie->proto);
1733
1734 uni_print_entry(cx, "len", "%u", ie->len);
1735 uni_print_entry(cx, "info", "(");
1736 for(i = 0; i < ie->len; i++)
1737 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->apdu[i]);
1738 uni_printf(cx, ")");
1739
1740 uni_print_ieend(cx);
1741}
1742
1743DEF_IE_CHECK(itu, facility)
1744{
1745 cx = cx;
1746
1747 if(ie->len > UNI_FACILITY_MAXAPDU)
1748 return -1;
1749
1750 return 0;
1751}
1752
1753DEF_IE_ENCODE(itu, facility)
1754{
1755 START_IE(facility, UNI_IE_FACILITY, 1 + ie->len);
1756
1757 APP_BYTE(msg, ie->proto | 0x80);
1758 APP_BUF(msg, ie->apdu, ie->len);
1759
1760 SET_IE_LEN(msg);
1761 return 0;
1762}
1763
1764DEF_IE_DECODE(itu, facility)
1765{
1766 u_char c;
1767
1768 IE_START(;);
1769
1770 if(ielen > UNI_FACILITY_MAXAPDU + 1 || ielen < 1)
1771 goto rej;
1772
1773 ie->proto = (c = *msg->b_rptr++) & 0x1f;
1774 ielen--;
1775 if((c & 0xe0) != 0x80)
1776 goto rej;
1777
1778 ie->len = ielen;
1779 ielen = 0;
1780 (void)memcpy(ie->apdu, msg->b_rptr, ie->len);
1781 msg->b_rptr += ie->len;
1782
1783 IE_END(FACILITY);
1784}
1785
1786/*********************************************************************
1787 *
1788 * Notification Indicator
1789 *
1790 * References for this IE are:
1791 *
1792 * Q.2931 p. 76
1793 * UNI4.0 p. 17
1794 *
1795 * Only ITU-T coding allowed.
1796 */
1797
1798DEF_IE_PRINT(itu, notify)
1799{
1800 u_int i;
1801
1802 if(uni_print_iehdr("notify", &ie->h, cx))
1803 return;
1804 uni_print_entry(cx, "len", "%u", ie->len);
1805 uni_print_entry(cx, "info", "(");
1806 for(i = 0; i < ie->len; i++)
1807 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->notify[i]);
1808 uni_printf(cx, ")");
1809 uni_print_ieend(cx);
1810}
1811
1812DEF_IE_CHECK(itu, notify)
1813{
1814 cx = cx;
1815
1816 if(ie->len > UNI_NOTIFY_MAXLEN)
1817 return -1;
1818
1819 return 0;
1820}
1821
1822DEF_IE_ENCODE(itu, notify)
1823{
1824 START_IE(notify, UNI_IE_NOTIFY, ie->len);
1825
1826 APP_BUF(msg, ie->notify, ie->len);
1827 if (IE_ISERROR(*ie)) {
1828 /* make it too long */
1829 u_int i = ie->len;
1830
1831 while (i < UNI_NOTIFY_MAXLEN + 1) {
1832 APP_BYTE(msg, 0x00);
1833 i++;
1834 }
1835 }
1836
1837 SET_IE_LEN(msg);
1838 return (0);
1839}
1840
1841DEF_IE_DECODE(itu, notify)
1842{
1843 IE_START(;);
1844
1845 if (ielen > UNI_NOTIFY_MAXLEN || ielen < 1)
1846 goto rej;
1847
1848 ie->len = ielen;
1849 ielen = 0;
1850 (void)memcpy(ie->notify, msg->b_rptr, ie->len);
1851 msg->b_rptr += ie->len;
1852
1853 IE_END(NOTIFY);
1854}
1855
1856/*********************************************************************
1857 *
1858 * End-to-end transit delay.
1859 *
1860 * References for this IE are:
1861 *
1862 * Q.2931 pp. 70...71
1863 * UNI4.0 pp. 69...70
1864 * PNNI1.0 pp. 198...200
1865 *
1866 * Not clear, whether the new indicator should be used with NET coding or
1867 * not.
1868 *
1869 * Only ITU-T coding allowed.
1870 */
1871
1872static void
1873print_eetd(struct uni_ie_eetd *ie, struct unicx *cx)
1874{
1875 if (uni_print_iehdr("eetd", &ie->h, cx))
1876 return;
1877
1878 if (ie->h.present & UNI_EETD_CUM_P)
1879 uni_print_entry(cx, "cum", "%u", ie->cumulative);
1880 if (ie->h.present & UNI_EETD_MAX_P) {
1881 if (ie->maximum == UNI_EETD_ANYMAX)
1882 uni_print_entry(cx, "max", "any");
1883 else
1884 uni_print_entry(cx, "max", "%u", ie->maximum);
1885 }
1886 if (ie->h.present & UNI_EETD_PCTD_P)
1887 uni_print_entry(cx, "pnni_cum", "%u", ie->pctd);
1888 if (ie->h.present & UNI_EETD_PMTD_P)
1889 uni_print_entry(cx, "pnni_max", "%u", ie->pmtd);
1890 if (ie->h.present & UNI_EETD_NET_P)
1891 uni_print_flag("netgen", cx);
1892
1893 uni_print_ieend(cx);
1894}
1895DEF_IE_PRINT(itu, eetd)
1896{
1897 print_eetd(ie, cx);
1898}
1899DEF_IE_PRINT(net, eetd)
1900{
1901 print_eetd(ie, cx);
1902}
1903
1904DEF_IE_CHECK(itu, eetd)
1905{
1906
1907 cx = cx;
1908
1909 if (!(ie->h.present & UNI_EETD_CUM_P))
1910 return (-1);
1911 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1912 return (-1);
1913 return (0);
1914}
1915
1916DEF_IE_CHECK(net, eetd)
1917{
1918
1919 if (!cx->pnni) {
1920 if (!(ie->h.present & UNI_EETD_CUM_P))
1921 return (-1);
1922 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1923 return (-1);
1924 } else {
1925 if (ie->h.present & UNI_EETD_MAX_P)
1926 return (-1);
1927 if ((ie->h.present & UNI_EETD_CUM_P) &&
1928 (ie->h.present & UNI_EETD_PCTD_P))
1929 return (-1);
1930 }
1931 return (0);
1932}
1933
1934DEF_IE_ENCODE(itu, eetd)
1935{
1936 START_IE(eetd, UNI_IE_EETD, 9);
1937
1938 if (ie->h.present & UNI_EETD_CUM_P) {
1939 APP_BYTE(msg, UNI_EETD_CTD_ID);
1940 APP_16BIT(msg, ie->cumulative);
1941 }
1942 if (ie->h.present & UNI_EETD_MAX_P) {
1943 APP_BYTE(msg, UNI_EETD_MTD_ID);
1944 APP_16BIT(msg, ie->maximum);
1945 }
1946 if (ie->h.present & UNI_EETD_PMTD_P) {
1947 APP_BYTE(msg, UNI_EETD_PMTD_ID);
1948 APP_24BIT(msg, ie->pmtd);
1949 }
1950 if (ie->h.present & UNI_EETD_PCTD_P) {
1951 APP_BYTE(msg, UNI_EETD_PCTD_ID);
1952 APP_24BIT(msg, ie->pctd);
1953 }
1954 if (ie->h.present & UNI_EETD_NET_P) {
1955 APP_BYTE(msg, UNI_EETD_NET_ID);
1956 }
1957
1958 SET_IE_LEN(msg);
1959 return (0);
1960}
1961
1962DEF_IE_ENCODE(net, eetd)
1963{
1964 return (uni_ie_encode_itu_eetd(msg, ie, cx));
1965}
1966
1967DEF_IE_DECODE(itu, eetd)
1968{
1969 IE_START(;);
1970
1971 while (ielen > 0) {
1972 switch (ielen--, *msg->b_rptr++) {
1973
1974 case UNI_EETD_CTD_ID:
1975 if (ielen < 2)
1976 goto rej;
1977 ie->h.present |= UNI_EETD_CUM_P;
1978 ie->cumulative = *msg->b_rptr++ << 8;
1979 ie->cumulative |= *msg->b_rptr++;
1980 ielen -= 2;
1981 break;
1982
1983 case UNI_EETD_MTD_ID:
1984 if (ielen < 2)
1985 goto rej;
1986 ie->h.present |= UNI_EETD_MAX_P;
1987 ie->maximum = *msg->b_rptr++ << 8;
1988 ie->maximum |= *msg->b_rptr++;
1989 ielen -= 2;
1990 break;
1991
1992 case UNI_EETD_PCTD_ID:
1993 if (ielen < 3)
1994 goto rej;
1995 ie->h.present |= UNI_EETD_PCTD_P;
1996 ie->pctd = *msg->b_rptr++ << 16;
1997 ie->pctd |= *msg->b_rptr++ << 8;
1998 ie->pctd |= *msg->b_rptr++;
1999 ielen -= 3;
2000 break;
2001
2002 case UNI_EETD_PMTD_ID:
2003 if (ielen < 3)
2004 goto rej;
2005 ie->h.present |= UNI_EETD_PMTD_P;
2006 ie->pmtd = *msg->b_rptr++ << 16;
2007 ie->pmtd |= *msg->b_rptr++ << 8;
2008 ie->pmtd |= *msg->b_rptr++;
2009 ielen -= 3;
2010 break;
2011
2012 case UNI_EETD_NET_ID:
2013 ie->h.present |= UNI_EETD_NET_P;
2014 break;
2015
2016 default:
2017 goto rej;
2018 }
2019 }
2020
2021 IE_END(EETD);
2022}
2023DEF_IE_DECODE(net, eetd)
2024{
2025 return (uni_ie_decode_itu_eetd(ie, msg, ielen, cx));
2026}
2027
2028/*********************************************************************
2029 *
2030 * Called address
2031 * Called subaddress
2032 * Calling address
2033 * Calling subaddress
2034 * Connected address
2035 * Connected subaddress
2036 *
2037 * References for this IE are:
2038 *
2039 * Q.2931 pp. 60...68
2040 * ...A4 pp. 27...36
2041 * UNI4.0 pp. 14...15
2042 * Q.2951 pp. 28...40
2043 *
2044 * It is assumed, that the coding of the addr arrays is ok.
2045 *
2046 * Only ITU-T coding allowed.
2047 */
2048
2049static const struct uni_print_tbl screen_tbl[] = {
2050 MKT(UNI_ADDR_SCREEN_NOT, no),
2051 MKT(UNI_ADDR_SCREEN_PASSED, passed),
2052 MKT(UNI_ADDR_SCREEN_FAILED, failed),
2053 MKT(UNI_ADDR_SCREEN_NET, network),
2054 EOT()
2055};
2056static const struct uni_print_tbl pres_tbl[] = {
2057 MKT(UNI_ADDR_PRES, allowed),
2058 MKT(UNI_ADDR_RESTRICT, restricted),
2059 MKT(UNI_ADDR_NONUMBER, no-number),
2060 EOT()
2061};
2062
2063
2064static void
2065print_addr(struct unicx *cx, struct uni_addr *addr)
2066{
2067 static const struct uni_print_tbl plan_tbl[] = {
2068 MKT(UNI_ADDR_UNKNOWN, unknown),
2069 MKT(UNI_ADDR_E164, E164),
2070 MKT(UNI_ADDR_ATME, ATME),
2071 MKT(UNI_ADDR_DATA, data),
2072 MKT(UNI_ADDR_PRIVATE, private),
2073 EOT()
2074 };
2075 static const struct uni_print_tbl type_tbl[] = {
2076 MKT(UNI_ADDR_UNKNOWN, unknown),
2077 MKT(UNI_ADDR_INTERNATIONAL, international),
2078 MKT(UNI_ADDR_NATIONAL, national),
2079 MKT(UNI_ADDR_NETWORK, network),
2080 MKT(UNI_ADDR_SUBSCR, subscriber),
2081 MKT(UNI_ADDR_ABBR, abbreviated),
2082 EOT()
2083 };
2084 u_int i;
2085
2086 uni_print_entry(cx, "addr", "(");
2087 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2088 uni_putc(',', cx);
2089 uni_print_tbl(NULL, addr->plan, plan_tbl, cx);
2090 uni_putc(',', cx);
2091 if(addr->plan == UNI_ADDR_E164) {
2092 uni_putc('"', cx);
2093 for(i = 0; i < addr->len; i++) {
2094 if(addr->addr[i] < ' ')
2095 uni_printf(cx, "^%c", addr->addr[i] + '@');
2096 else if(addr->addr[i] <= '~')
2097 uni_putc(addr->addr[i], cx);
2098 else
2099 uni_printf(cx, "\\%03o", addr->addr[i]);
2100 }
2101 uni_putc('"', cx);
2102
2103 } else if(addr->plan == UNI_ADDR_ATME) {
2104 for(i = 0; i < addr->len; i++)
2105 uni_printf(cx, "%02x", addr->addr[i]);
2106 }
2107 uni_putc(')', cx);
2108}
2109
2110static void
2111print_addrsub(struct unicx *cx, struct uni_subaddr *addr)
2112{
2113 static const struct uni_print_tbl type_tbl[] = {
2114 MKT(UNI_SUBADDR_NSAP, NSAP),
2115 MKT(UNI_SUBADDR_ATME, ATME),
2116 MKT(UNI_SUBADDR_USER, USER),
2117 EOT()
2118 };
2119 u_int i;
2120
2121 uni_print_entry(cx, "addr", "(");
2122 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2123 uni_putc(',', cx);
2124
2125 for(i = 0; i < addr->len; i++)
2126 uni_printf(cx, "%02x", addr->addr[i]);
2127
2128 uni_putc(')', cx);
2129}
2130
2131static int
2132check_addr(struct uni_addr *addr)
2133{
2134 u_int i;
2135
2136 switch(addr->plan) {
2137 default:
2138 return -1;
2139
2140 case UNI_ADDR_E164:
2141 if(addr->type != UNI_ADDR_INTERNATIONAL)
2142 return -1;
2143 if(addr->len > 15 || addr->len == 0)
2144 return -1;
2145 for(i = 0; i < addr->len; i++)
2146 if(addr->addr[i] == 0 || (addr->addr[i] & 0x80))
2147 return -1;
2148 break;
2149
2150 case UNI_ADDR_ATME:
2151 if(addr->type != UNI_ADDR_UNKNOWN)
2152 return -1;
2153 if(addr->len != 20)
2154 return -1;
2155 break;
2156 }
2157
2158 return 0;
2159}
2160
2161static int
2162check_subaddr(struct uni_subaddr *addr)
2163{
2164 switch(addr->type) {
2165 default:
2166 return -1;
2167
2168 case UNI_SUBADDR_NSAP:
2169 if(addr->len != 20)
2170 return -1;
2171 break;
2172
2173 case UNI_SUBADDR_ATME:
2174 if(addr->len > 20)
2175 return -1;
2176 break;
2177 }
2178 return 0;
2179}
2180
2181static int
2182check_screen(enum uni_addr_screen screen, enum uni_addr_pres pres)
2183{
2184 switch(pres) {
2185 default:
2186 return -1;
2187
2188 case UNI_ADDR_PRES:
2189 case UNI_ADDR_RESTRICT:
2190 case UNI_ADDR_NONUMBER:
2191 break;
2192 }
2193 switch(screen) {
2194 default:
2195 return -1;
2196
2197 case UNI_ADDR_SCREEN_NOT:
2198 case UNI_ADDR_SCREEN_PASSED:
2199 case UNI_ADDR_SCREEN_FAILED:
2200 case UNI_ADDR_SCREEN_NET:
2201 break;
2202 }
2203
2204 return 0;
2205}
2206
2207static void
2208encode_addr(struct uni_msg *msg, struct uni_addr *addr, u_int flag,
2209 enum uni_addr_screen screen, enum uni_addr_pres pres, int err)
2210{
2211 u_char ext = err ? 0x00 : 0x80;
2212
2213 if (flag) {
2214 APP_BYTE(msg, (addr->type << 4) | addr->plan);
2215 APP_BYTE(msg, ext | (pres << 5) | (screen));
2216 } else {
2217 APP_BYTE(msg, ext | (addr->type << 4) | addr->plan);
2218 }
2219 APP_BUF(msg, addr->addr, addr->len);
2220}
2221
2222static void
2223encode_subaddr(struct uni_msg *msg, struct uni_subaddr *addr)
2224{
2225 APP_BYTE(msg, 0x80|(addr->type<<4));
2226 APP_BUF(msg, addr->addr, addr->len);
2227}
2228
2229static int
2230decode_addr(struct uni_addr *addr, u_int ielen, struct uni_msg *msg, u_int plan)
2231{
2232 addr->plan = plan & 0xf;
2233 addr->type = (plan >> 4) & 0x7;
2234
2235 switch(addr->plan) {
2236
2237 case UNI_ADDR_E164:
2238 if(ielen > 15 || ielen == 0)
2239 return -1;
2240 addr->addr[ielen] = 0;
2241 break;
2242
2243 case UNI_ADDR_ATME:
2244 if(ielen != 20)
2245 return -1;
2246 break;
2247
2248 default:
2249 return -1;
2250 }
2251 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2252 addr->len = ielen;
2253 msg->b_rptr += ielen;
2254
2255 return 0;
2256}
2257
2258static int
2259decode_subaddr(struct uni_subaddr *addr, u_int ielen, struct uni_msg *msg,
2260 u_int type)
2261{
2262 switch(addr->type = (type >> 4) & 0x7) {
2263
2264 case UNI_SUBADDR_NSAP:
2265 if(ielen == 0 || ielen > 20)
2266 return -1;
2267 break;
2268
2269 case UNI_SUBADDR_ATME:
2270 if(ielen != 20)
2271 return -1;
2272 break;
2273
2274 default:
2275 return -1;
2276 }
2277 if(!(type & 0x80))
2278 return -1;
2279 if((type & 0x7) != 0)
2280 return -1;
2281
2282 addr->len = ielen;
2283 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2284 msg->b_rptr += ielen;
2285
2286 return 0;
2287}
2288
2289/**********************************************************************/
2290
2291DEF_IE_PRINT(itu, called)
2292{
2293 if (uni_print_iehdr("called", &ie->h, cx))
2294 return;
2295 print_addr(cx, &ie->addr);
2296 uni_print_ieend(cx);
2297}
2298
2299DEF_IE_CHECK(itu, called)
2300{
2301 cx = cx;
2302
2303 if (check_addr(&ie->addr))
2304 return (-1);
2305 return (0);
2306}
2307
2308DEF_IE_ENCODE(itu, called)
2309{
2310 START_IE(called, UNI_IE_CALLED, 21);
2311 encode_addr(msg, &ie->addr, 0, 0, 0, IE_ISERROR(*ie));
2312 SET_IE_LEN(msg);
2313 return (0);
2314}
2315
2316DEF_IE_DECODE(itu, called)
2317{
2318 u_char c;
2319 IE_START(;);
2320
2321 if (ielen > 21 || ielen < 1)
2322 goto rej;
2323
2324 c = *msg->b_rptr++;
2325 ielen--;
2326
2327 if (!(c & 0x80))
2328 goto rej;
2329
2330 if (decode_addr(&ie->addr, ielen, msg, c))
2331 goto rej;
2332
2333 IE_END(CALLED);
2334}
2335
2336/**********************************************************************/
2337
2338DEF_IE_PRINT(itu, calledsub)
2339{
2340 if(uni_print_iehdr("calledsub", &ie->h, cx))
2341 return;
2342 print_addrsub(cx, &ie->addr);
2343 uni_print_ieend(cx);
2344}
2345
2346DEF_IE_CHECK(itu, calledsub)
2347{
2348 cx = cx;
2349
2350 if(check_subaddr(&ie->addr))
2351 return -1;
2352 return 0;
2353}
2354
2355DEF_IE_ENCODE(itu, calledsub)
2356{
2357 START_IE(calledsub, UNI_IE_CALLEDSUB, 21);
2358 encode_subaddr(msg, &ie->addr);
2359 SET_IE_LEN(msg);
2360 return 0;
2361}
2362
2363DEF_IE_DECODE(itu, calledsub)
2364{
2365 u_char c;
2366
2367 IE_START(;);
2368
2369 if(ielen > 21)
2370 goto rej;
2371
2372 c = *msg->b_rptr++;
2373 ielen--;
2374
2375 if(decode_subaddr(&ie->addr, ielen, msg, c))
2376 goto rej;
2377
2378 IE_END(CALLEDSUB);
2379}
2380
2381/**********************************************************************/
2382
2383DEF_IE_PRINT(itu, calling)
2384{
2385 if(uni_print_iehdr("calling", &ie->h, cx))
2386 return;
2387 print_addr(cx, &ie->addr);
2388
2389 if(ie->h.present & UNI_CALLING_SCREEN_P) {
2390 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2391 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2392 }
2393
2394 uni_print_ieend(cx);
2395}
2396
2397DEF_IE_CHECK(itu, calling)
2398{
2399 cx = cx;
2400
2401 if(check_addr(&ie->addr))
2402 return -1;
2403
2404 if(ie->h.present & UNI_CALLING_SCREEN_P)
2405 if(check_screen(ie->screen, ie->pres))
2406 return -1;
2407 return 0;
2408}
2409
2410DEF_IE_ENCODE(itu, calling)
2411{
2412 START_IE(calling, UNI_IE_CALLING, 22);
2413 encode_addr(msg, &ie->addr, ie->h.present & UNI_CALLING_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2414 SET_IE_LEN(msg);
2415 return 0;
2416}
2417
2418DEF_IE_DECODE(itu, calling)
2419{
2420 u_char c, plan;
2421
2422 IE_START(;);
2423
2424 if(ielen > 22 || ielen < 1)
2425 goto rej;
2426
2427 plan = *msg->b_rptr++;
2428 ielen--;
2429
2430 if(!(plan & 0x80)) {
2431 if(ielen == 0)
2432 goto rej;
2433 ielen--;
2434 c = *msg->b_rptr++;
2435
2436 ie->h.present |= UNI_CALLING_SCREEN_P;
2437 ie->pres = (c >> 5) & 0x3;
2438 ie->screen = c & 0x3;
2439
2440 if(!(c & 0x80))
2441 goto rej;
2442 }
2443
2444 if(decode_addr(&ie->addr, ielen, msg, plan))
2445 goto rej;
2446
2447 IE_END(CALLING);
2448}
2449
2450/**********************************************************************/
2451
2452DEF_IE_PRINT(itu, callingsub)
2453{
2454 if(uni_print_iehdr("callingsub", &ie->h, cx))
2455 return;
2456 print_addrsub(cx, &ie->addr);
2457 uni_print_ieend(cx);
2458}
2459
2460DEF_IE_CHECK(itu, callingsub)
2461{
2462 cx = cx;
2463
2464 if(check_subaddr(&ie->addr))
2465 return -1;
2466 return 0;
2467}
2468
2469DEF_IE_ENCODE(itu, callingsub)
2470{
2471 START_IE(callingsub, UNI_IE_CALLINGSUB, 21);
2472 encode_subaddr(msg, &ie->addr);
2473 SET_IE_LEN(msg);
2474 return 0;
2475}
2476
2477DEF_IE_DECODE(itu, callingsub)
2478{
2479 u_char c;
2480
2481 IE_START(;);
2482
2483 if(ielen > 21)
2484 goto rej;
2485
2486 c = *msg->b_rptr++;
2487 ielen--;
2488
2489 if(decode_subaddr(&ie->addr, ielen, msg, c))
2490 goto rej;
2491
2492 IE_END(CALLINGSUB);
2493}
2494
2495/**********************************************************************/
2496
2497DEF_IE_PRINT(itu, conned)
2498{
2499 if(uni_print_iehdr("conned", &ie->h, cx))
2500 return;
2501 print_addr(cx, &ie->addr);
2502
2503 if(ie->h.present & UNI_CONNED_SCREEN_P) {
2504 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2505 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2506 }
2507
2508 uni_print_ieend(cx);
2509}
2510
2511DEF_IE_CHECK(itu, conned)
2512{
2513 cx = cx;
2514
2515 if(check_addr(&ie->addr))
2516 return -1;
2517
2518 if(ie->h.present & UNI_CONNED_SCREEN_P)
2519 if(check_screen(ie->screen, ie->pres))
2520 return -1;
2521 return 0;
2522}
2523
2524DEF_IE_ENCODE(itu, conned)
2525{
2526 START_IE(conned, UNI_IE_CONNED, 22);
2527 encode_addr(msg, &ie->addr, ie->h.present & UNI_CONNED_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2528 SET_IE_LEN(msg);
2529 return 0;
2530}
2531
2532DEF_IE_DECODE(itu, conned)
2533{
2534 u_char c, plan;
2535
2536 IE_START(;);
2537
2538 if(ielen > 22 || ielen < 1)
2539 goto rej;
2540
2541 plan = *msg->b_rptr++;
2542 ielen--;
2543
2544 if(!(plan & 0x80)) {
2545 if(ielen == 0)
2546 goto rej;
2547 ielen--;
2548 c = *msg->b_rptr++;
2549
2550 ie->h.present |= UNI_CONNED_SCREEN_P;
2551 ie->pres = (c >> 5) & 0x3;
2552 ie->screen = c & 0x3;
2553
2554 if(!(c & 0x80))
2555 goto rej;
2556 }
2557
2558 if(decode_addr(&ie->addr, ielen, msg, plan))
2559 goto rej;
2560
2561 IE_END(CONNED);
2562}
2563
2564/**********************************************************************/
2565
2566DEF_IE_PRINT(itu, connedsub)
2567{
2568 if(uni_print_iehdr("connedsub", &ie->h, cx))
2569 return;
2570 print_addrsub(cx, &ie->addr);
2571 uni_print_ieend(cx);
2572}
2573
2574DEF_IE_CHECK(itu, connedsub)
2575{
2576 cx = cx;
2577
2578 if(check_subaddr(&ie->addr))
2579 return -1;
2580 return 0;
2581}
2582
2583DEF_IE_ENCODE(itu, connedsub)
2584{
2585 START_IE(connedsub, UNI_IE_CONNEDSUB, 21);
2586 encode_subaddr(msg, &ie->addr);
2587 SET_IE_LEN(msg);
2588 return 0;
2589}
2590
2591DEF_IE_DECODE(itu, connedsub)
2592{
2593 u_char c;
2594
2595 IE_START(;);
2596
2597 if(ielen > 21)
2598 goto rej;
2599
2600 c = *msg->b_rptr++;
2601 ielen--;
2602
2603 if(decode_subaddr(&ie->addr, ielen, msg, c))
2604 goto rej;
2605
2606 IE_END(CONNEDSUB);
2607}
2608
2609/*********************************************************************
2610 *
2611 * Endpoint reference.
2612 *
2613 * References for this IE are:
2614 *
2615 * Q.2971 p. 14
2616 *
2617 * Only ITU-T coding allowed.
2618 */
2619
2620DEF_IE_PRINT(itu, epref)
2621{
2622 if(uni_print_iehdr("epref", &ie->h, cx))
2623 return;
2624 uni_print_entry(cx, "epref", "(%u,%u)", ie->flag, ie->epref);
2625 uni_print_ieend(cx);
2626}
2627
2628DEF_IE_CHECK(itu, epref)
2629{
2630 cx = cx;
2631
2632 if(ie->epref >= (2<<15))
2633 return -1;
2634
2635 return 0;
2636}
2637
2638DEF_IE_ENCODE(itu, epref)
2639{
2640 START_IE(epref, UNI_IE_EPREF, 3);
2641
2642 if (IE_ISERROR(*ie))
2643 APP_BYTE(msg, 0xff);
2644 else
2645 APP_BYTE(msg, 0);
2646 APP_BYTE(msg, (ie->flag << 7) | ((ie->epref >> 8) & 0x7f));
2647 APP_BYTE(msg, (ie->epref & 0xff));
2648
2649 SET_IE_LEN(msg);
2650 return 0;
2651}
2652
2653DEF_IE_DECODE(itu, epref)
2654{
2655 u_char c;
2656
2657 IE_START(;);
2658
2659 if(ielen != 3)
2660 goto rej;
2661 if(*msg->b_rptr++ != 0)
2662 goto rej;
2663
2664 c = *msg->b_rptr++;
2665 ie->flag = (c & 0x80) ? 1 : 0;
2666 ie->epref = (c & 0x7f) << 8;
2667 ie->epref |= *msg->b_rptr++;
2668
2669 IE_END(EPREF);
2670}
2671
2672/*********************************************************************
2673 *
2674 * Endpoint state.
2675 *
2676 * References for this IE are:
2677 *
2678 * Q.2971 pp. 14...15
2679 *
2680 * Only ITU-T coding allowed.
2681 */
2682
2683DEF_IE_PRINT(itu, epstate)
2684{
2685 static const struct uni_print_tbl tbl[] = {
2686 MKT(UNI_EPSTATE_NULL, null),
2687 MKT(UNI_EPSTATE_ADD_INIT, add-initiated),
2688 MKT(UNI_EPSTATE_ALERT_DLVD, alerting-delivered),
2689 MKT(UNI_EPSTATE_ADD_RCVD, add-received),
2690 MKT(UNI_EPSTATE_ALERT_RCVD, alerting-received),
2691 MKT(UNI_EPSTATE_ACTIVE, active),
2692 MKT(UNI_EPSTATE_DROP_INIT, drop-initiated),
2693 MKT(UNI_EPSTATE_DROP_RCVD, drop-received),
2694 EOT()
2695 };
2696
2697 if(uni_print_iehdr("epstate", &ie->h, cx))
2698 return;
2699 uni_print_tbl("state", ie->state, tbl, cx);
2700 uni_print_ieend(cx);
2701}
2702
2703DEF_IE_CHECK(itu, epstate)
2704{
2705 cx = cx;
2706
2707 switch(ie->state) {
2708 default:
2709 return -1;
2710
2711 case UNI_EPSTATE_NULL:
2712 case UNI_EPSTATE_ADD_INIT:
2713 case UNI_EPSTATE_ALERT_DLVD:
2714 case UNI_EPSTATE_ADD_RCVD:
2715 case UNI_EPSTATE_ALERT_RCVD:
2716 case UNI_EPSTATE_DROP_INIT:
2717 case UNI_EPSTATE_DROP_RCVD:
2718 case UNI_EPSTATE_ACTIVE:
2719 break;
2720 }
2721
2722 return 0;
2723}
2724
2725DEF_IE_ENCODE(itu, epstate)
2726{
2727 START_IE(epstate, UNI_IE_EPSTATE, 1);
2728
2729 APP_BYTE(msg, ie->state);
2730
2731 SET_IE_LEN(msg);
2732 return 0;
2733}
2734
2735DEF_IE_DECODE(itu, epstate)
2736{
2737 IE_START(;);
2738
2739 if(ielen != 1)
2740 goto rej;
2741
2742 ie->state = *msg->b_rptr++ & 0x3f;
2743
2744 IE_END(EPSTATE);
2745}
2746
2747/*********************************************************************
2748 *
2749 * ATM adaptation layer parameters
2750 *
2751 * References for this IE are:
2752 *
2753 * Q.2931 pp. 43...49
2754 * Q.2931 Amd 2
2755 * UNI4.0 p. 9
2756 *
2757 * UNI4.0 states, that AAL2 is not supported. However we keep it. No
2758 * parameters are associated with AAL2.
2759 *
2760 * Amd2 not checked. XXX
2761 *
2762 * Only ITU-T coding allowed.
2763 */
2764DEF_IE_PRINT(itu, aal)
2765{
2766 static const struct uni_print_tbl aal_tbl[] = {
2767 MKT(UNI_AAL_0, VOICE),
2768 MKT(UNI_AAL_1, 1),
2769 MKT(UNI_AAL_2, 2),
2770 MKT(UNI_AAL_4, 3/4),
2771 MKT(UNI_AAL_5, 5),
2772 MKT(UNI_AAL_USER, USER),
2773 EOT()
2774 };
2775 static const struct uni_print_tbl subtype_tbl[] = {
2776 MKT(UNI_AAL1_SUB_NULL, null),
2777 MKT(UNI_AAL1_SUB_VOICE, voice),
2778 MKT(UNI_AAL1_SUB_CIRCUIT, circuit),
2779 MKT(UNI_AAL1_SUB_HQAUDIO, hqaudio),
2780 MKT(UNI_AAL1_SUB_VIDEO, video),
2781 EOT()
2782 };
2783 static const struct uni_print_tbl cbr_rate_tbl[] = {
2784 MKT(UNI_AAL1_CBR_64, 64),
2785 MKT(UNI_AAL1_CBR_1544, 1544(DS1)),
2786 MKT(UNI_AAL1_CBR_6312, 6312(DS2)),
2787 MKT(UNI_AAL1_CBR_32064, 32064),
2788 MKT(UNI_AAL1_CBR_44736, 44736(DS3)),
2789 MKT(UNI_AAL1_CBR_97728, 97728),
2790 MKT(UNI_AAL1_CBR_2048, 2048(E1)),
2791 MKT(UNI_AAL1_CBR_8448, 8448(E2)),
2792 MKT(UNI_AAL1_CBR_34368, 34368(E3)),
2793 MKT(UNI_AAL1_CBR_139264, 139264),
2794 MKT(UNI_AAL1_CBR_N64, Nx64),
2795 MKT(UNI_AAL1_CBR_N8, Nx8),
2796 EOT()
2797 };
2798 static const struct uni_print_tbl screc_tbl[] = {
2799 MKT(UNI_AAL1_SCREC_NULL, null),
2800 MKT(UNI_AAL1_SCREC_SRTS, srts),
2801 MKT(UNI_AAL1_SCREC_ACLK, aclk),
2802 EOT()
2803 };
2804 static const struct uni_print_tbl ecm_tbl[] = {
2805 MKT(UNI_AAL1_ECM_NULL, null),
2806 MKT(UNI_AAL1_ECM_LOSS, loss),
2807 MKT(UNI_AAL1_ECM_DELAY, delay),
2808 EOT()
2809 };
2810 static const struct uni_print_tbl sscs_tbl[] = {
2811 MKT(UNI_AAL_SSCS_NULL, null),
2812 MKT(UNI_AAL_SSCS_SSCOPA, sscopa),
2813 MKT(UNI_AAL_SSCS_SSCOPU, sscopu),
2814 MKT(UNI_AAL_SSCS_FRAME, frame),
2815 EOT()
2816 };
2817
2818 if(uni_print_iehdr("aal", &ie->h, cx))
2819 return;
2820 uni_print_tbl("type", ie->type, aal_tbl, cx);
2821
2822 switch(ie->type) {
2823
2824 case UNI_AAL_0:
2825 uni_print_push_prefix("0", cx);
2826 cx->indent++;
2827 break;
2828
2829 case UNI_AAL_2:
2830 uni_print_push_prefix("2", cx);
2831 cx->indent++;
2832 break;
2833
2834 case UNI_AAL_1:
2835 uni_print_push_prefix("1", cx);
2836 cx->indent++;
2837 uni_print_tbl("subtype", ie->u.aal1.subtype, subtype_tbl, cx);
2838 uni_print_tbl("cbr_rate", ie->u.aal1.cbr_rate, cbr_rate_tbl, cx);
2839 if(ie->h.present & UNI_AAL1_MULT_P)
2840 uni_print_entry(cx, "mult", "%u", ie->u.aal1.mult);
2841 if(ie->h.present & UNI_AAL1_SCREC_P)
2842 uni_print_tbl("screc", ie->u.aal1.screc, screc_tbl, cx);
2843 if(ie->h.present & UNI_AAL1_ECM_P)
2844 uni_print_tbl("ecm", ie->u.aal1.ecm, ecm_tbl, cx);
2845 if(ie->h.present & UNI_AAL1_BSIZE_P)
2846 uni_print_entry(cx, "bsize", "%u", ie->u.aal1.bsize);
2847 if(ie->h.present & UNI_AAL1_PART_P)
2848 uni_print_entry(cx, "part", "%u", ie->u.aal1.part);
2849 break;
2850
2851 case UNI_AAL_4:
2852 uni_print_push_prefix("4", cx);
2853 cx->indent++;
2854 if(ie->h.present & UNI_AAL4_CPCS_P)
2855 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal4.fwd_cpcs,
2856 ie->u.aal4.bwd_cpcs);
2857 if(ie->h.present & UNI_AAL4_MID_P)
2858 uni_print_entry(cx, "mid", "(%u,%u)", ie->u.aal4.mid_low,
2859 ie->u.aal4.mid_high);
2860 if(ie->h.present & UNI_AAL4_SSCS_P)
2861 uni_print_tbl("sscs", ie->u.aal4.sscs, sscs_tbl, cx);
2862 break;
2863
2864 case UNI_AAL_5:
2865 uni_print_push_prefix("5", cx);
2866 cx->indent++;
2867 if(ie->h.present & UNI_AAL5_CPCS_P)
2868 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal5.fwd_cpcs,
2869 ie->u.aal5.bwd_cpcs);
2870 if(ie->h.present & UNI_AAL5_SSCS_P)
2871 uni_print_tbl("sscs", ie->u.aal5.sscs, sscs_tbl, cx);
2872 break;
2873
2874 case UNI_AAL_USER:
2875 uni_print_push_prefix("user", cx);
2876 cx->indent++;
2877 if(ie->u.aalu.len > 4) {
2878 uni_print_entry(cx, "info", "ERROR(len=%u)", ie->u.aalu.len);
2879 } else {
2880 u_int i;
2881
2882 uni_print_entry(cx, "info", "(");
2883 for(i = 0; i < ie->u.aalu.len; i++)
2884 uni_printf(cx, "%s%u", !i?"":",", ie->u.aalu.user[i]);
2885 uni_printf(cx, ")");
2886 }
2887 break;
2888 }
2889 cx->indent--;
2890 uni_print_pop_prefix(cx);
2891 uni_print_eol(cx);
2892
2893 uni_print_ieend(cx);
2894}
2895
2896DEF_IE_CHECK(itu, aal)
2897{
2898 cx = cx;
2899
2900 if(ie->type == UNI_AAL_0) {
2901 ;
2902 } else if(ie->type == UNI_AAL_1) {
2903 switch(ie->u.aal1.subtype) {
2904
2905 default:
2906 return -1;
2907
2908 case UNI_AAL1_SUB_NULL:
2909 case UNI_AAL1_SUB_VOICE:
2910 case UNI_AAL1_SUB_CIRCUIT:
2911 case UNI_AAL1_SUB_HQAUDIO:
2912 case UNI_AAL1_SUB_VIDEO:
2913 break;
2914 }
2915 switch(ie->u.aal1.cbr_rate) {
2916
2917 default:
2918 return -1;
2919
2920 case UNI_AAL1_CBR_64:
2921 case UNI_AAL1_CBR_1544:
2922 case UNI_AAL1_CBR_6312:
2923 case UNI_AAL1_CBR_32064:
2924 case UNI_AAL1_CBR_44736:
2925 case UNI_AAL1_CBR_97728:
2926 case UNI_AAL1_CBR_2048:
2927 case UNI_AAL1_CBR_8448:
2928 case UNI_AAL1_CBR_34368:
2929 case UNI_AAL1_CBR_139264:
2930 if((ie->h.present & UNI_AAL1_MULT_P))
2931 return -1;
2932 break;
2933
2934 case UNI_AAL1_CBR_N64:
2935 if(!(ie->h.present & UNI_AAL1_MULT_P))
2936 return -1;
2937 if(ie->u.aal1.mult < 2)
2938 return -1;
2939 break;
2940
2941 case UNI_AAL1_CBR_N8:
2942 if(!(ie->h.present & UNI_AAL1_MULT_P))
2943 return -1;
2944 if(ie->u.aal1.mult == 0 || ie->u.aal1.mult > 7)
2945 return -1;
2946 break;
2947 }
2948 if(ie->h.present & UNI_AAL1_SCREC_P) {
2949 switch(ie->u.aal1.screc) {
2950
2951 default:
2952 return -1;
2953
2954 case UNI_AAL1_SCREC_NULL:
2955 case UNI_AAL1_SCREC_SRTS:
2956 case UNI_AAL1_SCREC_ACLK:
2957 break;
2958 }
2959 }
2960 if(ie->h.present & UNI_AAL1_ECM_P) {
2961 switch(ie->u.aal1.ecm) {
2962
2963 default:
2964 return -1;
2965
2966 case UNI_AAL1_ECM_NULL:
2967 case UNI_AAL1_ECM_LOSS:
2968 case UNI_AAL1_ECM_DELAY:
2969 break;
2970 }
2971 }
2972 if(ie->h.present & UNI_AAL1_BSIZE_P) {
2973 if(ie->u.aal1.bsize == 0)
2974 return -1;
2975 }
2976 if(ie->h.present & UNI_AAL1_PART_P) {
2977 if(ie->u.aal1.part == 0 || ie->u.aal1.part > 47)
2978 return -1;
2979 }
2980
2981 } else if(ie->type == UNI_AAL_2) {
2982 ;
2983
2984 } else if(ie->type == UNI_AAL_4) {
2985 if(ie->h.present & UNI_AAL4_MID_P) {
2986 if(ie->u.aal4.mid_low >= 1024)
2987 return -1;
2988 if(ie->u.aal4.mid_high >= 1024)
2989 return -1;
2990 if(ie->u.aal4.mid_low > ie->u.aal4.mid_high)
2991 return -1;
2992 }
2993 if(ie->h.present & UNI_AAL4_SSCS_P) {
2994 switch(ie->u.aal4.sscs) {
2995
2996 default:
2997 return -1;
2998
2999 case UNI_AAL_SSCS_NULL:
3000 case UNI_AAL_SSCS_SSCOPA:
3001 case UNI_AAL_SSCS_SSCOPU:
3002 case UNI_AAL_SSCS_FRAME:
3003 break;
3004 }
3005 }
3006
3007 } else if(ie->type == UNI_AAL_5) {
3008 if(ie->h.present & UNI_AAL5_SSCS_P) {
3009 switch(ie->u.aal5.sscs) {
3010
3011 default:
3012 return -1;
3013
3014 case UNI_AAL_SSCS_NULL:
3015 case UNI_AAL_SSCS_SSCOPA:
3016 case UNI_AAL_SSCS_SSCOPU:
3017 case UNI_AAL_SSCS_FRAME:
3018 break;
3019 }
3020 }
3021
3022 } else if(ie->type == UNI_AAL_USER) {
3023 if(ie->u.aalu.len > 4)
3024 return -1;
3025
3026 } else
3027 return -1;
3028
3029 return 0;
3030}
3031
3032DEF_IE_ENCODE(itu, aal)
3033{
3034 START_IE(aal, UNI_IE_AAL, 16);
3035
3036 APP_BYTE(msg, ie->type);
3037 switch(ie->type) {
3038
3039 case UNI_AAL_0:
3040 break;
3041
3042 case UNI_AAL_1:
3043 APP_SUB_BYTE(msg,
3044 UNI_AAL_SUB_ID, ie->u.aal1.subtype);
3045 APP_SUB_BYTE(msg,
3046 UNI_AAL_CBR_ID, ie->u.aal1.cbr_rate);
3047 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_MULT_P,
3048 UNI_AAL_MULT_ID, ie->u.aal1.mult);
3049 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_SCREC_P,
3050 UNI_AAL_SCREC_ID, ie->u.aal1.screc);
3051 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_ECM_P,
3052 UNI_AAL_ECM_ID, ie->u.aal1.ecm);
3053 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_BSIZE_P,
3054 UNI_AAL_BSIZE_ID, ie->u.aal1.bsize);
3055 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_PART_P,
3056 UNI_AAL_PART_ID, ie->u.aal1.part);
3057 break;
3058
3059 case UNI_AAL_2:
3060 break;
3061
3062 case UNI_AAL_4:
3063 if(ie->h.present & UNI_AAL4_CPCS_P) {
3064 APP_SUB_16BIT(msg,
3065 UNI_AAL_FWDCPCS_ID, ie->u.aal4.fwd_cpcs);
3066 APP_SUB_16BIT(msg,
3067 UNI_AAL_BWDCPCS_ID, ie->u.aal4.bwd_cpcs);
3068 }
3069 if(ie->h.present & UNI_AAL4_MID_P) {
3070 APP_BYTE(msg, UNI_AAL_MID_ID);
3071 APP_16BIT(msg, ie->u.aal4.mid_low);
3072 APP_16BIT(msg, ie->u.aal4.mid_high);
3073 }
3074 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL4_SSCS_P,
3075 UNI_AAL_SSCS_ID, ie->u.aal4.sscs);
3076 break;
3077
3078 case UNI_AAL_5:
3079 if(ie->h.present & UNI_AAL5_CPCS_P) {
3080 APP_SUB_16BIT(msg,
3081 UNI_AAL_FWDCPCS_ID, ie->u.aal5.fwd_cpcs);
3082 APP_SUB_16BIT(msg,
3083 UNI_AAL_BWDCPCS_ID, ie->u.aal5.bwd_cpcs);
3084 }
3085 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL5_SSCS_P,
3086 UNI_AAL_SSCS_ID, ie->u.aal5.sscs);
3087 break;
3088
3089 case UNI_AAL_USER:
3090 APP_BUF(msg, ie->u.aalu.user, ie->u.aalu.len);
3091 break;
3092
3093 default:
3094 return -1;
3095 }
3096
3097 SET_IE_LEN(msg);
3098 return 0;
3099}
3100
3101/*
3102 * XXX What should we do with multiple subtype occurences? Ignore
3103 * or reject. Currently we reject.
3104 */
3105static int
3106decode_aal_1(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3107{
3108 int subtype_p, cbr_p;
3109
3110 subtype_p = cbr_p = 0;
3111
3112 while(ielen-- > 0) {
3113 switch(*msg->b_rptr++) {
3114
3115 case UNI_AAL_SUB_ID:
3116 if(ielen == 0 || subtype_p)
3117 return -1;
3118 ielen--;
3119 subtype_p = 1;
3120 ie->u.aal1.subtype = *msg->b_rptr++;
3121 break;
3122
3123 case UNI_AAL_CBR_ID:
3124 if(ielen == 0 || cbr_p)
3125 return -1;
3126 ielen--;
3127 cbr_p = 1;
3128 ie->u.aal1.cbr_rate = *msg->b_rptr++;
3129 break;
3130
3131 case UNI_AAL_MULT_ID:
3132 if(ielen < 2 || (ie->h.present & UNI_AAL1_MULT_P))
3133 return -1;
3134 ielen -= 2;
3135 ie->h.present |= UNI_AAL1_MULT_P;
3136 ie->u.aal1.mult = *msg->b_rptr++ << 8;
3137 ie->u.aal1.mult |= *msg->b_rptr++;
3138 break;
3139
3140 case UNI_AAL_SCREC_ID:
3141 if(ielen == 0 || (ie->h.present & UNI_AAL1_SCREC_P))
3142 return -1;
3143 ielen--;
3144 ie->h.present |= UNI_AAL1_SCREC_P;
3145 ie->u.aal1.screc = *msg->b_rptr++;
3146 break;
3147
3148 case UNI_AAL_ECM_ID:
3149 if(ielen == 0 || (ie->h.present & UNI_AAL1_ECM_P))
3150 return -1;
3151 ielen--;
3152 ie->h.present |= UNI_AAL1_ECM_P;
3153 ie->u.aal1.ecm = *msg->b_rptr++;
3154 break;
3155
3156 case UNI_AAL_BSIZE_ID:
3157 if(ielen < 2 || (ie->h.present & UNI_AAL1_BSIZE_P))
3158 return -1;
3159 ielen -= 2;
3160 ie->h.present |= UNI_AAL1_BSIZE_P;
3161 ie->u.aal1.bsize = *msg->b_rptr++ << 8;
3162 ie->u.aal1.bsize |= *msg->b_rptr++;
3163 break;
3164
3165 case UNI_AAL_PART_ID:
3166 if(ielen == 0 || (ie->h.present & UNI_AAL1_PART_P))
3167 return -1;
3168 ielen--;
3169 ie->h.present |= UNI_AAL1_PART_P;
3170 ie->u.aal1.part = *msg->b_rptr++;
3171 break;
3172
3173 default:
3174 return -1;
3175 }
3176 }
3177 if(!subtype_p || !cbr_p)
3178 return -1;
3179
3180 return 0;
3181}
3182
3183static int
3184decode_aal_4(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3185{
3186 int fcpcs_p, bcpcs_p;
3187
3188 fcpcs_p = bcpcs_p = 0;
3189
3190 while(ielen-- > 0) {
3191 switch(*msg->b_rptr++) {
3192
3193 case UNI_AAL_FWDCPCS_ID:
3194 if(ielen < 2 || fcpcs_p)
3195 return -1;
3196 ielen -= 2;
3197 fcpcs_p = 1;
3198 ie->u.aal4.fwd_cpcs = *msg->b_rptr++ << 8;
3199 ie->u.aal4.fwd_cpcs |= *msg->b_rptr++;
3200 break;
3201
3202 case UNI_AAL_BWDCPCS_ID:
3203 if(ielen < 2 || bcpcs_p)
3204 return -1;
3205 ielen -= 2;
3206 bcpcs_p = 1;
3207 ie->u.aal4.bwd_cpcs = *msg->b_rptr++ << 8;
3208 ie->u.aal4.bwd_cpcs |= *msg->b_rptr++;
3209 break;
3210
3211 case UNI_AAL_MID_ID:
3212 if(ielen < 4 || (ie->h.present & UNI_AAL4_MID_P))
3213 return -1;
3214 ielen -= 4;
3215 ie->h.present |= UNI_AAL4_MID_P;
3216 ie->u.aal4.mid_low = *msg->b_rptr++ << 8;
3217 ie->u.aal4.mid_low |= *msg->b_rptr++;
3218 ie->u.aal4.mid_high = *msg->b_rptr++ << 8;
3219 ie->u.aal4.mid_high |= *msg->b_rptr++;
3220 break;
3221
3222 case UNI_AAL_SSCS_ID:
3223 if(ielen == 0 || (ie->h.present & UNI_AAL4_SSCS_P))
3224 return -1;
3225 ielen--;
3226 ie->h.present |= UNI_AAL4_SSCS_P;
3227 ie->u.aal4.sscs = *msg->b_rptr++;
3228 break;
3229
3230 default:
3231 return -1;
3232 }
3233 }
3234
3235 if(fcpcs_p ^ bcpcs_p)
3236 return -1;
3237 if(fcpcs_p)
3238 ie->h.present |= UNI_AAL4_CPCS_P;
3239
3240 return 0;
3241}
3242
3243static int
3244decode_aal_5(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3245{
3246 int fcpcs_p, bcpcs_p;
3247
3248 fcpcs_p = bcpcs_p = 0;
3249
3250 while(ielen-- > 0) {
3251 switch(*msg->b_rptr++) {
3252
3253 case UNI_AAL_FWDCPCS_ID:
3254 if(ielen < 2 || fcpcs_p)
3255 return -1;
3256 ielen -= 2;
3257 fcpcs_p = 1;
3258 ie->u.aal5.fwd_cpcs = *msg->b_rptr++ << 8;
3259 ie->u.aal5.fwd_cpcs |= *msg->b_rptr++;
3260 break;
3261
3262 case UNI_AAL_BWDCPCS_ID:
3263 if(ielen < 2 || bcpcs_p)
3264 return -1;
3265 ielen -= 2;
3266 bcpcs_p = 1;
3267 ie->u.aal5.bwd_cpcs = *msg->b_rptr++ << 8;
3268 ie->u.aal5.bwd_cpcs |= *msg->b_rptr++;
3269 break;
3270
3271 case UNI_AAL_SSCS_ID:
3272 if(ielen == 0 || (ie->h.present & UNI_AAL5_SSCS_P))
3273 return -1;
3274 ielen--;
3275 ie->h.present |= UNI_AAL5_SSCS_P;
3276 ie->u.aal5.sscs = *msg->b_rptr++;
3277 break;
3278
3279 default:
3280 return -1;
3281 }
3282 }
3283
3284 if(fcpcs_p ^ bcpcs_p)
3285 return -1;
3286 if(fcpcs_p)
3287 ie->h.present |= UNI_AAL5_CPCS_P;
3288
3289 return 0;
3290}
3291
3292static int
3293decode_aal_user(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3294{
3295 if(ielen > 4)
3296 return -1;
3297
3298 ie->u.aalu.len = 0;
3299 while(ielen--)
3300 ie->u.aalu.user[ie->u.aalu.len++] = *msg->b_rptr++;
3301
3302 return 0;
3303}
3304
3305DEF_IE_DECODE(itu, aal)
3306{
3307 u_char c;
3308
3309 IE_START(DISC_ACC_ERR(AAL));
3310
3311 if(ielen < 1 || ielen > 21)
3312 goto rej;
3313
3314 c = *msg->b_rptr++;
3315 ielen--;
3316
3317 switch(c) {
3318
3319 case UNI_AAL_0:
3320 ie->type = c;
3321 break;
3322
3323 case UNI_AAL_1:
3324 ie->type = c;
3325 if(decode_aal_1(ie, msg, ielen))
3326 goto rej;
3327 break;
3328
3329 case UNI_AAL_2:
3330 ie->type = c;
3331 break;
3332
3333 case UNI_AAL_4:
3334 ie->type = c;
3335 if(decode_aal_4(ie, msg, ielen))
3336 goto rej;
3337 break;
3338
3339 case UNI_AAL_5:
3340 ie->type = c;
3341 if(decode_aal_5(ie, msg, ielen))
3342 goto rej;
3343 break;
3344
3345 case UNI_AAL_USER:
3346 ie->type = c;
3347 if(decode_aal_user(ie, msg, ielen))
3348 goto rej;
3349 break;
3350
3351 default:
3352 goto rej;
3353 }
3354
3355 IE_END(AAL);
3356}
3357
3358/*********************************************************************
3359 *
3360 * Traffic descriptor.
3361 * Alternate traffic descriptor.
3362 * Minimum traffic descriptor.
3363 *
3364 * References for this IE are:
3365 *
3366 * Q.2931 pp. 49...51
3367 * Q.2961
3368 * Q.2962
3369 * UNI4.0 pp. 9...10, 106...109
3370 *
3371 * The Q.s specify the coding. UNI4.0 adds frame discard and best-effort.
3372 * Appendix in UNI4.0 lists the allowed combinations.
3373 *
3374 * PCR0 PCR1 SCR/MBS0 SCR/MBS1 BE TAG FDISC ABR
3375 * 1 CBR.1 - Y - - - N Y/N -
3376 * 2 CBR.2 - Y - - - N Y/N - (*)
3377 * 3 CBR.3 Y Y - - - Y Y/N - (*)
3378 * 4 rt-VBR.1 - Y - Y - N Y/N -
3379 * 5 rt-VBR.2 - Y Y - - N Y/N -
3380 * 6 rt-VBR.3 - Y Y - - Y Y/N -
3381 * 7 rt-VBR.4 Y Y - - - Y/N Y/N - (*)
3382 * 8 rt-VBR.5 - Y - - - N Y/N - (*)
3383 * 9 rt-VBR.6 - Y - Y - N Y/N - (*)
3384 * 10 nrt-VBR.1 - Y - Y - N Y/N -
3385 * 11 nrt-VBR.2 - Y Y - - N Y/N -
3386 * 12 nrt-VBR.3 - Y Y - - Y Y/N -
3387 * 13 nrt-VBR.4 Y Y - - - Y/N Y/N - (*)
3388 * 14 nrt-VBR.5 - Y - - - N Y/N - (*)
3389 * 15 nrt-VBR.6 - Y - Y - N Y/N - (*)
3390 * 16 ABR - Y - - - N Y/N O (*)
3391 * 17 UBR.1 - Y - - Y N Y/N -
3392 * 18 UBR.2 - Y - - Y Y Y/N -
3393 *
3394 * Allow ITU-T and NET coding, because its not clear, whether the
3395 * new fields in UNI4.0 should be used with NET coding or not.
3396 * Does not allow for experimental codings yet.
3397 */
3398
3399static void
3400print_ie_traffic_common(struct unicx *cx, u_int present, struct uni_xtraffic *ie)
3401{
3402 uni_print_entry(cx, "fwd", "(");
3403 if(present & UNI_TRAFFIC_FPCR0_P)
3404 uni_printf(cx, "%u", ie->fpcr0);
3405 uni_putc(',', cx);
3406 if(present & UNI_TRAFFIC_FPCR1_P)
3407 uni_printf(cx, "%u", ie->fpcr1);
3408 uni_putc(',', cx);
3409 if(present & UNI_TRAFFIC_FSCR0_P)
3410 uni_printf(cx, "%u", ie->fscr0);
3411 uni_putc(',', cx);
3412 if(present & UNI_TRAFFIC_FSCR1_P)
3413 uni_printf(cx, "%u", ie->fscr1);
3414 uni_putc(',', cx);
3415 if(present & UNI_TRAFFIC_FMBS0_P)
3416 uni_printf(cx, "%u", ie->fmbs0);
3417 uni_putc(',', cx);
3418 if(present & UNI_TRAFFIC_FMBS1_P)
3419 uni_printf(cx, "%u", ie->fmbs1);
3420 uni_putc(',', cx);
3421 if(present & UNI_TRAFFIC_FABR1_P)
3422 uni_printf(cx, "%u", ie->fabr1);
3423 uni_printf(cx, ")");
3424
3425 uni_print_entry(cx, "bwd", "(");
3426 if(present & UNI_TRAFFIC_BPCR0_P)
3427 uni_printf(cx, "%u", ie->bpcr0);
3428 uni_putc(',', cx);
3429 if(present & UNI_TRAFFIC_BPCR1_P)
3430 uni_printf(cx, "%u", ie->bpcr1);
3431 uni_putc(',', cx);
3432 if(present & UNI_TRAFFIC_BSCR0_P)
3433 uni_printf(cx, "%u", ie->bscr0);
3434 uni_putc(',', cx);
3435 if(present & UNI_TRAFFIC_BSCR1_P)
3436 uni_printf(cx, "%u", ie->bscr1);
3437 uni_putc(',', cx);
3438 if(present & UNI_TRAFFIC_BMBS0_P)
3439 uni_printf(cx, "%u", ie->bmbs0);
3440 uni_putc(',', cx);
3441 if(present & UNI_TRAFFIC_BMBS1_P)
3442 uni_printf(cx, "%u", ie->bmbs1);
3443 uni_putc(',', cx);
3444 if(present & UNI_TRAFFIC_BABR1_P)
3445 uni_printf(cx, "%u", ie->babr1);
3446 uni_printf(cx, ")");
3447
3448 if(present & UNI_TRAFFIC_BEST_P)
3449 uni_print_flag("best_effort", cx);
3450 if(present & UNI_TRAFFIC_MOPT_P) {
3451 uni_print_entry(cx, "tag", "(");
3452 if(ie->ftag)
3453 uni_printf(cx, "fwd");
3454 uni_putc(',', cx);
3455 if(ie->btag)
3456 uni_printf(cx, "bwd");
3457 uni_putc(')', cx);
3458
3459 uni_print_entry(cx, "disc", "(");
3460 if(ie->fdisc)
3461 uni_printf(cx, "fwd");
3462 uni_putc(',', cx);
3463 if(ie->bdisc)
3464 uni_printf(cx, "bwd");
3465 uni_putc(')', cx);
3466 }
3467}
3468
3469struct tallow {
3470 u_int mask;
3471 int mopt_flag;
3472 u_char mopt_mask, mopt_val;
3473};
3474
3475static int
3476check_traffic(u_int mask, u_int mopt, struct tallow *a)
3477{
3478 if(mask != a->mask)
3479 return 0;
3480
3481 if(a->mopt_flag == 0) {
3482 /* not allowed */
3483 if(mopt == 0xffff)
3484 return 1;
3485 return 0;
3486 }
3487
3488 if(a->mopt_flag < 0) {
3489 /* optional */
3490 if(mopt == 0xffff)
3491 return 1;
3492 if((mopt & a->mopt_mask) == a->mopt_val)
3493 return 1;
3494 return 0;
3495 }
3496
3497 /* required */
3498 if(mopt == 0xffff)
3499 return 0;
3500 if((mopt & a->mopt_mask) == a->mopt_val)
3501 return 1;
3502 return 0;
3503}
3504
3505static int
3506check_ie_traffic_common(struct uni_xtraffic *ie, u_int present,
3507 struct unicx *cx __unused)
3508{
3509 static u_int fmask =
3510 UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
3511 UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P |
3512 UNI_TRAFFIC_FMBS0_P | UNI_TRAFFIC_FMBS1_P |
3513 UNI_TRAFFIC_FABR1_P;
3514 static u_int bmask =
3515 UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
3516 UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P |
3517 UNI_TRAFFIC_BMBS0_P | UNI_TRAFFIC_BMBS1_P |
3518 UNI_TRAFFIC_BABR1_P;
3519#define DTAB(U,X) \
3520 { U##X##PCR1_P, \
3521 -1, U##X##TAG, 0 }, /* 1, 2, 8, 14 */ \
3522 { U##X##PCR0_P | U##X##PCR1_P, \
3523 +1, U##X##TAG, U##X##TAG }, /* 3 */ \
3524 { U##X##PCR1_P | U##X##SCR1_P | U##X##MBS1_P, \
3525 -1, U##X##TAG, 0 }, /* 4, 9, 10, 15 */ \
3526 { U##X##PCR1_P | U##X##SCR0_P | U##X##MBS0_P, \
3527 -1, 0, 0 }, /* 5, 6, 11, 12 */ \
3528 { U##X##PCR0_P | U##X##PCR1_P, \
3529 -1, 0, 0 }, /* 7, 13 */ \
3530 { U##X##PCR1_P | U##X##ABR1_P, \
3531 -1, U##X##TAG, 0 }, /* 16a */
3532#define DTABSIZE 6
3533
3534 static struct tallow allow[2][DTABSIZE] = {
3535 { DTAB(UNI_TRAFFIC_, F) },
3536 { DTAB(UNI_TRAFFIC_, B) },
3537 };
3538#undef DTAB
3539
3540 u_int f, b, p, m;
3541 int i;
3542
3543 f = present & fmask;
3544 b = present & bmask;
3545 p = present & (fmask | bmask);
3546 m = (present & UNI_TRAFFIC_MOPT_P)
3547 ? ( (ie->ftag ? UNI_TRAFFIC_FTAG : 0)
3548 | (ie->btag ? UNI_TRAFFIC_BTAG : 0)
3549 | (ie->fdisc ? UNI_TRAFFIC_FDISC : 0)
3550 | (ie->bdisc ? UNI_TRAFFIC_BDISC : 0))
3551 : 0xffff;
3552
3553
3554 if(present & UNI_TRAFFIC_BEST_P) {
3555 /*
3556 * Lines 17 and 18
3557 */
3558 if(p != (UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_BPCR1_P))
3559 return -1;
3560 return 0;
3561 }
3562
3563 /*
3564 * Check forward and backward independent. There must be a higher
3565 * level checking in the CAC
3566 */
3567 for(i = 0; i < DTABSIZE; i++)
3568 if(check_traffic(f, m, &allow[0][i]))
3569 break;
3570 if(i == DTABSIZE)
3571 return -1;
3572
3573 for(i = 0; i < DTABSIZE; i++)
3574 if(check_traffic(b, m, &allow[1][i]))
3575 break;
3576 if(i == DTABSIZE)
3577 return -1;
3578
3579 return 0;
3580}
3581
3582static int
3583encode_traffic_common(struct uni_msg *msg, struct uni_xtraffic *ie,
3584 u_int present, struct unicx *cx __unused)
3585{
3586 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR0_P,
3587 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3588 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR0_P,
3589 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3590 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR1_P,
3591 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3592 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR1_P,
3593 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3594 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR0_P,
3595 UNI_TRAFFIC_FSCR0_ID, ie->fscr0);
3596 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR0_P,
3597 UNI_TRAFFIC_BSCR0_ID, ie->bscr0);
3598 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR1_P,
3599 UNI_TRAFFIC_FSCR1_ID, ie->fscr1);
3600 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR1_P,
3601 UNI_TRAFFIC_BSCR1_ID, ie->bscr1);
3602 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS0_P,
3603 UNI_TRAFFIC_FMBS0_ID, ie->fmbs0);
3604 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS0_P,
3605 UNI_TRAFFIC_BMBS0_ID, ie->bmbs0);
3606 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS1_P,
3607 UNI_TRAFFIC_FMBS1_ID, ie->fmbs1);
3608 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS1_P,
3609 UNI_TRAFFIC_BMBS1_ID, ie->bmbs1);
3610 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FABR1_P,
3611 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3612 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BABR1_P,
3613 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3614
3615 APP_OPT(msg, present, UNI_TRAFFIC_BEST_P,
3616 UNI_TRAFFIC_BEST_ID);
3617 APP_OPT_BYTE(msg, present, UNI_TRAFFIC_MOPT_P,
3618 UNI_TRAFFIC_MOPT_ID,
3619 (ie->ftag ? UNI_TRAFFIC_FTAG : 0) |
3620 (ie->btag ? UNI_TRAFFIC_BTAG : 0) |
3621 (ie->fdisc ? UNI_TRAFFIC_FDISC : 0) |
3622 (ie->fdisc ? UNI_TRAFFIC_BDISC : 0));
3623
3624 return 0;
3625}
3626
3627static int
3628decode_traffic_common(struct uni_xtraffic *ie, struct uni_msg *msg,
3629 u_int ielen, u_int *present)
3630{
3631 u_char c;
3632
3633 while(ielen--) {
3634 switch(c = *msg->b_rptr++) {
3635
3636 default:
3637 rej:
3638 return -1;
3639
3640 DEC_GETF3(TRAFFIC_FPCR0, fpcr0, *present);
3641 DEC_GETF3(TRAFFIC_BPCR0, bpcr0, *present);
3642 DEC_GETF3(TRAFFIC_FPCR1, fpcr1, *present);
3643 DEC_GETF3(TRAFFIC_BPCR1, bpcr1, *present);
3644 DEC_GETF3(TRAFFIC_FSCR0, fscr0, *present);
3645 DEC_GETF3(TRAFFIC_BSCR0, bscr0, *present);
3646 DEC_GETF3(TRAFFIC_FSCR1, fscr1, *present);
3647 DEC_GETF3(TRAFFIC_BSCR1, bscr1, *present);
3648 DEC_GETF3(TRAFFIC_FMBS0, fmbs0, *present);
3649 DEC_GETF3(TRAFFIC_BMBS0, bmbs0, *present);
3650 DEC_GETF3(TRAFFIC_BMBS1, bmbs1, *present);
3651 DEC_GETF3(TRAFFIC_FABR1, fabr1, *present);
3652 DEC_GETF3(TRAFFIC_BABR1, babr1, *present);
3653
3654 case UNI_TRAFFIC_BEST_ID:
3655 *present |= UNI_TRAFFIC_BEST_P;
3656 break;
3657
3658 case UNI_TRAFFIC_MOPT_ID:
3659 if(ielen == 0)
3660 return -1;
3661 ielen--;
3662 if(!(*present & UNI_TRAFFIC_MOPT_P)) {
3663 *present |= UNI_TRAFFIC_MOPT_P;
3664 ie->ftag = (*msg->b_rptr&UNI_TRAFFIC_FTAG)?1:0;
3665 ie->btag = (*msg->b_rptr&UNI_TRAFFIC_BTAG)?1:0;
3666 ie->fdisc = (*msg->b_rptr&UNI_TRAFFIC_FDISC)?1:0;
3667 ie->bdisc = (*msg->b_rptr&UNI_TRAFFIC_BDISC)?1:0;
3668 }
3669 msg->b_rptr++;
3670 break;
3671 }
3672 }
3673 return 0;
3674}
3675
3676
3677/*****************************************************************/
3678
3679DEF_IE_PRINT(itu, traffic)
3680{
3681 if(uni_print_iehdr("traffic", &ie->h, cx))
3682 return;
3683 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3684 uni_print_ieend(cx);
3685}
3686
3687DEF_IE_CHECK(itu, traffic)
3688{
3689 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3690}
3691
3692DEF_IE_ENCODE(itu, traffic)
3693{
3694 START_IE(traffic, UNI_IE_TRAFFIC, 26);
3695 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3696 SET_IE_LEN(msg);
3697 return 0;
3698}
3699
3700DEF_IE_DECODE(itu, traffic)
3701{
3702 IE_START(;);
3703
3704 if(ielen > 30)
3705 goto rej;
3706
3707 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3708 goto rej;
3709
3710 IE_END(TRAFFIC);
3711}
3712
3713/*****************************************************************/
3714
3715DEF_IE_PRINT(itu, atraffic)
3716{
3717 if(uni_print_iehdr("atraffic", &ie->h, cx))
3718 return;
3719 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3720 uni_print_ieend(cx);
3721}
3722
3723DEF_IE_CHECK(itu, atraffic)
3724{
3725 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3726}
3727
3728DEF_IE_ENCODE(itu, atraffic)
3729{
3730 START_IE(traffic, UNI_IE_ATRAFFIC, 26);
3731 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3732 SET_IE_LEN(msg);
3733 return 0;
3734}
3735
3736DEF_IE_DECODE(itu, atraffic)
3737{
3738 IE_START(;);
3739
3740 if(ielen > 30)
3741 goto rej;
3742
3743 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3744 goto rej;
3745
3746 IE_END(ATRAFFIC);
3747}
3748
3749/*****************************************************************/
3750
3751DEF_IE_PRINT(itu, mintraffic)
3752{
3753 if(uni_print_iehdr("mintraffic", &ie->h, cx))
3754 return;
3755
3756 uni_print_entry(cx, "pcr0", "(");
3757 if(ie->h.present & UNI_MINTRAFFIC_FPCR0_P)
3758 uni_printf(cx, "%u", ie->fpcr0);
3759 uni_putc(',', cx);
3760 if(ie->h.present & UNI_MINTRAFFIC_BPCR0_P)
3761 uni_printf(cx, "%u", ie->bpcr0);
3762 uni_putc(')', cx);
3763
3764 uni_print_entry(cx, "pcr1", "(");
3765 if(ie->h.present & UNI_MINTRAFFIC_FPCR1_P)
3766 uni_printf(cx, "%u", ie->fpcr1);
3767 uni_putc(',', cx);
3768 if(ie->h.present & UNI_MINTRAFFIC_BPCR1_P)
3769 uni_printf(cx, "%u", ie->bpcr1);
3770 uni_putc(')', cx);
3771
3772 uni_print_entry(cx, "abr1", "(");
3773 if(ie->h.present & UNI_MINTRAFFIC_FABR1_P)
3774 uni_printf(cx, "%u", ie->fabr1);
3775 uni_putc(',', cx);
3776 if(ie->h.present & UNI_MINTRAFFIC_BABR1_P)
3777 uni_printf(cx, "%u", ie->babr1);
3778 uni_printf(cx, ")");
3779
3780 uni_print_ieend(cx);
3781}
3782
3783DEF_IE_CHECK(itu, mintraffic)
3784{
3785 u_int abr;
3786 u_int xbr;
3787 cx = cx;
3788
3789 abr = ie->h.present & (UNI_MINTRAFFIC_FABR1_P|UNI_MINTRAFFIC_BABR1_P);
3790 xbr = ie->h.present & (UNI_MINTRAFFIC_FPCR0_P|UNI_MINTRAFFIC_BPCR0_P|
3791 UNI_MINTRAFFIC_FPCR1_P|UNI_MINTRAFFIC_BPCR1_P);
3792
3793 if(abr && xbr)
3794 return -1;
3795
3796 return 0;
3797}
3798
3799DEF_IE_ENCODE(itu, mintraffic)
3800{
3801 START_IE(mintraffic, UNI_IE_MINTRAFFIC, 16);
3802
3803 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR0_P,
3804 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3805 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR0_P,
3806 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3807 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR1_P,
3808 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3809 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR1_P,
3810 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3811 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FABR1_P,
3812 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3813 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BABR1_P,
3814 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3815
3816 SET_IE_LEN(msg);
3817 return 0;
3818}
3819
3820DEF_IE_DECODE(itu, mintraffic)
3821{
3822 u_char c;
3823
3824 IE_START(;);
3825
3826 if(ielen > 20)
3827 goto rej;
3828
3829 while(ielen--) {
3830 switch(c = *msg->b_rptr++) {
3831
3832 default:
3833 goto rej;
3834
3835 DEC_GETF3(MINTRAFFIC_FPCR0, fpcr0, ie->h.present);
3836 DEC_GETF3(MINTRAFFIC_BPCR0, bpcr0, ie->h.present);
3837 DEC_GETF3(MINTRAFFIC_FPCR1, fpcr1, ie->h.present);
3838 DEC_GETF3(MINTRAFFIC_BPCR1, bpcr1, ie->h.present);
3839 DEC_GETF3(MINTRAFFIC_FABR1, fabr1, ie->h.present);
3840 DEC_GETF3(MINTRAFFIC_BABR1, babr1, ie->h.present);
3841 }
3842 }
3843
3844 IE_END(MINTRAFFIC);
3845}
3846
3847/*****************************************************************/
3848
3849DEF_IE_PRINT(net, mdcr)
3850{
3851 static const struct uni_print_tbl origin_tbl[] = {
3852 MKT(UNI_MDCR_ORIGIN_USER, user),
3853 MKT(UNI_MDCR_ORIGIN_NET, net),
3854 EOT()
3855 };
3856
3857 if(uni_print_iehdr("mdcr", &ie->h, cx))
3858 return;
3859
3860 uni_print_tbl("origin", ie->origin, origin_tbl, cx);
3861 uni_print_entry(cx, "mdcr", "(");
3862 uni_printf(cx, "%u", ie->fmdcr);
3863 uni_putc(',', cx);
3864 uni_printf(cx, "%u", ie->bmdcr);
3865 uni_putc(')', cx);
3866
3867 uni_print_ieend(cx);
3868}
3869
3870DEF_IE_CHECK(net, mdcr)
3871{
3872 cx = cx;
3873
3874 if ((ie->origin != UNI_MDCR_ORIGIN_USER &&
3875 ie->origin != UNI_MDCR_ORIGIN_NET) ||
3876 ie->fmdcr >= (1 << 24) || ie->bmdcr >= (1 << 24))
3877 return (-1);
3878
3879 return (0);
3880}
3881
3882DEF_IE_ENCODE(net, mdcr)
3883{
3884 START_IE(mdcr, UNI_IE_MDCR, 9);
3885
3886 APP_BYTE(msg, ie->origin);
3887 APP_SUB_24BIT(msg, UNI_TRAFFIC_FMDCR_ID, ie->fmdcr);
3888 APP_SUB_24BIT(msg, UNI_TRAFFIC_BMDCR_ID, ie->bmdcr);
3889
3890 SET_IE_LEN(msg);
3891 return (0);
3892}
3893
3894DEF_IE_DECODE(net, mdcr)
3895{
3896 u_char c;
3897#define UNI_TRAFFIC_FMDCR_P 0x01
3898#define UNI_TRAFFIC_BMDCR_P 0x02
3899 u_int p = 0;
3900
3901 IE_START(;);
3902
3903 if(ielen != 9)
3904 goto rej;
3905
3906 ie->origin = *msg->b_rptr++;
3907 ielen--;
3908
3909 while(ielen--) {
3910 switch(c = *msg->b_rptr++) {
3911
3912 default:
3913 goto rej;
3914
3915 DEC_GETF3(TRAFFIC_FMDCR, fmdcr, p);
3916 DEC_GETF3(TRAFFIC_BMDCR, bmdcr, p);
3917 }
3918 }
3919 if (p != (UNI_TRAFFIC_FMDCR_P | UNI_TRAFFIC_BMDCR_P))
3920 goto rej;
3921
3922 IE_END(MDCR);
3923}
3924
3925/*********************************************************************
3926 *
3927 * Connection identifier
3928 *
3929 * References for this IE are:
3930 *
3931 * Q.2931 pp. 69...70
3932 * UNI4.0 pp. 15...16
3933 * PNNI1.0 p. 198
3934 *
3935 * Only ITU-T coding allowed.
3936 */
3937
3938DEF_IE_PRINT(itu, connid)
3939{
3940 static const struct uni_print_tbl tbl[] = {
3941 MKT(UNI_CONNID_VCI, exclusive),
3942 MKT(UNI_CONNID_ANYVCI, any),
3943 MKT(UNI_CONNID_NOVCI, no),
3944 EOT()
3945 };
3946 static const struct uni_print_tbl assoc_tbl[] = {
3947 MKT(UNI_CONNID_ASSOC, associated),
3948 MKT(UNI_CONNID_NONASSOC,non-associated),
3949 EOT()
3950 };
3951
3952 if(uni_print_iehdr("connid", &ie->h, cx))
3953 return;
3954
3955 uni_print_tbl("mode", ie->assoc, assoc_tbl, cx);
3956 uni_print_entry(cx, "connid", "(%u,", ie->vpci);
3957 if(ie->type == UNI_CONNID_VCI)
3958 uni_printf(cx, "%u", ie->vci);
3959 else
3960 uni_print_tbl(NULL, ie->type, tbl, cx);
3961 uni_printf(cx, ")");
3962
3963 uni_print_ieend(cx);
3964}
3965
3966DEF_IE_CHECK(itu, connid)
3967{
3968 cx = cx;
3969 switch(ie->type) {
3970 default:
3971 return -1;
3972 case UNI_CONNID_VCI:
3973 case UNI_CONNID_ANYVCI:
3974 case UNI_CONNID_NOVCI:
3975 break;
3976 }
3977
3978#if 0
3979 /*
3980 * This field must be checked by the application to fulfil
3981 * Q.2931Amd4 27) 5.2.3 last sentence
3982 */
3983 switch(ie->assoc) {
3984
3985 case UNI_CONNID_ASSOC:
3986 if(!cx->cx.pnni)
3987 return -1;
3988 break;
3989
3990 case UNI_CONNID_NONASSOC:
3991 break;
3992
3993 default:
3994 return -1;
3995 }
3996#endif
3997 return 0;
3998}
3999
4000DEF_IE_ENCODE(itu, connid)
4001{
4002 START_IE(connid, UNI_IE_CONNID, 5);
4003
4004 APP_BYTE(msg, 0x80 | (ie->assoc << 3) | ie->type);
4005 APP_BYTE(msg, ie->vpci >> 8);
4006 APP_BYTE(msg, ie->vpci >> 0);
4007 APP_BYTE(msg, ie->vci >> 8);
4008 APP_BYTE(msg, ie->vci >> 0);
4009
4010 SET_IE_LEN(msg);
4011 return 0;
4012}
4013
4014DEF_IE_DECODE(itu, connid)
4015{
4016 u_char c;
4017
4018 IE_START(;);
4019
4020 if(ielen != 5)
4021 goto rej;
4022
4023 c = *msg->b_rptr++;
4024 if((c & 0x80) == 0)
4025 goto rej;
4026 ie->assoc = (c >> 3) & 3;
4027 ie->type = c & 7;
4028 ie->vpci = *msg->b_rptr++ << 8;
4029 ie->vpci |= *msg->b_rptr++;
4030 ie->vci = *msg->b_rptr++ << 8;
4031 ie->vci |= *msg->b_rptr++;
4032
4033 IE_END(CONNID);
4034}
4035
4036/*********************************************************************
4037 *
4038 * Quality of Service
4039 *
4040 * References for this IE are:
4041 *
4042 * Q.2931 pp. 72
4043 * UNI4.0 pp. 16...17
4044 */
4045
4046static void
4047print_qos(struct unicx *cx, struct uni_ie_qos *ie)
4048{
4049 static const struct uni_print_tbl class_tbl[] = {
4050 MKT(UNI_QOS_CLASS0, Class0),
4051 MKT(UNI_QOS_CLASS1, Class1),
4052 MKT(UNI_QOS_CLASS2, Class2),
4053 MKT(UNI_QOS_CLASS3, Class3),
4054 MKT(UNI_QOS_CLASS4, Class4),
4055 EOT()
4056 };
4057
4058 if(uni_print_iehdr("qos", &ie->h, cx))
4059 return;
4060
4061 uni_print_tbl("fwd", ie->fwd, class_tbl, cx);
4062 uni_print_tbl("bwd", ie->bwd, class_tbl, cx);
4063
4064 uni_print_ieend(cx);
4065}
4066
4067DEF_IE_PRINT(itu, qos)
4068{
4069 print_qos(cx, ie);
4070}
4071DEF_IE_PRINT(net, qos)
4072{
4073 print_qos(cx, ie);
4074}
4075
4076DEF_IE_CHECK(itu, qos)
4077{
4078 cx = cx;
4079
4080 switch(ie->fwd) {
4081 default:
4082 return -1;
4083
4084 case UNI_QOS_CLASS0:
4085 break;
4086 }
4087 switch(ie->bwd) {
4088 default:
4089 return -1;
4090
4091 case UNI_QOS_CLASS0:
4092 break;
4093 }
4094 return 0;
4095}
4096
4097DEF_IE_CHECK(net, qos)
4098{
4099 cx = cx;
4100
4101 switch(ie->fwd) {
4102 default:
4103 return -1;
4104
4105 case UNI_QOS_CLASS1:
4106 case UNI_QOS_CLASS2:
4107 case UNI_QOS_CLASS3:
4108 case UNI_QOS_CLASS4:
4109 break;
4110 }
4111 switch(ie->bwd) {
4112 default:
4113 return -1;
4114
4115 case UNI_QOS_CLASS1:
4116 case UNI_QOS_CLASS2:
4117 case UNI_QOS_CLASS3:
4118 case UNI_QOS_CLASS4:
4119 break;
4120 }
4121 return 0;
4122}
4123
4124DEF_IE_ENCODE(itu, qos)
4125{
4126 START_IE(qos, UNI_IE_QOS, 2);
4127
4128 APP_BYTE(msg, ie->fwd);
4129 APP_BYTE(msg, ie->bwd);
4130
4131 SET_IE_LEN(msg);
4132 return 0;
4133}
4134DEF_IE_ENCODE(net, qos)
4135{
4136 START_IE(qos, UNI_IE_QOS, 2);
4137
4138 APP_BYTE(msg, ie->fwd);
4139 APP_BYTE(msg, ie->bwd);
4140
4141 SET_IE_LEN(msg);
4142 return 0;
4143}
4144
4145DEF_IE_DECODE(itu, qos)
4146{
4147 IE_START(;);
4148
4149 if(ielen != 2)
4150 goto rej;
4151
4152 ie->fwd = *msg->b_rptr++;
4153 ie->bwd = *msg->b_rptr++;
4154
4155 IE_END(QOS);
4156}
4157
4158DEF_IE_DECODE(net, qos)
4159{
4160 IE_START(;);
4161
4162 if(ielen != 2)
4163 goto rej;
4164
4165 ie->fwd = *msg->b_rptr++;
4166 ie->bwd = *msg->b_rptr++;
4167
4168 IE_END(QOS);
4169}
4170
4171/*********************************************************************
4172 *
4173 * Broadband Lower Layer Information
4174 *
4175 * References for this IE are:
4176 *
4177 * Q.2931 pp. 53...54
4178 * UNI4.0 p. 12
4179 *
4180 * Only ITU-T coding allowed.
4181 */
4182
4183DEF_IE_PRINT(itu, bhli)
4184{
4185 static const struct uni_print_tbl type_tbl[] = {
4186 MKT(UNI_BHLI_ISO, iso),
4187 MKT(UNI_BHLI_USER, user),
4188 MKT(UNI_BHLI_VENDOR, vendor),
4189 EOT()
4190 };
4191 u_int i;
4192
4193 if(uni_print_iehdr("bhli", &ie->h, cx))
4194 return;
4195
4196 uni_print_tbl("type", ie->type, type_tbl, cx);
4197 uni_print_entry(cx, "len", "%d", ie->len);
4198 uni_print_entry(cx, "info", "(");
4199 for(i = 0; i < ie->len; i++)
4200 uni_printf(cx, ",0x%02x", ie->info[i]);
4201 uni_printf(cx, ")");
4202
4203 uni_print_ieend(cx);
4204}
4205
4206DEF_IE_CHECK(itu, bhli)
4207{
4208 cx = cx;
4209
4210 switch(ie->type) {
4211 default:
4212 return -1;
4213
4214 case UNI_BHLI_ISO:
4215 case UNI_BHLI_USER:
4216 case UNI_BHLI_VENDOR:
4217 break;
4218 }
4219 if(ie->len > 8)
4220 return -1;
4221
4222 return 0;
4223}
4224
4225DEF_IE_ENCODE(itu, bhli)
4226{
4227 START_IE(bhli, UNI_IE_BHLI, 9);
4228
4229 APP_BYTE(msg, 0x80 | ie->type);
4230 APP_BUF(msg, ie->info, ie->len);
4231
4232 SET_IE_LEN(msg);
4233 return 0;
4234}
4235
4236DEF_IE_DECODE(itu, bhli)
4237{
4238 u_char c;
4239
4240 IE_START(;);
4241
4242 if(ielen > 9)
4243 goto rej;
4244
4245 c = *msg->b_rptr++;
4246 ielen--;
4247
4248 if(!(c & 0x80))
4249 goto rej;
4250 ie->type = c & 0x7f;
4251 ie->len = ielen;
4252 (void)memcpy(ie->info, msg->b_rptr, ielen);
4253 msg->b_rptr += ielen;
4254
4255 IE_END(BHLI);
4256}
4257
4258/*********************************************************************
4259 *
4260 * Broadband bearer capabilities
4261 *
4262 * References for this IE are:
4263 *
4264 * Q.2931 pp. 51...52
4265 * Q.2931 Amd 1
4266 * UNI4.0 pp. 10...12, 106...109
4267 *
4268 * UNI4.0 changed the meaning of byte 5a. Instead of 3 bit traffic type and
4269 * 2 bit timing requirements there are now 7 bits ATM transfer capabilities.
4270 * However the old format is still supported: it should be recognized on
4271 * input, but never be generated on output. Mapping is left to the user of
4272 * UNI.
4273 *
4274 * Amd 1 not checked XXX.
4275 *
4276 * The Appendix in UNI4.0 lists all the supported combinations of various
4277 * traffic IE's. The check function implements part of it.
4278 *
4279 * A C X VP
4280 * 1 CBR.1 7 . 7 7
4281 * 2 CBR.2 - . 4,5,6 5 (*)
4282 * 3 CBR.3 - . 4,5,6 5 (*)
4283 * 4 rt-VBR.1 . 19 19 19
4284 * 5 rt-VBR.2 . 9 1,9 9
4285 * 6 rt-VBR.3 . 9 1,9 9
4286 * 7 rt-VBR.4 . . 1,9 . (*)
4287 * 8 rt-VBR.5 . . 1,9 . (*)
4288 * 9 rt-VBR.6 . 9 1,9 9 (*)
4289 * 10 nrt-VBR.1 . 11 11 11
4290 * 11 nrt-VBR.2 . - -,0,2,8,10 -,10
4291 * 12 nrt-VBR.3 . - -,0,2,8,10 -,10
4292 * 13 nrt-VBR.4 . - -,0,2,8,10 . (*)
4293 * 14 nrt-VBR.5 . - -,0,2,8,10 . (*)
4294 * 15 nrt-VBR.6 . - -,0,2,8,10 -,10(*)
4295 * 16 ABR . 12 12 12
4296 * 17 UBR.1 . - -,0,2,8,10 -,10
4297 * 18 UBR.2 . - -,0,2,8,10 -,10
4298 *
4299 * (*) compatibility
4300 *
4301 * Only ITU-T coding allowed.
4302 */
4303
4304DEF_IE_PRINT(itu, bearer)
4305{
4306 static const struct uni_print_tbl bclass_tbl[] = {
4307 MKT(UNI_BEARER_A, bcob-A),
4308 MKT(UNI_BEARER_C, bcob-C),
4309 MKT(UNI_BEARER_X, bcob-X),
4310 MKT(UNI_BEARER_TVP, transparent-VP),
4311 EOT()
4312 };
4313 static const struct uni_print_tbl atc_tbl[] = {
4314 MKT(UNI_BEARER_ATC_CBR, cbr),
4315 MKT(UNI_BEARER_ATC_CBR1, cbr1),
4316 MKT(UNI_BEARER_ATC_VBR, vbr),
4317 MKT(UNI_BEARER_ATC_VBR1, vbr1),
4318 MKT(UNI_BEARER_ATC_NVBR, nvbr),
4319 MKT(UNI_BEARER_ATC_NVBR1, nvbr1),
4320 MKT(UNI_BEARER_ATC_ABR, abr),
4321
4322 MKT(UNI_BEARER_ATCX_0, x0),
4323 MKT(UNI_BEARER_ATCX_1, x1),
4324 MKT(UNI_BEARER_ATCX_2, x2),
4325 MKT(UNI_BEARER_ATCX_4, x4),
4326 MKT(UNI_BEARER_ATCX_6, x6),
4327 MKT(UNI_BEARER_ATCX_8, x8),
4328 EOT()
4329 };
4330 static const struct uni_print_tbl cfg_tbl[] = {
4331 MKT(UNI_BEARER_P2P, p2p),
4332 MKT(UNI_BEARER_MP, mp),
4333 EOT()
4334 };
4335 static const struct uni_print_tbl clip_tbl[] = {
4336 MKT(UNI_BEARER_NOCLIP, no),
4337 MKT(UNI_BEARER_CLIP, yes),
4338 EOT()
4339 };
4340
4341 if(uni_print_iehdr("bearer", &ie->h, cx))
4342 return;
4343
4344 uni_print_tbl("class", ie->bclass, bclass_tbl, cx);
4345
4346 if(ie->h.present & UNI_BEARER_ATC_P) {
4347 uni_print_tbl("atc", ie->atc, atc_tbl, cx);
4348 }
4349 uni_print_tbl("clip", ie->clip, clip_tbl, cx);
4350 uni_print_tbl("cfg", ie->cfg, cfg_tbl, cx);
4351
4352 uni_print_ieend(cx);
4353}
4354
4355#define QTYPE(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATC_##A)
4356#define QTYPEX(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATCX_##A)
4357#define QTYPE0(C) ((UNI_BEARER_##C << 8) | (1 << 16))
4358DEF_IE_CHECK(itu, bearer)
4359{
4360 cx = cx;
4361
4362 switch((ie->bclass << 8) |
4363 ((ie->h.present & UNI_BEARER_ATC_P) == 0
4364 ? (1 << 16)
4365 : ie->atc)) {
4366
4367 default:
4368 return -1;
4369
4370 case QTYPE (A, CBR1): /* 1 */
4371 case QTYPE (X, CBR1): /* 1 */
4372 case QTYPE (TVP, CBR1): /* 1 */
4373
4374 case QTYPE0(A): /* 2,3 */
4375 case QTYPEX(X, 4): /* 2,3 */
4376 case QTYPE (X, CBR): /* 2,3 */
4377 case QTYPEX(X, 6): /* 2,3 */
4378 case QTYPE (TVP, CBR): /* 2,3 */
4379
4380 case QTYPE (C, VBR1): /* 4 */
4381 case QTYPE (X, VBR1): /* 4 */
4382 case QTYPE (TVP, VBR1): /* 4 */
4383
4384 case QTYPE (C, VBR): /* 5,6,9 */
4385 case QTYPEX(X, 1): /* 5,6,7,8,9 */
4386 case QTYPE (X, VBR): /* 5,6,7,8,9 */
4387 case QTYPE (TVP, VBR): /* 5,6,9 */
4388
4389 case QTYPE (C, NVBR1): /* 10 */
4390 case QTYPE (X, NVBR1): /* 10 */
4391 case QTYPE (TVP, NVBR1): /* 10 */
4392
4393 case QTYPE0(C): /* 11,12,13,14,15,17,18 */
4394 case QTYPE0(X): /* 11,12,13,14,15,17,18 */
4395 case QTYPEX(X, 0): /* 11,12,13,14,15,17,18 */
4396 case QTYPEX(X, 2): /* 11,12,13,14,15,17,18 */
4397 case QTYPEX(X, 8): /* 11,12,13,14,15,17,18 */
4398 case QTYPE (X, NVBR): /* 11,12,13,14,15,17,18 */
4399 case QTYPE0(TVP): /* 11,12,15,17,18 */
4400 case QTYPE (TVP, NVBR): /* 11,12,15,17,18 */
4401
4402 case QTYPE (C, ABR): /* 16 */
4403 case QTYPE (X, ABR): /* 16 */
4404 case QTYPE (TVP, ABR): /* 16 */
4405 break;
4406 }
4407
4408 switch(ie->clip) {
4409 default:
4410 return -1;
4411
4412 case UNI_BEARER_NOCLIP:
4413 case UNI_BEARER_CLIP:
4414 break;
4415 }
4416 switch(ie->cfg) {
4417 default:
4418 return -1;
4419
4420 case UNI_BEARER_P2P:
4421 case UNI_BEARER_MP:
4422 break;
4423 }
4424
4425 return 0;
4426}
4427#undef QTYPE
4428#undef QTYPEX
4429#undef QTYPE0
4430
4431DEF_IE_ENCODE(itu, bearer)
4432{
4433 START_IE(bearer, UNI_IE_BEARER, 3);
4434
4435 APP_BYTE(msg, ie->bclass |
4436 ((ie->h.present & UNI_BEARER_ATC_P) ? 0:0x80));
4437 APP_OPT(msg, ie->h.present, UNI_BEARER_ATC_P,
4438 0x80 | ie->atc);
4439 APP_BYTE(msg, 0x80 | (ie->clip << 5) | ie->cfg);
4440
4441 SET_IE_LEN(msg);
4442 return 0;
4443}
4444
4445DEF_IE_DECODE(itu, bearer)
4446{
4447 u_char c;
4448
4449 IE_START(;);
4450
4451 if(ielen != 2 && ielen != 3)
4452 goto rej;
4453
4454 c = *msg->b_rptr++;
4455 ielen--;
4456 ie->bclass = c & 0x1f;
4457 if(!(c & 0x80)) {
4458 c = *msg->b_rptr++;
4459 ielen--;
4460 ie->h.present |= UNI_BEARER_ATC_P;
4461
4462 switch(c & 0x7f) {
4463 /*
4464 * Real legal values
4465 */
4466 case UNI_BEARER_ATC_CBR:
4467 case UNI_BEARER_ATC_CBR1:
4468 case UNI_BEARER_ATC_VBR:
4469 case UNI_BEARER_ATC_VBR1:
4470 case UNI_BEARER_ATC_NVBR:
4471 case UNI_BEARER_ATC_NVBR1:
4472 case UNI_BEARER_ATC_ABR:
4473 break;
4474
4475 /*
4476 * Compat values
4477 */
4478 case UNI_BEARER_ATCX_0:
4479 case UNI_BEARER_ATCX_1:
4480 case UNI_BEARER_ATCX_2:
4481 case UNI_BEARER_ATCX_4:
4482 case UNI_BEARER_ATCX_6:
4483 case UNI_BEARER_ATCX_8:
4484 break;
4485
4486 default:
4487 goto rej;
4488 }
4489
4490 if(!(c & 0x80))
4491 goto rej;
4492
4493 ie->atc = c & 0x7f;
4494 }
4495 if(ielen == 0)
4496 goto rej;
4497 c = *msg->b_rptr++;
4498 ielen--;
4499 if(!(c & 0x80))
4500 goto rej;
4501 ie->clip = (c >> 5) & 0x3;
4502 ie->cfg = c & 0x3;
4503
4504 IE_END(BEARER);
4505}
4506
4507/*********************************************************************
4508 *
4509 * Broadband Lower Layer Information
4510 *
4511 * References for this IE are:
4512 *
4513 * Q.2931 pp. 54...59
4514 * UNI4.0 pp. 12...14
4515 *
4516 * UNI4.0 states, that layer 1 info is not supported.
4517 * We allow a layer 1 protocol identifier.
4518 *
4519 * UNI4.0 states, that the layer information subelements are NOT position
4520 * dependent. We allow them in any order on input, but generate always the
4521 * definit order on output.
4522 *
4523 * Only ITU-T coding allowed.
4524 */
4525
4526DEF_IE_PRINT(itu, blli)
4527{
4528 static const struct uni_print_tbl l2_tbl[] = {
4529 MKT(UNI_BLLI_L2_BASIC, basic),
4530 MKT(UNI_BLLI_L2_Q921, Q921),
4531 MKT(UNI_BLLI_L2_X25LL, X25-LL),
4532 MKT(UNI_BLLI_L2_X25ML, X25-ML),
4533 MKT(UNI_BLLI_L2_LABP, LAPB),
4534 MKT(UNI_BLLI_L2_HDLC_ARM, HDLC-ARM),
4535 MKT(UNI_BLLI_L2_HDLC_NRM, HDLC-NRM),
4536 MKT(UNI_BLLI_L2_HDLC_ABM, HDLC-ABM),
4537 MKT(UNI_BLLI_L2_LAN, LAN),
4538 MKT(UNI_BLLI_L2_X75, X75),
4539 MKT(UNI_BLLI_L2_Q922, Q922),
4540 MKT(UNI_BLLI_L2_USER, user),
4541 MKT(UNI_BLLI_L2_ISO7776, ISO7776),
4542 EOT()
4543 };
4544 static const struct uni_print_tbl l2mode_tbl[] = {
4545 MKT(UNI_BLLI_L2NORM, normal),
4546 MKT(UNI_BLLI_L2EXT, extended),
4547 EOT()
4548 };
4549 static const struct uni_print_tbl l3_tbl[] = {
4550 MKT(UNI_BLLI_L3_X25, X25),
4551 MKT(UNI_BLLI_L3_ISO8208, ISO8208),
4552 MKT(UNI_BLLI_L3_X223, X223),
4553 MKT(UNI_BLLI_L3_CLMP, CLMP),
4554 MKT(UNI_BLLI_L3_T70, T70),
4555 MKT(UNI_BLLI_L3_TR9577, TR9577),
4556 MKT(UNI_BLLI_L3_USER, user),
4557 MKT(UNI_BLLI_L3_H310, H310),
4558 MKT(UNI_BLLI_L3_H321, H321),
4559 EOT()
4560 };
4561 static const struct uni_print_tbl l3mode_tbl[] = {
4562 MKT(UNI_BLLI_L3NSEQ, normal-seq),
4563 MKT(UNI_BLLI_L3ESEQ, extended-seq),
4564 EOT()
4565 };
4566 static const struct uni_print_tbl l3psiz_tbl[] = {
4567 MKT(UNI_BLLI_L3_16, 16),
4568 MKT(UNI_BLLI_L3_32, 32),
4569 MKT(UNI_BLLI_L3_64, 64),
4570 MKT(UNI_BLLI_L3_128, 128),
4571 MKT(UNI_BLLI_L3_256, 256),
4572 MKT(UNI_BLLI_L3_512, 512),
4573 MKT(UNI_BLLI_L3_1024, 1024),
4574 MKT(UNI_BLLI_L3_2048, 2048),
4575 MKT(UNI_BLLI_L3_4096, 4096),
4576 EOT()
4577 };
4578 static const struct uni_print_tbl l3ttype_tbl[] = {
4579 MKT(UNI_BLLI_L3_TTYPE_RECV, receive_only),
4580 MKT(UNI_BLLI_L3_TTYPE_SEND, send_only),
4581 MKT(UNI_BLLI_L3_TTYPE_BOTH, both),
4582 EOT()
4583 };
4584 static const struct uni_print_tbl l3mux_tbl[] = {
4585 MKT(UNI_BLLI_L3_MUX_NOMUX, NOMUX),
4586 MKT(UNI_BLLI_L3_MUX_TS, TS),
4587 MKT(UNI_BLLI_L3_MUX_TSFEC, TSFEC),
4588 MKT(UNI_BLLI_L3_MUX_PS, PS),
4589 MKT(UNI_BLLI_L3_MUX_PSFEC, PSFEC),
4590 MKT(UNI_BLLI_L3_MUX_H221, H221),
4591 EOT()
4592 };
4593 static const struct uni_print_tbl l3tcap_tbl[] = {
4594 MKT(UNI_BLLI_L3_TCAP_NOIND, noind),
4595 MKT(UNI_BLLI_L3_TCAP_AAL1, aal1),
4596 MKT(UNI_BLLI_L3_TCAP_AAL5, aal5),
4597 MKT(UNI_BLLI_L3_TCAP_AAL15, aal1&5),
4598 EOT()
4599 };
4600
4601 if(uni_print_iehdr("blli", &ie->h, cx))
4602 return;
4603
4604 if(ie->h.present & UNI_BLLI_L1_P) {
4605 uni_print_entry(cx, "l1", "%u", ie->l1);
4606 uni_print_eol(cx);
4607 }
4608 if(ie->h.present & UNI_BLLI_L2_P) {
4609 uni_print_tbl("l2", ie->l2, l2_tbl, cx);
4610 uni_print_push_prefix("l2", cx);
4611 cx->indent++;
4612 if(ie->h.present & UNI_BLLI_L2_USER_P)
4613 uni_print_entry(cx, "proto", "%u", ie->l2_user);
4614 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4615 uni_print_entry(cx, "q933", "%u", ie->l2_q933);
4616 uni_print_tbl("mode", ie->l2_mode, l2mode_tbl, cx);
4617 }
4618 if(ie->h.present & UNI_BLLI_L2_WSIZ_P)
4619 uni_print_entry(cx, "wsize", "%u", ie->l2_wsiz);
4620 uni_print_pop_prefix(cx);
4621 cx->indent--;
4622 uni_print_eol(cx);
4623
4624 }
4625 if(ie->h.present & UNI_BLLI_L3_P) {
4626 uni_print_tbl("l3", ie->l3, l3_tbl, cx);
4627 uni_print_push_prefix("l3", cx);
4628 cx->indent++;
4629 if(ie->h.present & UNI_BLLI_L3_USER_P)
4630 uni_print_entry(cx, "proto", "%u", ie->l3_user);
4631 if(ie->h.present & UNI_BLLI_L3_MODE_P)
4632 uni_print_tbl("mode", ie->l3_mode, l3mode_tbl, cx);
4633 if(ie->h.present & UNI_BLLI_L3_PSIZ_P)
4634 uni_print_tbl("packet-size", ie->l3_psiz, l3psiz_tbl, cx);
4635 if(ie->h.present & UNI_BLLI_L3_WSIZ_P)
4636 uni_print_entry(cx, "window-size", "%u", ie->l3_wsiz);
4637 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4638 uni_print_tbl("ttype", ie->l3_ttype, l3ttype_tbl, cx);
4639 uni_print_tbl("tcap", ie->l3_tcap, l3tcap_tbl, cx);
4640 }
4641 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4642 uni_print_tbl("fmux", ie->l3_fmux, l3mux_tbl, cx);
4643 uni_print_tbl("bmux", ie->l3_bmux, l3mux_tbl, cx);
4644 }
4645 if(ie->h.present & UNI_BLLI_L3_IPI_P)
4646 uni_print_entry(cx, "ipi", "0x%02x", ie->l3_ipi);
4647 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4648 uni_print_entry(cx, "snap", "%06x.%04x", ie->oui, ie->pid);
4649 uni_print_pop_prefix(cx);
4650 cx->indent--;
4651 uni_print_eol(cx);
4652 }
4653
4654 uni_print_ieend(cx);
4655}
4656
4657DEF_IE_CHECK(itu, blli)
4658{
4659 cx = cx;
4660/*
4661 if(ie->h.present & UNI_BLLI_L1_P)
4662 ;
4663*/
4664
4665 if(ie->h.present & UNI_BLLI_L2_P) {
4666 static u_int mask =
4667 UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P |
4668 UNI_BLLI_L2_USER_P;
4669
4670 switch(ie->l2) {
4671 default:
4672 return -1;
4673
4674 case UNI_BLLI_L2_BASIC:
4675 case UNI_BLLI_L2_Q921:
4676 case UNI_BLLI_L2_LABP:
4677 case UNI_BLLI_L2_LAN:
4678 case UNI_BLLI_L2_X75:
4679 if(ie->h.present & mask)
4680 return -1;
4681 break;
4682
4683 case UNI_BLLI_L2_X25LL:
4684 case UNI_BLLI_L2_X25ML:
4685 case UNI_BLLI_L2_HDLC_ARM:
4686 case UNI_BLLI_L2_HDLC_NRM:
4687 case UNI_BLLI_L2_HDLC_ABM:
4688 case UNI_BLLI_L2_Q922:
4689 case UNI_BLLI_L2_ISO7776:
4690 switch(ie->h.present & mask) {
4691 default:
4692 return -1;
4693
4694 case 0:
4695 case UNI_BLLI_L2_Q933_P:
4696 case UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P:
4697 break;
4698 }
4699 break;
4700
4701 case UNI_BLLI_L2_USER:
4702 switch(ie->h.present & mask) {
4703 default:
4704 return -1;
4705
4706 case 0: /* XXX ? */
4707 case UNI_BLLI_L2_USER_P:
4708 break;
4709 }
4710 break;
4711 }
4712 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4713 if(ie->l2_q933 != 0)
4714 return -1;
4715
4716 switch(ie->l2_mode) {
4717 default:
4718 return -1;
4719
4720 case UNI_BLLI_L2NORM:
4721 case UNI_BLLI_L2EXT:
4722 break;
4723 }
4724 }
4725 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4726 if(ie->l2_wsiz == 0 || ie->l2_wsiz > 127)
4727 return -1;
4728 }
4729 if(ie->h.present & UNI_BLLI_L2_USER_P) {
4730 if(ie->l2_user > 127)
4731 return -1;
4732 }
4733 }
4734 if(ie->h.present & UNI_BLLI_L3_P) {
4735 static u_int mask =
4736 UNI_BLLI_L3_MODE_P | UNI_BLLI_L3_PSIZ_P |
4737 UNI_BLLI_L3_WSIZ_P | UNI_BLLI_L3_USER_P |
4738 UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P |
4739 UNI_BLLI_L3_TTYPE_P | UNI_BLLI_L3_MUX_P;
4740
4741 switch(ie->l3) {
4742 default:
4743 return -1;
4744
4745 case UNI_BLLI_L3_X25:
4746 case UNI_BLLI_L3_ISO8208:
4747 case UNI_BLLI_L3_X223:
4748 switch(ie->h.present & mask) {
4749 default:
4750 return -1;
4751
4752 case 0:
4753 case UNI_BLLI_L3_MODE_P:
4754 case UNI_BLLI_L3_MODE_P |
4755 UNI_BLLI_L3_PSIZ_P:
4756 case UNI_BLLI_L3_MODE_P |
4757 UNI_BLLI_L3_PSIZ_P |
4758 UNI_BLLI_L3_WSIZ_P:
4759 break;
4760 }
4761 break;
4762
4763 case UNI_BLLI_L3_CLMP:
4764 case UNI_BLLI_L3_T70:
4765 if(ie->h.present & mask)
4766 return -1;
4767 break;
4768
4769 case UNI_BLLI_L3_TR9577:
4770 switch(ie->h.present & mask) {
4771 default:
4772 return -1;
4773
4774 case 0:
4775 case UNI_BLLI_L3_IPI_P:
4776 case UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P:
4777 break;
4778 }
4779 break;
4780
4781 case UNI_BLLI_L3_H310:
4782 switch(ie->h.present & mask) {
4783 default:
4784 return -1;
4785
4786 case 0:
4787 case UNI_BLLI_L3_TTYPE_P:
4788 case UNI_BLLI_L3_TTYPE_P|UNI_BLLI_L3_MUX_P:
4789 break;
4790 }
4791 break;
4792
4793 case UNI_BLLI_L3_USER:
4794 switch(ie->h.present & mask) {
4795 default:
4796 return -1;
4797
4798 case 0: /* XXX ? */
4799 case UNI_BLLI_L3_USER_P:
4800 break;
4801 }
4802 break;
4803 }
4804 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4805 switch(ie->l3_mode) {
4806 default:
4807 return -1;
4808
4809 case UNI_BLLI_L3NSEQ:
4810 case UNI_BLLI_L3ESEQ:
4811 break;
4812 }
4813 }
4814 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4815 switch(ie->l3_psiz) {
4816 default:
4817 return -1;
4818
4819 case UNI_BLLI_L3_16:
4820 case UNI_BLLI_L3_32:
4821 case UNI_BLLI_L3_64:
4822 case UNI_BLLI_L3_128:
4823 case UNI_BLLI_L3_256:
4824 case UNI_BLLI_L3_512:
4825 case UNI_BLLI_L3_1024:
4826 case UNI_BLLI_L3_2048:
4827 case UNI_BLLI_L3_4096:
4828 break;
4829 }
4830 }
4831 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4832 if(ie->l3_wsiz == 0 || ie->l3_wsiz > 127)
4833 return -1;
4834 }
4835 if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4836 if(ie->l3_ipi == UNI_BLLI_L3_SNAP) {
4837 if(!(ie->h.present & UNI_BLLI_L3_SNAP_P))
4838 return -1;
4839 } else {
4840 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4841 return -1;
4842 }
4843 }
4844 if(ie->h.present & UNI_BLLI_L3_USER_P) {
4845 if(ie->l3_user > 127)
4846 return -1;
4847 }
4848 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4849 if(ie->oui >= (1<<24))
4850 return -1;
4851 if(ie->pid >= (1<<16))
4852 return -1;
4853 }
4854 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4855 switch(ie->l3_ttype) {
4856 default:
4857 return -1;
4858
4859 case UNI_BLLI_L3_TTYPE_RECV:
4860 case UNI_BLLI_L3_TTYPE_SEND:
4861 case UNI_BLLI_L3_TTYPE_BOTH:
4862 break;
4863 }
4864 switch(ie->l3_tcap) {
4865 default:
4866 return -1;
4867
4868 case UNI_BLLI_L3_TCAP_NOIND:
4869 case UNI_BLLI_L3_TCAP_AAL1:
4870 case UNI_BLLI_L3_TCAP_AAL5:
4871 case UNI_BLLI_L3_TCAP_AAL15:
4872 break;
4873 }
4874 }
4875 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4876 switch(ie->l3_fmux) {
4877 default:
4878 return -1;
4879
4880 case UNI_BLLI_L3_MUX_NOMUX:
4881 case UNI_BLLI_L3_MUX_TS:
4882 case UNI_BLLI_L3_MUX_TSFEC:
4883 case UNI_BLLI_L3_MUX_PS:
4884 case UNI_BLLI_L3_MUX_PSFEC:
4885 case UNI_BLLI_L3_MUX_H221:
4886 break;
4887 }
4888 switch(ie->l3_bmux) {
4889 default:
4890 return -1;
4891
4892 case UNI_BLLI_L3_MUX_NOMUX:
4893 case UNI_BLLI_L3_MUX_TS:
4894 case UNI_BLLI_L3_MUX_TSFEC:
4895 case UNI_BLLI_L3_MUX_PS:
4896 case UNI_BLLI_L3_MUX_PSFEC:
4897 case UNI_BLLI_L3_MUX_H221:
4898 break;
4899 }
4900 }
4901 }
4902
4903 return 0;
4904}
4905
4906DEF_IE_ENCODE(itu, blli)
4907{
4908 START_IE(blli, UNI_IE_BLLI, 13);
4909
4910 if (IE_ISERROR(*ie)) {
4911 APP_BYTE(msg, 0xff);
4912 APP_BYTE(msg, 0xff);
4913 goto out;
4914 }
4915
4916 if(ie->h.present & UNI_BLLI_L1_P)
4917 APP_BYTE(msg, (UNI_BLLI_L1_ID<<5)|ie->l1|0x80);
4918
4919 if(ie->h.present & UNI_BLLI_L2_P) {
4920 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4921 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4922 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4923 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933);
4924 APP_BYTE(msg, ie->l2_wsiz | 0x80);
4925 } else {
4926 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933|0x80);
4927 }
4928 } else if(ie->h.present & UNI_BLLI_L2_USER_P) {
4929 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4930 APP_BYTE(msg, ie->l2_user | 0x80);
4931 } else {
4932 APP_BYTE(msg, (UNI_BLLI_L2_ID << 5) | ie->l2 | 0x80);
4933 }
4934 }
4935
4936 if(ie->h.present & UNI_BLLI_L3_P) {
4937 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4938 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4939 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4940 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4941 APP_BYTE(msg,(ie->l3_mode<<5));
4942 APP_BYTE(msg,ie->l3_psiz);
4943 APP_BYTE(msg,ie->l3_wsiz|0x80);
4944 } else {
4945 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4946 APP_BYTE(msg,(ie->l3_mode<<5));
4947 APP_BYTE(msg,(ie->l3_psiz|0x80));
4948 }
4949 } else {
4950 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4951 APP_BYTE(msg, (ie->l3_mode<<5)|0x80);
4952 }
4953 } else if(ie->h.present & UNI_BLLI_L3_USER_P) {
4954 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4955 APP_BYTE(msg,(ie->l3_user|0x80));
4956 } else if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4957 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4958 APP_BYTE(msg,((ie->l3_ipi>>1) & 0x7f));
4959 APP_BYTE(msg,(((ie->l3_ipi&1)<<6)|0x80));
4960 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4961 APP_BYTE(msg, 0x80);
4962 APP_BYTE(msg, (ie->oui >> 16));
4963 APP_BYTE(msg, (ie->oui >> 8));
4964 APP_BYTE(msg, (ie->oui >> 0));
4965 APP_BYTE(msg, (ie->pid >> 8));
4966 APP_BYTE(msg, (ie->pid >> 0));
4967 }
4968 } else if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4969 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4970 APP_BYTE(msg, ie->l3_ttype | (ie->l3_tcap << 4));
4971 APP_BYTE(msg, 0x80 | (ie->l3_fmux << 3) | ie->l3_bmux);
4972 } else {
4973 APP_BYTE(msg, 0x80 | ie->l3_ttype | (ie->l3_tcap << 4));
4974 }
4975 } else {
4976 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3|0x80);
4977 }
4978 }
4979
4980 out:
4981 SET_IE_LEN(msg);
4982 return 0;
4983}
4984
4985DEF_IE_DECODE(itu, blli)
4986{
4987 u_char c;
4988
4989 IE_START(;);
4990
4991 if(ielen > 17)
4992 goto rej;
4993
4994 while(ielen--) {
4995 switch(((c = *msg->b_rptr++) >> 5) & 0x3) {
4996 default:
4997 goto rej;
4998
4999 case UNI_BLLI_L1_ID:
5000 ie->h.present |= UNI_BLLI_L1_P;
5001 ie->l1 = c & 0x1f;
5002 if(!(c & 0x80))
5003 goto rej;
5004 break;
5005
5006 case UNI_BLLI_L2_ID:
5007 ie->h.present |= UNI_BLLI_L2_P;
5008 ie->l2 = c & 0x1f;
5009 if(!(c & 0x80)) {
5010 if(ielen == 0)
5011 goto rej;
5012 ielen--;
5013 c = *msg->b_rptr++;
5014 if(ie->l2 == UNI_BLLI_L2_USER) {
5015 ie->h.present |= UNI_BLLI_L2_USER_P;
5016 ie->l2_user = c & 0x7f;
5017 if(!(c & 0x80))
5018 goto rej;
5019 } else {
5020 ie->h.present |= UNI_BLLI_L2_Q933_P;
5021 ie->l2_q933 = c & 0x3;
5022 ie->l2_mode = (c >> 5) & 0x3;
5023 if(!(c & 0x80)) {
5024 if(ielen == 0)
5025 goto rej;
5026 ielen--;
5027 c = *msg->b_rptr++;
5028 ie->h.present |= UNI_BLLI_L2_WSIZ_P;
5029 ie->l2_wsiz = c & 0x7f;
5030 if(!(c & 0x80))
5031 goto rej;
5032 }
5033 }
5034 }
5035 break;
5036
5037 case UNI_BLLI_L3_ID:
5038 ie->h.present |= UNI_BLLI_L3_P;
5039 ie->l3 = c & 0x1f;
5040 if(!(c & 0x80)) {
5041 switch(ie->l3) {
5042 default:
5043 case UNI_BLLI_L3_CLMP:
5044 case UNI_BLLI_L3_T70:
5045 goto rej;
5046
5047 case UNI_BLLI_L3_X25:
5048 case UNI_BLLI_L3_ISO8208:
5049 case UNI_BLLI_L3_X223:
5050 if(ielen == 0)
5051 goto rej;
5052 ielen--;
5053 c = *msg->b_rptr++;
5054 ie->l3_mode = (c >> 5) & 0x3;
5055 ie->h.present |= UNI_BLLI_L3_MODE_P;
5056
5057 if(c & 0x80)
5058 break;
5059
5060 if(ielen == 0)
5061 goto rej;
5062 ielen--;
5063 c = *msg->b_rptr++;
5064 ie->l3_psiz = c & 0xf;
5065 ie->h.present |= UNI_BLLI_L3_PSIZ_P;
5066
5067 if(c & 0x80)
5068 break;
5069
5070 if(ielen == 0)
5071 goto rej;
5072 ielen--;
5073 c = *msg->b_rptr++;
5074 ie->l3_wsiz = c & 0x7f;
5075 ie->h.present |= UNI_BLLI_L3_WSIZ_P;
5076
5077 if(!(c & 0x80))
5078 goto rej;
5079 break;
5080
5081 case UNI_BLLI_L3_TR9577:
5082 if(ielen < 2)
5083 goto rej;
5084 ielen -= 2;
5085 c = *msg->b_rptr++;
5086 ie->l3_ipi = (c << 1) & 0xfe;
5087 if(c & 0x80)
5088 goto rej;
5089 c = *msg->b_rptr++;
5090 ie->l3_ipi |= c & 1;
5091 if(!(c & 0x80))
5092 goto rej;
5093 ie->h.present |= UNI_BLLI_L3_IPI_P;
5094
5095 if(ie->l3_ipi != UNI_BLLI_L3_SNAP)
5096 break;
5097 if(ielen < 6)
5098 goto rej;
5099 ielen -= 6;
5100 if(*msg->b_rptr++ != 0x80)
5101 goto rej;
5102 ie->h.present |= UNI_BLLI_L3_SNAP_P;
5103 ie->oui = *msg->b_rptr++ << 16;
5104 ie->oui |= *msg->b_rptr++ << 8;
5105 ie->oui |= *msg->b_rptr++;
5106 ie->pid = *msg->b_rptr++ << 8;
5107 ie->pid |= *msg->b_rptr++;
5108 break;
5109
5110 case UNI_BLLI_L3_H310:
5111 if(ielen == 0)
5112 goto rej;
5113 ielen--;
5114 c = *msg->b_rptr++;
5115 ie->l3_ttype = c & 0xf;
5116 ie->l3_tcap = (c >> 4) & 0x7;
5117 ie->h.present |= UNI_BLLI_L3_TTYPE_P;
5118 if(c & 0x80)
5119 break;
5120 if(ielen == 0)
5121 goto rej;
5122 ielen--;
5123 c = *msg->b_rptr++;
5124 ie->l3_fmux = (c >> 3) & 7;
5125 ie->l3_bmux = c & 7;
5126 ie->h.present |= UNI_BLLI_L3_MUX_P;
5127 if(!(c & 0x80))
5128 goto rej;
5129 break;
5130
5131 case UNI_BLLI_L3_USER:
5132 if(ielen == 0)
5133 goto rej;
5134 ielen--;
5135 c = *msg->b_rptr++;
5136 ie->l3_user = c & 0x7f;
5137 ie->h.present |= UNI_BLLI_L3_USER_P;
5138 if(!(c & 0x80))
5139 goto rej;
5140 break;
5141 }
5142 }
5143 break;
5144 }
5145 }
5146
5147 IE_END(BLLI);
5148}
5149
5150/*********************************************************************
5151 *
5152 * Broadband locking shift
5153 * Broadband non-locking shift.
5154 *
5155 * References for this IE are:
5156 *
5157 * Q.2931 pp. 41...42
5158 * UNI4.0 pp. 9
5159 *
5160 * Procedure not supported in UNI4.0, but IE's must be recognized.
5161 *
5162 * Only ITU-T coding allowed.
5163 */
5164
5165DEF_IE_PRINT(itu, lshift)
5166{
5167 if(uni_print_iehdr("locking_shift", &ie->h, cx))
5168 return;
5169 uni_print_ieend(cx);
5170}
5171
5172DEF_IE_CHECK(itu, lshift)
5173{
5174 cx = cx; ie = ie;
5175 return -1;
5176}
5177
5178DEF_IE_ENCODE(itu, lshift)
5179{
5180 START_IE(lshift, UNI_IE_LSHIFT, 1);
5181 APP_BYTE(msg, 0x80 | ie->set);
5182 SET_IE_LEN(msg);
5183 return 0;
5184}
5185
5186DEF_IE_DECODE(itu, lshift)
5187{
5188 u_char c;
5189
5190 IE_START(;);
5191
5192 if(ielen != 1)
5193 goto rej;
5194
5195 c = *msg->b_rptr++;
5196
5197 if(!(c & 0x80))
5198 goto rej;
5199 ie->set = c & 7;
5200
5201 IE_END(LSHIFT);
5202}
5203
5204/***********************************************************************/
5205
5206DEF_IE_PRINT(itu, nlshift)
5207{
5208 if(uni_print_iehdr("nonlocking_shift", &ie->h, cx))
5209 return;
5210 uni_print_ieend(cx);
5211}
5212
5213DEF_IE_CHECK(itu, nlshift)
5214{
5215 cx = cx; ie = ie;
5216 return -1;
5217}
5218
5219DEF_IE_ENCODE(itu, nlshift)
5220{
5221 START_IE(nlshift, UNI_IE_NLSHIFT, 1);
5222 APP_BYTE(msg, 0x80 | ie->set);
5223 SET_IE_LEN(msg);
5224 return 0;
5225}
5226
5227DEF_IE_DECODE(itu, nlshift)
5228{
5229 u_char c;
5230
5231 IE_START(;);
5232
5233 if(ielen != 1)
5234 goto rej;
5235
5236 c = *msg->b_rptr++;
5237
5238 if(!(c & 0x80))
5239 goto rej;
5240 ie->set = c & 7;
5241
5242 IE_END(NLSHIFT);
5243}
5244
5245/*********************************************************************
5246 *
5247 * Broadband Sending Complete Indicator
5248 *
5249 * References for this IE are:
5250 *
5251 * Q.2931 pp. 74-75
5252 *
5253 * Only ITU-T coding allowed.
5254 */
5255DEF_IE_PRINT(itu, scompl)
5256{
5257 if(uni_print_iehdr("sending_complete", &ie->h, cx))
5258 return;
5259 uni_print_ieend(cx);
5260}
5261
5262DEF_IE_CHECK(itu, scompl)
5263{
5264 ie = ie; cx = cx;
5265 return 0;
5266}
5267
5268DEF_IE_ENCODE(itu, scompl)
5269{
5270 START_IE(scompl, UNI_IE_SCOMPL, 1);
5271
5272 APP_BYTE(msg, 0x80 | 0x21);
5273
5274 SET_IE_LEN(msg);
5275 return 0;
5276}
5277
5278DEF_IE_DECODE(itu, scompl)
5279{
5280 IE_START(;);
5281
5282 if(ielen != 1)
5283 goto rej;
5284
5285 if(*msg->b_rptr++ != (0x80 | 0x21))
5286 goto rej;
5287
5288 IE_END(SCOMPL);
5289}
5290
5291/*********************************************************************
5292 *
5293 * Broadband Repeat Indicator
5294 *
5295 * References for this IE are:
5296 *
5297 * Q.2931 p. 73
5298 * PNNI1.0 p. 196
5299 *
5300 * Q.2931 has table 4-19. Only codepoints 0x2 and 0xa (for PNNI) supported.
5301 *
5302 * Only ITU-T coding allowed.
5303 */
5304DEF_IE_PRINT(itu, repeat)
5305{
5306 static const struct uni_print_tbl tbl[] = {
5307 MKT(UNI_REPEAT_PRIDESC, desc),
5308 MKT(UNI_REPEAT_STACK, stack),
5309 EOT()
5310 };
5311
5312 if(uni_print_iehdr("repeat", &ie->h, cx))
5313 return;
5314 uni_print_tbl("type", ie->type, tbl, cx);
5315 uni_print_ieend(cx);
5316}
5317
5318DEF_IE_CHECK(itu, repeat)
5319{
5320 switch(ie->type) {
5321
5322 case UNI_REPEAT_PRIDESC:
5323 break;
5324
5325 case UNI_REPEAT_STACK:
5326 if(!cx->pnni)
5327 return -1;
5328 break;
5329
5330 default:
5331 return -1;
5332 }
5333 return 0;
5334}
5335
5336DEF_IE_ENCODE(itu, repeat)
5337{
5338 START_IE(repeat, UNI_IE_REPEAT, 1);
5339
5340 APP_BYTE(msg, 0x80 | ie->type);
5341
5342 SET_IE_LEN(msg);
5343 return 0;
5344}
5345
5346DEF_IE_DECODE(itu, repeat)
5347{
5348 u_char c;
5349
5350 IE_START(;);
5351
5352 if(ielen != 1)
5353 goto rej;
5354
5355 c = *msg->b_rptr++;
5356 if(!(c & 0x80))
5357 goto rej;
5358 ie->type = c & 0xf;
5359
5360 IE_END(REPEAT);
5361}
5362
5363/*********************************************************************
5364 *
5365 * Transit Network Selection
5366 *
5367 * References for this IE are:
5368 *
5369 * Q.2931 pp. 75...76
5370 * UNI4.0 pp. 17
5371 *
5372 * According to UNI4.0 this is always National Network Id/Carried Id.
5373 *
5374 * ITU-T/Net coding allowed.
5375 */
5376
5377DEF_IE_PRINT(itu, tns)
5378{
5379 u_int i;
5380
5381 if(uni_print_iehdr("tns", &ie->h, cx))
5382 return;
5383 uni_print_entry(cx, "net", "%u,\"", ie->len);
5384 uni_putc('"', cx);
5385 for(i = 0; i < ie->len; i++) {
5386 if(ie->net[i] < ' ')
5387 uni_printf(cx, "^%c", ie->net[i] + '@');
5388 else if(ie->net[i] < '~')
5389 uni_putc(ie->net[i], cx);
5390 else
5391 uni_printf(cx, "\\%03o", ie->net[i]);
5392 }
5393 uni_putc('"', cx);
5394 uni_print_ieend(cx);
5395}
5396
5397DEF_IE_CHECK(itu, tns)
5398{
5399 u_int i;
5400
5401 cx = cx;
5402
5403 if(ie->len == 0 || ie->len > UNI_TNS_MAXLEN)
5404 return -1;
5405 for(i = 0; i < ie->len; i++)
5406 if(ie->net[i] < ' ' || ie->net[i] > '~')
5407 return -1;
5408 return 0;
5409}
5410
5411DEF_IE_ENCODE(itu, tns)
5412{
5413 START_IE(tns, UNI_IE_TNS, ie->len + 1);
5414
5415 APP_BYTE(msg, 0x80 | (0x2 << 4) | 0x1);
5416 APP_BUF(msg, ie->net, ie->len);
5417
5418 SET_IE_LEN(msg);
5419 return 0;
5420}
5421
5422DEF_IE_DECODE(itu, tns)
5423{
5424 IE_START(;);
5425
5426 if(ielen < 2 || ielen > 5)
5427 goto rej;
5428
5429 if(*msg->b_rptr++ != (0x80 | (0x2 << 4) | 0x1))
5430 goto rej;
5431 ielen--;
5432
5433 ie->len = 0;
5434 while(ielen--)
5435 ie->net[ie->len++] = *msg->b_rptr++;
5436
5437 IE_END(TNS);
5438}
5439
5440/*********************************************************************
5441 *
5442 * Restart indicator
5443 *
5444 * References for this IE are:
5445 *
5446 * Q.2931 pp. 73...74
5447 * UNI4.0 p. 17
5448 *
5449 * Only ITU-T coding allowed.
5450 */
5451
5452DEF_IE_PRINT(itu, restart)
5453{
5454 static const struct uni_print_tbl tbl[] = {
5455 MKT(UNI_RESTART_CHANNEL, channel),
5456 MKT(UNI_RESTART_PATH, path),
5457 MKT(UNI_RESTART_ALL, all),
5458 EOT()
5459 };
5460
5461 if(uni_print_iehdr("restart", &ie->h, cx))
5462 return;
5463 uni_print_tbl("class", ie->rclass, tbl, cx);
5464 uni_print_ieend(cx);
5465}
5466
5467DEF_IE_CHECK(itu, restart)
5468{
5469 cx = cx;
5470
5471 switch(ie->rclass) {
5472 default:
5473 return -1;
5474
5475 case UNI_RESTART_CHANNEL:
5476 case UNI_RESTART_PATH:
5477 case UNI_RESTART_ALL:
5478 break;
5479 }
5480
5481 return 0;
5482}
5483
5484DEF_IE_ENCODE(itu, restart)
5485{
5486 START_IE(restart, UNI_IE_RESTART, 1);
5487
5488 APP_BYTE(msg, 0x80 | ie->rclass);
5489
5490 SET_IE_LEN(msg);
5491 return 0;
5492}
5493
5494DEF_IE_DECODE(itu, restart)
5495{
5496 u_char c;
5497
5498 IE_START(;);
5499
5500 if(ielen != 1)
5501 goto rej;
5502
5503 ie->rclass = (c = *msg->b_rptr++) & 0x7;
5504
5505 if(!(c & 0x80))
5506 goto rej;
5507
5508 IE_END(RESTART);
5509}
5510
5511/*********************************************************************
5512 *
5513 * User-to-user info.
5514 *
5515 * References for this IE are:
5516 *
5517 * Q.2957
5518 *
5519 * Only ITU-T coding allowed.
5520 */
5521
5522DEF_IE_PRINT(itu, uu)
5523{
5524 u_int i;
5525
5526 if(uni_print_iehdr("uu", &ie->h, cx))
5527 return;
5528 uni_print_entry(cx, "len", "%u", ie->len);
5529 uni_print_entry(cx, "info", "(");
5530 for(i = 0; i < ie->len; i++)
5531 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->uu[i]);
5532 uni_printf(cx, ")");
5533 uni_print_ieend(cx);
5534}
5535
5536DEF_IE_CHECK(itu, uu)
5537{
5538 cx = cx;
5539
5540 if(ie->len > UNI_UU_MAXLEN)
5541 return -1;
5542
5543 return 0;
5544}
5545
5546DEF_IE_ENCODE(itu, uu)
5547{
5548 START_IE(uu, UNI_IE_UU, ie->len);
5549
5550 APP_BUF(msg, ie->uu, ie->len);
5551
5552 SET_IE_LEN(msg);
5553 return 0;
5554}
5555
5556DEF_IE_DECODE(itu, uu)
5557{
5558 IE_START(;);
5559
5560 if(ielen > UNI_UU_MAXLEN || ielen < 1)
5561 goto rej;
5562
5563 ie->len = ielen;
5564 ielen = 0;
5565 (void)memcpy(ie->uu, msg->b_rptr, ie->len);
5566 msg->b_rptr += ie->len;
5567
5568 IE_END(UU);
5569}
5570
5571/*********************************************************************
5572 *
5573 * Generic Identifier Transport
5574 *
5575 * References for this IE are:
5576 *
5577 * UNI4.0 pp. 26...28
5578 *
5579 * UNI4.0 prescribes a fixed format for this IE. We have a flag in the
5580 * context structur, which tells us whether the check of this IE should be
5581 * hard or soft. Probably it should be hard for end systems and soft for
5582 * network nodes.
5583 *
5584 * Only Net Coding allowed. (XXX)
5585 */
5586
5587DEF_IE_PRINT(net, git)
5588{
5589 static const struct uni_print_tbl std_tbl[] = {
5590 MKT(UNI_GIT_STD_DSMCC, dsmcc),
5591 MKT(UNI_GIT_STD_H245, H.245),
5592 EOT()
5593 };
5594 static const struct uni_print_tbl type_tbl[] = {
5595 MKT(UNI_GIT_TYPE_SESS, sess),
5596 MKT(UNI_GIT_TYPE_RES, res),
5597 EOT()
5598 };
5599 u_int i, j;
5600 char buf[20];
5601
5602 if(uni_print_iehdr("git", &ie->h, cx))
5603 return;
5604
5605 uni_print_tbl("std", ie->std, std_tbl, cx);
5606
5607 uni_print_eol(cx);
5608 uni_print_push_prefix("id", cx);
5609 cx->indent++;
5610 for(i = 0; i < ie->numsub; i++) {
5611 sprintf(buf, "%u", i);
5612 uni_print_entry(cx, buf, "(");
5613 uni_print_tbl(NULL, ie->sub[i].type, type_tbl, cx);
5614 for(j = 0; j < ie->sub[i].len; j++)
5615 uni_printf(cx, ",0x%02x", ie->sub[i].val[j]);
5616 uni_printf(cx, ")");
5617 uni_print_eol(cx);
5618 }
5619 cx->indent--;
5620 uni_print_pop_prefix(cx);
5621
5622 uni_print_ieend(cx);
5623}
5624
5625DEF_IE_CHECK(net, git)
5626{
5627 u_int i;
5628
5629 if(cx->git_hard) {
5630 switch(ie->std) {
5631 case UNI_GIT_STD_DSMCC:
5632 case UNI_GIT_STD_H245:
5633 break;
5634 default:
5635 return -1;
5636 }
5637 if(ie->numsub != 2)
5638 return -1;
5639 if(ie->sub[0].type != UNI_GIT_TYPE_SESS)
5640 return -1;
5641 if(ie->sub[0].len > UNI_GIT_MAXSESS)
5642 return -1;
5643 if(ie->sub[1].type != UNI_GIT_TYPE_RES)
5644 return -1;
5645 if(ie->sub[1].len > UNI_GIT_MAXRES)
5646 return -1;
5647 } else {
5648 if(ie->numsub > UNI_GIT_MAXSUB)
5649 return -1;
5650 for(i = 0; i < ie->numsub; i++)
5651 if(ie->sub[i].len > UNI_GIT_MAXVAL)
5652 return -1;
5653 }
5654 return 0;
5655}
5656
5657DEF_IE_ENCODE(net, git)
5658{
5659 u_int i;
5660
5661 START_IE(git, UNI_IE_GIT, 1 + ie->numsub * (1 + UNI_GIT_MAXVAL));
5662
5663 APP_BYTE(msg, ie->std);
5664 for(i = 0; i < ie->numsub; i++) {
5665 APP_BYTE(msg, ie->sub[i].type);
5666 APP_BYTE(msg, ie->sub[i].len);
5667 APP_BUF(msg, ie->sub[i].val, ie->sub[i].len);
5668 }
5669
5670 SET_IE_LEN(msg);
5671 return 0;
5672}
5673
5674DEF_IE_DECODE(net, git)
5675{
5676 IE_START(;);
5677
5678 if(ielen > 1 + UNI_GIT_MAXSUB * (1 + UNI_GIT_MAXVAL) || ielen < 1)
5679 goto rej;
5680
5681 ie->std = *msg->b_rptr++;
5682 ielen--;
5683
5684 ie->numsub = 0;
5685 while(ielen > 0) {
5686 if(ie->numsub >= UNI_GIT_MAXSUB)
5687 goto rej;
5688
5689 ie->sub[ie->numsub].type = *msg->b_rptr++;
5690 ielen--;
5691
5692 if(ielen == 0)
5693 goto rej;
5694 ie->sub[ie->numsub].len = *msg->b_rptr++;
5695 ielen--;
5696
5697 if(ie->sub[ie->numsub].len > UNI_GIT_MAXVAL)
5698 goto rej;
5699 if(ie->sub[ie->numsub].len > (u_int)ielen)
5700 goto rej;
5701
5702 (void)memcpy(ie->sub[ie->numsub].val, msg->b_rptr, ie->sub[ie->numsub].len);
5703 ielen -= ie->sub[ie->numsub].len;
5704 msg->b_rptr += ie->sub[ie->numsub].len;
5705
5706 ie->numsub++;
5707 }
5708
5709 IE_END(GIT);
5710}
5711
5712/*********************************************************************
5713 *
5714 * Additional ABR Parameters
5715 * ABR Setup parameters
5716 *
5717 * References for this IE are:
5718 *
5719 * UNI4.0 pp. 78...82
5720 * PNNI1.0 p. 195
5721 *
5722 * Notes:
5723 * Only NET coding.
5724 */
5725
5726static void
5727print_abr_rec(struct unicx *cx, struct uni_abr_rec *rec)
5728{
5729 if(rec->present & UNI_ABR_REC_NRM_P)
5730 uni_print_entry(cx, "nrm", "%d", rec->nrm);
5731 if(rec->present & UNI_ABR_REC_TRM_P)
5732 uni_print_entry(cx, "trm", "%d", rec->trm);
5733 if(rec->present & UNI_ABR_REC_CDF_P)
5734 uni_print_entry(cx, "cdf", "%d", rec->cdf);
5735 if(rec->present & UNI_ABR_REC_ADTF_P)
5736 uni_print_entry(cx, "adtf", "%d", rec->adtf);
5737}
5738
5739DEF_IE_PRINT(net, abradd)
5740{
5741 if(uni_print_iehdr("abradd", &ie->h, cx))
5742 return;
5743
5744 uni_print_push_prefix("fwd", cx);
5745 print_abr_rec(cx, &ie->fwd);
5746 uni_print_pop_prefix(cx);
5747
5748 uni_print_push_prefix("bwd", cx);
5749 print_abr_rec(cx, &ie->bwd);
5750 uni_print_pop_prefix(cx);
5751
5752 uni_print_ieend(cx);
5753}
5754
5755DEF_IE_CHECK(net, abradd)
5756{
5757 cx = cx;
5758 ie = ie;
5759
5760 return 0;
5761}
5762
5763static u_int
5764encode_abr_rec(struct uni_abr_rec *rec)
5765{
5766 u_int ret = rec->present & 0xf000;
5767
5768 if(ret & UNI_ABR_REC_NRM_P)
5769 ret |= (rec->nrm & 0x7) << 25;
5770 if(ret & UNI_ABR_REC_TRM_P)
5771 ret |= (rec->trm & 0x7) << 22;
5772 if(ret & UNI_ABR_REC_CDF_P)
5773 ret |= (rec->cdf & 0x7) << 19;
5774 if(ret & UNI_ABR_REC_ADTF_P)
5775 ret |= (rec->adtf & 0x3ff) << 9;
5776
5777 return ret;
5778}
5779
5780DEF_IE_ENCODE(net, abradd)
5781{
5782 START_IE(abradd, UNI_IE_ABRADD, 10);
5783
5784 APP_SUB_32BIT(msg, UNI_ABRADD_FADD_ID, encode_abr_rec(&ie->fwd));
5785 APP_SUB_32BIT(msg, UNI_ABRADD_BADD_ID, encode_abr_rec(&ie->bwd));
5786
5787 SET_IE_LEN(msg);
5788 return 0;
5789}
5790
5791static int
5792decode_abr_rec(struct uni_msg *msg, struct uni_abr_rec *rec)
5793{
5794 u_int val;
5795
5796 val = *msg->b_rptr++ << 24;
5797 val |= *msg->b_rptr++ << 16;
5798 val |= *msg->b_rptr++ << 8;
5799 val |= *msg->b_rptr++ << 0;
5800
5801 rec->present = val & 0xf000;
5802
5803 rec->nrm = (val & UNI_ABR_REC_NRM_P) ? ((val >> 25) & 0x7) : 0;
5804 rec->trm = (val & UNI_ABR_REC_TRM_P) ? ((val >> 22) & 0x7) : 0;
5805 rec->cdf = (val & UNI_ABR_REC_CDF_P) ? ((val >> 19) & 0x7) : 0;
5806 rec->adtf = (val & UNI_ABR_REC_ADTF_P)? ((val >> 9) & 0x3ff) : 0;
5807
5808 return 0;
5809}
5810
5811DEF_IE_DECODE(net, abradd)
5812{
5813 IE_START(;);
5814
5815 if(ielen != 10)
5816 goto rej;
5817
5818
5819 while(ielen--) {
5820 switch(*msg->b_rptr++) {
5821
5822 default:
5823 goto rej;
5824
5825 case UNI_ABRADD_FADD_ID:
5826 if(decode_abr_rec(msg, &ie->fwd))
5827 goto rej;
5828 ielen -= 4;
5829 break;
5830
5831 case UNI_ABRADD_BADD_ID:
5832 if(decode_abr_rec(msg, &ie->bwd))
5833 goto rej;
5834 ielen -= 4;
5835 break;
5836 }
5837 }
5838 IE_END(ABRADD);
5839}
5840
5841/*********************************************************************/
5842
5843DEF_IE_PRINT(net, abrsetup)
5844{
5845 if(uni_print_iehdr("abrsetup", &ie->h, cx))
5846 return;
5847
5848 uni_print_entry(cx, "rm_frt", "%d", ie->rmfrt);
5849
5850 uni_print_push_prefix("fwd", cx);
5851 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5852 uni_print_entry(cx, "icr", "%d", ie->ficr);
5853 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5854 uni_print_entry(cx, "tbe", "%d", ie->ftbe);
5855 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5856 uni_print_entry(cx, "rif", "%d", ie->frif);
5857 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5858 uni_print_entry(cx, "rdf", "%d", ie->frdf);
5859 uni_print_pop_prefix(cx);
5860
5861 uni_print_push_prefix("bwd", cx);
5862 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5863 uni_print_entry(cx, "icr", "%d", ie->bicr);
5864 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5865 uni_print_entry(cx, "tbe", "%d", ie->btbe);
5866 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5867 uni_print_entry(cx, "rif", "%d", ie->brif);
5868 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5869 uni_print_entry(cx, "rdf", "%d", ie->brdf);
5870 uni_print_pop_prefix(cx);
5871
5872 uni_print_ieend(cx);
5873}
5874
5875DEF_IE_CHECK(net, abrsetup)
5876{
5877 if(cx->pnni) {
5878 if(!(ie->h.present & UNI_ABRSETUP_FICR_P))
5879 return -1;
5880 if(!(ie->h.present & UNI_ABRSETUP_BICR_P))
5881 return -1;
5882 if(!(ie->h.present & UNI_ABRSETUP_FTBE_P))
5883 return -1;
5884 if(!(ie->h.present & UNI_ABRSETUP_BTBE_P))
5885 return -1;
5886 if(!(ie->h.present & UNI_ABRSETUP_FRIF_P))
5887 return -1;
5888 if(!(ie->h.present & UNI_ABRSETUP_BRIF_P))
5889 return -1;
5890 if(!(ie->h.present & UNI_ABRSETUP_FRDF_P))
5891 return -1;
5892 if(!(ie->h.present & UNI_ABRSETUP_BRDF_P))
5893 return -1;
5894 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5895 return -1;
5896 }
5897
5898 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5899 return -1;
5900
5901 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5902 if(ie->ficr >= 1 << 24)
5903 return -1;
5904 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5905 if(ie->bicr >= 1 << 24)
5906 return -1;
5907
5908 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5909 if(ie->ftbe >= 1 << 24 || ie->ftbe == 0)
5910 return -1;
5911 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5912 if(ie->btbe >= 1 << 24 || ie->btbe == 0)
5913 return -1;
5914
5915 if(ie->rmfrt >= 1 << 24)
5916 return -1;
5917
5918 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5919 if(ie->frif > 15)
5920 return -1;
5921 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5922 if(ie->frdf > 15)
5923 return -1;
5924 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5925 if(ie->brif > 15)
5926 return -1;
5927 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5928 if(ie->brdf > 15)
5929 return -1;
5930 return 0;
5931}
5932
5933DEF_IE_ENCODE(net, abrsetup)
5934{
5935 START_IE(abrsetup, UNI_IE_ABRSETUP, 32);
5936
5937 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FICR_P,
5938 UNI_ABRSETUP_FICR_ID, ie->ficr);
5939 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BICR_P,
5940 UNI_ABRSETUP_BICR_ID, ie->bicr);
5941 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FTBE_P,
5942 UNI_ABRSETUP_FTBE_ID, ie->ftbe);
5943 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BTBE_P,
5944 UNI_ABRSETUP_BTBE_ID, ie->btbe);
5945 APP_SUB_24BIT(msg, UNI_ABRSETUP_RMFRT_ID, ie->rmfrt);
5946 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRIF_P,
5947 UNI_ABRSETUP_FRIF_ID, ie->frif);
5948 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRIF_P,
5949 UNI_ABRSETUP_BRIF_ID, ie->brif);
5950 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRDF_P,
5951 UNI_ABRSETUP_FRDF_ID, ie->frdf);
5952 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRDF_P,
5953 UNI_ABRSETUP_BRDF_ID, ie->brdf);
5954
5955 SET_IE_LEN(msg);
5956 return 0;
5957}
5958
5959DEF_IE_DECODE(net, abrsetup)
5960{
5961 IE_START(;);
5962
5963 if(ielen < 4 || ielen > 32)
5964 goto rej;
5965
5966
5967 while(ielen--) {
5968 switch(*msg->b_rptr++) {
5969
5970 default:
5971 goto rej;
5972
5973
5974 DEC_GETF3(ABRSETUP_FICR, ficr, ie->h.present);
5975 DEC_GETF3(ABRSETUP_BICR, bicr, ie->h.present);
5976 DEC_GETF3(ABRSETUP_FTBE, ftbe, ie->h.present);
5977 DEC_GETF3(ABRSETUP_BTBE, btbe, ie->h.present);
5978 DEC_GETF1(ABRSETUP_FRIF, frif, ie->h.present);
5979 DEC_GETF1(ABRSETUP_BRIF, brif, ie->h.present);
5980 DEC_GETF1(ABRSETUP_FRDF, frdf, ie->h.present);
5981 DEC_GETF1(ABRSETUP_BRDF, brdf, ie->h.present);
5982 DEC_GETF3(ABRSETUP_RMFRT, frif, ie->h.present);
5983 }
5984 }
5985 IE_END(ABRSETUP);
5986}
5987
5988/*********************************************************************
5989 *
5990 * Broadband report type
5991 *
5992 * References for this IE are:
5993 *
5994 * Q.2963.1 pp. 7...8
5995 *
5996 * Only ITU-T coding allowed.
5997 */
5998
5999DEF_IE_PRINT(itu, report)
6000{
6001 static const struct uni_print_tbl tbl[] = {
6002 MKT(UNI_REPORT_MODCONF, modconf),
6003 MKT(UNI_REPORT_CLOCK, clock),
6004 MKT(UNI_REPORT_EEAVAIL, eeavail),
6005 MKT(UNI_REPORT_EEREQ, eereq),
6006 MKT(UNI_REPORT_EECOMPL, eecompl),
6007 EOT()
6008 };
6009
6010 if(uni_print_iehdr("report", &ie->h, cx))
6011 return;
6012 uni_print_tbl("type", ie->report, tbl, cx);
6013 uni_print_ieend(cx);
6014}
6015
6016DEF_IE_CHECK(itu, report)
6017{
6018 cx = cx;
6019
6020 switch(ie->report) {
6021
6022 default:
6023 return -1;
6024
6025 case UNI_REPORT_MODCONF:
6026 case UNI_REPORT_CLOCK:
6027 case UNI_REPORT_EEAVAIL:
6028 case UNI_REPORT_EEREQ:
6029 case UNI_REPORT_EECOMPL:
6030 break;
6031 }
6032 return 0;
6033}
6034
6035DEF_IE_ENCODE(itu, report)
6036{
6037 START_IE(report, UNI_IE_REPORT, 1);
6038
6039 APP_BYTE(msg, ie->report);
6040
6041 SET_IE_LEN(msg);
6042 return 0;
6043}
6044
6045DEF_IE_DECODE(itu, report)
6046{
6047 IE_START(;);
6048 if(ielen != 1)
6049 goto rej;
6050
6051 ie->report = *msg->b_rptr++;
6052
6053 IE_END(REPORT);
6054}
6055
6056/*********************************************************************
6057 *
6058 * Soft PVPC/PVCC
6059 *
6060 * References for this IE are:
6061 *
6062 * PNNI1.0 pp. 201...203
6063 *
6064 * Only NET coding allowed.
6065 */
6066DEF_IE_PRINT(net, calling_soft)
6067{
6068 if(uni_print_iehdr("calling_soft", &ie->h, cx))
6069 return;
6070
6071 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6072 if(ie->h.present & UNI_CALLING_SOFT_VCI_P)
6073 uni_print_entry(cx, "vci", "%d", ie->vci);
6074
6075 uni_print_ieend(cx);
6076}
6077
6078DEF_IE_PRINT(net, called_soft)
6079{
6080 static const struct uni_print_tbl tab[] = {
6081 MKT(UNI_SOFT_SEL_ANY, any),
6082 MKT(UNI_SOFT_SEL_REQ, required),
6083 MKT(UNI_SOFT_SEL_ASS, assigned),
6084 EOT()
6085 };
6086
6087 if(uni_print_iehdr("called_soft", &ie->h, cx))
6088 return;
6089
6090 uni_print_tbl("selection", ie->sel, tab, cx);
6091 if(ie->h.present & UNI_CALLED_SOFT_VPI_P)
6092 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6093 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6094 uni_print_entry(cx, "vci", "%d", ie->vci);
6095
6096 uni_print_ieend(cx);
6097}
6098
6099DEF_IE_CHECK(net, calling_soft)
6100{
6101 cx = cx;
6102
6103 if(ie->vpi >= 1 << 12)
6104 return -1;
6105 return 0;
6106}
6107
6108DEF_IE_CHECK(net, called_soft)
6109{
6110 cx = cx;
6111
6112 switch(ie->sel) {
6113
6114 case UNI_SOFT_SEL_ANY:
6115 case UNI_SOFT_SEL_REQ:
6116 case UNI_SOFT_SEL_ASS:
6117 break;
6118
6119 default:
6120 return -1;
6121 }
6122 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6123 if(ie->vpi >= 1 << 12)
6124 return -1;
6125 } else {
6126 if(ie->sel != UNI_SOFT_SEL_ANY)
6127 return -1;
6128 }
6129
6130 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6131 if(!(ie->h.present & UNI_CALLED_SOFT_VPI_P))
6132 return -1;
6133
6134
6135 return 0;
6136}
6137
6138DEF_IE_ENCODE(net, calling_soft)
6139{
6140 START_IE(calling_soft, UNI_IE_CALLING_SOFT, 6);
6141
6142 APP_BYTE(msg, 0x81);
6143 APP_16BIT(msg, ie->vpi);
6144
6145 if(ie->h.present & UNI_CALLING_SOFT_VCI_P) {
6146 APP_BYTE(msg, 0x82);
6147 APP_16BIT(msg, ie->vci);
6148 }
6149
6150 SET_IE_LEN(msg);
6151 return 0;
6152}
6153
6154DEF_IE_ENCODE(net, called_soft)
6155{
6156 START_IE(called_soft, UNI_IE_CALLED_SOFT, 7);
6157
6158 APP_BYTE(msg, ie->sel);
6159
6160 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6161 APP_BYTE(msg, 0x81);
6162 APP_16BIT(msg, ie->vpi);
6163 }
6164
6165 if(ie->h.present & UNI_CALLED_SOFT_VCI_P) {
6166 APP_BYTE(msg, 0x82);
6167 APP_16BIT(msg, ie->vci);
6168 }
6169
6170 SET_IE_LEN(msg);
6171 return 0;
6172}
6173
6174DEF_IE_DECODE(net, calling_soft)
6175{
6176 int vci_seen, vpi_seen;
6177
6178 IE_START(;);
6179 if(ielen < 3)
6180 goto rej;
6181
6182 vci_seen = 0;
6183 vpi_seen = 0;
6184
6185 while(ielen) {
6186 switch(*msg->b_rptr++) {
6187
6188 case 0x81:
6189 if(!vpi_seen) {
6190 ie->vpi = *msg->b_rptr++ << 8;
6191 ie->vpi |= *msg->b_rptr++;
6192 } else {
6193 msg->b_rptr += 2;
6194 }
6195 ielen -= 3;
6196 break;
6197
6198 case 0x82:
6199 if(!vci_seen) {
6200 ie->vci = *msg->b_rptr++ << 8;
6201 ie->vci |= *msg->b_rptr++;
6202 } else {
6203 msg->b_rptr += 2;
6204 }
6205 ie->h.present |= UNI_CALLING_SOFT_VCI_P;
6206 ielen -= 3;
6207 break;
6208
6209 default:
6210 goto rej;
6211 }
6212 }
6213
6214 if(!vpi_seen)
6215 goto rej;
6216
6217 IE_END(CALLING_SOFT);
6218}
6219
6220DEF_IE_DECODE(net, called_soft)
6221{
6222 int vci_seen, vpi_seen;
6223
6224 IE_START(;);
6225 if(ielen < 3)
6226 goto rej;
6227
6228 vci_seen = 0;
6229 vpi_seen = 0;
6230
6231 while(ielen) {
6232 switch(*msg->b_rptr++) {
6233
6234 case 0x81:
6235 if(!vpi_seen) {
6236 ie->vpi = *msg->b_rptr++ << 8;
6237 ie->vpi |= *msg->b_rptr++;
6238 vpi_seen = 1;
6238 } else {
6239 msg->b_rptr += 2;
6240 }
6241 ielen -= 3;
6242 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6243 break;
6244
6245 case 0x82:
6246 if(!vci_seen) {
6247 ie->vci = *msg->b_rptr++ << 8;
6248 ie->vci |= *msg->b_rptr++;
6239 } else {
6240 msg->b_rptr += 2;
6241 }
6242 ielen -= 3;
6243 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6244 break;
6245
6246 case 0x82:
6247 if(!vci_seen) {
6248 ie->vci = *msg->b_rptr++ << 8;
6249 ie->vci |= *msg->b_rptr++;
6250 vci_seen = 1;
6249 } else {
6250 msg->b_rptr += 2;
6251 }
6252 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6253 ielen -= 3;
6254 break;
6255
6256 default:
6257 goto rej;
6258 }
6259 }
6260
6261 IE_END(CALLED_SOFT);
6262}
6263
6264/*********************************************************************
6265 *
6266 * Crankback
6267 *
6268 * References for this IE are:
6269 *
6270 * PNNI1.0 pp. 203...206
6271 *
6272 * Only NET coding allowed.
6273 */
6274
6275DEF_IE_PRINT(net, crankback)
6276{
6277 u_int j;
6278
6279 if(uni_print_iehdr("crankback", &ie->h, cx))
6280 return;
6281
6282 uni_print_entry(cx, "level", "%d", ie->level);
6283
6284 switch(ie->type) {
6285
6286 case UNI_CRANKBACK_IF:
6287 uni_print_entry(cx, "type", "interface");
6288 break;
6289
6290 case UNI_CRANKBACK_NODE:
6291 uni_print_entry(cx, "type", "node");
6292 uni_print_entry(cx, "node", "{%d/", ie->id.node.level);
6293 for(j = 0; j < 21; j++)
6294 uni_printf(cx, "%02x", ie->id.node.id[j]);
6295 uni_printf(cx, "}");
6296 uni_print_eol(cx);
6297 break;
6298
6299 case UNI_CRANKBACK_LINK:
6300 uni_print_entry(cx, "type", "link");
6301 uni_print_push_prefix("link", cx);
6302 cx->indent++;
6303
6304 uni_print_entry(cx, "prec", "{%d/", ie->id.link.plevel);
6305 for(j = 0; j < 21; j++)
6306 uni_printf(cx, "%02x", ie->id.link.pid[j]);
6307 uni_printf(cx, "}");
6308 uni_print_eol(cx);
6309
6310 uni_print_entry(cx, "port", "0x%04x", ie->id.link.port);
6311 uni_print_eol(cx);
6312
6313 uni_print_entry(cx, "succ", "{%d/", ie->id.link.slevel);
6314 for(j = 0; j < 21; j++)
6315 uni_printf(cx, "%02x", ie->id.link.sid[j]);
6316 uni_printf(cx, "}");
6317 uni_print_eol(cx);
6318
6319 cx->indent--;
6320 uni_print_pop_prefix(cx);
6321 break;
6322
6323 default:
6324 uni_print_entry(cx, "type", "0x%02x", ie->type);
6325 break;
6326 }
6327
6328 uni_print_entry(cx, "cause", "0x%02x", ie->cause);
6329
6330 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6331 uni_print_push_prefix("topol", cx);
6332 uni_print_entry(cx, "dir", "%d", ie->diag.top.dir);
6333 uni_print_entry(cx, "port", "0x%04x", ie->diag.top.port);
6334 uni_print_entry(cx, "avcr", "%u", ie->diag.top.avcr);
6335 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6336 uni_print_entry(cx, "crm", "%u", ie->diag.top.crm);
6337 uni_print_entry(cx, "vf", "%u", ie->diag.top.vf);
6338 }
6339 uni_print_pop_prefix(cx);
6340 uni_print_eol(cx);
6341 }
6342 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6343 uni_print_push_prefix("qos", cx);
6344 uni_print_entry(cx, "ctd", "%savail", ie->diag.qos.ctd ? "" : "un");
6345 uni_print_entry(cx, "cdv", "%savail", ie->diag.qos.cdv ? "" : "un");
6346 uni_print_entry(cx, "clr", "%savail", ie->diag.qos.clr ? "" : "un");
6347 uni_print_entry(cx, "other", "%savail", ie->diag.qos.other ? "" : "un");
6348 uni_print_pop_prefix(cx);
6349 uni_print_eol(cx);
6350 }
6351
6352 uni_print_eol(cx);
6353 uni_print_ieend(cx);
6354}
6355
6356DEF_IE_CHECK(net, crankback)
6357{
6358 cx = cx;
6359
6360 if(ie->level > 104)
6361 return -1;
6362 switch(ie->type) {
6363 case UNI_CRANKBACK_IF:
6364 break;
6365 case UNI_CRANKBACK_NODE:
6366 if(ie->id.node.level > 104)
6367 return -1;
6368 break;
6369
6370 case UNI_CRANKBACK_LINK:
6371 if(ie->id.link.plevel > 104)
6372 return -1;
6373 if(ie->id.link.slevel > 104)
6374 return -1;
6375 break;
6376
6377 default:
6378 return -1;
6379 }
6380
6381 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6382 if(ie->h.present & UNI_CRANKBACK_QOS_P)
6383 return -1;
6384
6385 if(ie->cause != UNI_CAUSE_CRATE_NAVL)
6386 return -1;
6387 switch(ie->diag.top.dir) {
6388
6389 case 0x00:
6390 case 0x01:
6391 break;
6392
6393 default:
6394 return -1;
6395 }
6396 }
6397 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6398 if(ie->cause != UNI_CAUSE_QOS_NAVL)
6399 return -1;
6400 }
6401 return 0;
6402}
6403
6404DEF_IE_ENCODE(net, crankback)
6405{
6406 START_IE(crankback, UNI_IE_CRANKBACK, 72);
6407
6408 APP_BYTE(msg, ie->level);
6409 APP_BYTE(msg, ie->type);
6410
6411 switch(ie->type) {
6412
6413 case UNI_CRANKBACK_IF:
6414 break;
6415
6416 case UNI_CRANKBACK_NODE:
6417 APP_BYTE(msg, ie->id.node.level);
6418 APP_BUF(msg, ie->id.node.id, 21);
6419 break;
6420
6421 case UNI_CRANKBACK_LINK:
6422 APP_BYTE(msg, ie->id.link.plevel);
6423 APP_BUF(msg, ie->id.link.pid, 21);
6424 APP_32BIT(msg, ie->id.link.port);
6425 APP_BYTE(msg, ie->id.link.slevel);
6426 APP_BUF(msg, ie->id.link.sid, 21);
6427 break;
6428 }
6429
6430 APP_BYTE(msg, ie->cause);
6431
6432 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6433 APP_BYTE(msg, ie->diag.top.dir);
6434 APP_32BIT(msg, ie->diag.top.port);
6435 APP_32BIT(msg, ie->diag.top.avcr);
6436 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6437 APP_32BIT(msg, ie->diag.top.crm);
6438 APP_32BIT(msg, ie->diag.top.vf);
6439 }
6440 }
6441
6442 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6443 APP_BYTE(msg, (ie->diag.qos.ctd << 3)
6444 |(ie->diag.qos.cdv << 2)
6445 |(ie->diag.qos.clr << 1)
6446 |(ie->diag.qos.other));
6447 }
6448 SET_IE_LEN(msg);
6449 return 0;
6450}
6451
6452
6453DEF_IE_DECODE(net, crankback)
6454{
6455 IE_START(;);
6456
6457 if(ielen < 3)
6458 goto rej;
6459
6460 ie->level = *msg->b_rptr++;
6461 ielen--;
6462
6463 ie->type = *msg->b_rptr++;
6464 ielen--;
6465
6466 switch(ie->type) {
6467
6468 default:
6469 goto rej;
6470
6471 case UNI_CRANKBACK_IF:
6472 break;
6473
6474 case UNI_CRANKBACK_NODE:
6475 if(ielen < 22)
6476 goto rej;
6477 ie->id.node.level = *msg->b_rptr++;
6478 (void)memcpy(ie->id.node.id, msg->b_rptr, 21);
6479 msg->b_rptr += 21;
6480 ielen -= 22;
6481 break;
6482
6483 case UNI_CRANKBACK_LINK:
6484 if(ielen < 48)
6485 goto rej;
6486 ie->id.link.plevel = *msg->b_rptr++;
6487 (void)memcpy(ie->id.link.pid, msg->b_rptr, 21);
6488 msg->b_rptr += 21;
6489 ielen -= 22;
6490
6491 ie->id.link.port = *msg->b_rptr++ << 24;
6492 ie->id.link.port |= *msg->b_rptr++ << 16;
6493 ie->id.link.port |= *msg->b_rptr++ << 8;
6494 ie->id.link.port |= *msg->b_rptr++ << 0;
6495 ielen -= 4;
6496
6497 ie->id.link.slevel = *msg->b_rptr++;
6498 (void)memcpy(ie->id.link.sid, msg->b_rptr, 21);
6499 msg->b_rptr += 21;
6500 ielen -= 22;
6501
6502 break;
6503 }
6504
6505 if(ielen < 1)
6506 goto rej;
6507 ie->cause = *msg->b_rptr++;
6508 ielen--;
6509
6510 if(ie->cause == UNI_CAUSE_CRATE_NAVL) {
6511 if(ielen > 0) {
6512 if(ielen != 9 && ielen != 17)
6513 goto rej;
6514 ie->diag.top.dir = *msg->b_rptr++;
6515 ie->diag.top.port = *msg->b_rptr++ << 24;
6516 ie->diag.top.port |= *msg->b_rptr++ << 16;
6517 ie->diag.top.port |= *msg->b_rptr++ << 8;
6518 ie->diag.top.port |= *msg->b_rptr++ << 0;
6519 ie->diag.top.avcr = *msg->b_rptr++ << 24;
6520 ie->diag.top.avcr |= *msg->b_rptr++ << 16;
6521 ie->diag.top.avcr |= *msg->b_rptr++ << 8;
6522 ie->diag.top.avcr |= *msg->b_rptr++ << 0;
6523 ielen -= 9;
6524 ie->h.present |= UNI_CRANKBACK_TOP_P;
6525 if(ielen > 0) {
6526 ie->diag.top.crm = *msg->b_rptr++ << 24;
6527 ie->diag.top.crm |= *msg->b_rptr++ << 16;
6528 ie->diag.top.crm |= *msg->b_rptr++ << 8;
6529 ie->diag.top.crm |= *msg->b_rptr++ << 0;
6530 ie->diag.top.vf = *msg->b_rptr++ << 24;
6531 ie->diag.top.vf |= *msg->b_rptr++ << 16;
6532 ie->diag.top.vf |= *msg->b_rptr++ << 8;
6533 ie->diag.top.vf |= *msg->b_rptr++ << 0;
6534 ie->h.present |= UNI_CRANKBACK_TOPX_P;
6535 ielen -= 8;
6536 }
6537 }
6538 } else if(ie->cause == UNI_CAUSE_QOS_NAVL) {
6539 if(ielen > 0) {
6540 if(ielen != 1)
6541 goto rej;
6542 ie->diag.qos.ctd = *msg->b_rptr >> 3;
6543 ie->diag.qos.cdv = *msg->b_rptr >> 2;
6544 ie->diag.qos.clr = *msg->b_rptr >> 1;
6545 ie->diag.qos.other = *msg->b_rptr >> 0;
6546 ie->h.present |= UNI_CRANKBACK_QOS_P;
6547 ielen -= 1;
6548 }
6549 } else {
6550 if(ielen > 0)
6551 goto rej;
6552 }
6553
6554 IE_END(CRANKBACK);
6555}
6556
6557/*********************************************************************
6558 *
6559 * Designated transit list
6560 *
6561 * References for this IE are:
6562 *
6563 * PNNI1.0 pp. 206...208
6564 *
6565 * Only NET coding allowed.
6566 */
6567DEF_IE_PRINT(net, dtl)
6568{
6569 u_int i, j;
6570 char buf[10];
6571
6572 if(uni_print_iehdr("dtl", &ie->h, cx))
6573 return;
6574
6575 uni_print_entry(cx, "ptr", "%d(%d)", ie->ptr, ie->ptr / UNI_DTL_LOGNP_SIZE);
6576 uni_print_push_prefix("dtl", cx);
6577 cx->indent++;
6578 uni_printf(cx, "{");
6579 for(i = 0; i < ie->num; i++) {
6580 sprintf(buf, "%d", i);
6581 uni_print_entry(cx, buf, "{%d/", ie->dtl[i].node_level);
6582 for(j = 0; j < 21; j++)
6583 uni_printf(cx, "%02x", ie->dtl[i].node_id[j]);
6584 uni_printf(cx, ",%04x}", ie->dtl[i].port_id);
6585 uni_print_eol(cx);
6586 }
6587 cx->indent--;
6588 uni_print_pop_prefix(cx);
6589 uni_print_ieend(cx);
6590}
6591
6592DEF_IE_CHECK(net, dtl)
6593{
6594 u_int i;
6595
6596 cx = cx;
6597
6598 if(ie->ptr % UNI_DTL_LOGNP_SIZE != 0)
6599 return -1;
6600 if(ie->ptr / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6601 return -1;
6602 if(ie->num > UNI_DTL_MAXNUM)
6603 return -1;
6604 for(i = 0; i < ie->num; i++)
6605 if(ie->dtl[i].node_level > 104)
6606 return -1;
6607 return 0;
6608}
6609
6610DEF_IE_ENCODE(net, dtl)
6611{
6612 u_int i;
6613
6614 START_IE(dtl, UNI_IE_DTL, 2 + UNI_DTL_LOGNP_SIZE * ie->num);
6615
6616 APP_16BIT(msg, ie->ptr);
6617
6618 for(i = 0; i < ie->num; i++) {
6619 APP_BYTE(msg, UNI_DTL_LOGNP);
6620 APP_BYTE(msg, ie->dtl[i].node_level);
6621 APP_BUF(msg, ie->dtl[i].node_id, 21);
6622 APP_32BIT(msg, ie->dtl[i].port_id);
6623 }
6624
6625 SET_IE_LEN(msg);
6626 return 0;
6627}
6628
6629
6630DEF_IE_DECODE(net, dtl)
6631{
6632 IE_START(;);
6633
6634 if(ielen < 2)
6635 goto rej;
6636
6637 ie->ptr = *msg->b_rptr++ << 8;
6638 ie->ptr |= *msg->b_rptr++;
6639 ielen -= 2;
6640
6641 if(ielen % UNI_DTL_LOGNP_SIZE != 0)
6642 goto rej;
6643 if(ielen / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6644 goto rej;
6645
6646 ie->num = 0;
6647 while(ielen) {
6648 if(*msg->b_rptr++ != UNI_DTL_LOGNP)
6649 goto rej;
6650 ielen--;
6651
6652 ie->dtl[ie->num].node_level = *msg->b_rptr++;
6653 ielen--;
6654
6655 (void)memcpy(ie->dtl[ie->num].node_id, msg->b_rptr, 21);
6656 msg->b_rptr += 21;
6657 ielen -= 21;
6658
6659 ie->dtl[ie->num].port_id = *msg->b_rptr++ << 24;
6660 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 16;
6661 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 8;
6662 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 0;
6663 ielen -= 4;
6664
6665 ie->num++;
6666 }
6667
6668 IE_END(DTL);
6669}
6670
6671/*********************************************************************
6672 *
6673 * Leaf initiated join call identifier.
6674 * Leaf initiated join parameters.
6675 * Leaf initiated join sequence number.
6676 *
6677 * References for this IE are:
6678 *
6679 * UNI4.0 pp. 46...48
6680 *
6681 * Only NET coding allowed.
6682 */
6683
6684/**********************************************************************/
6685
6686DEF_IE_PRINT(net, lij_callid)
6687{
6688 static const struct uni_print_tbl type_tbl[] = {
6689 MKT(UNI_LIJ_IDTYPE_ROOT, root),
6690 EOT()
6691 };
6692
6693 if(uni_print_iehdr("lij_callid", &ie->h, cx))
6694 return;
6695
6696 uni_print_tbl("type", ie->type, type_tbl, cx);
6697 uni_print_entry(cx, "id", "0x%x", ie->callid);
6698
6699 uni_print_ieend(cx);
6700}
6701
6702DEF_IE_CHECK(net, lij_callid)
6703{
6704 cx = cx;
6705
6706 switch(ie->type) {
6707
6708 case UNI_LIJ_IDTYPE_ROOT:
6709 break;
6710
6711 default:
6712 return -1;
6713 }
6714
6715 return 0;
6716}
6717
6718DEF_IE_ENCODE(net, lij_callid)
6719{
6720 START_IE(lij_callid, UNI_IE_LIJ_CALLID, 5);
6721
6722 APP_BYTE(msg, 0x80 | ie->type);
6723 APP_32BIT(msg, ie->callid);
6724
6725 SET_IE_LEN(msg);
6726 return 0;
6727}
6728
6729DEF_IE_DECODE(net, lij_callid)
6730{
6731 IE_START(;);
6732
6733 if(ielen != 5)
6734 goto rej;
6735
6736 ie->type = *msg->b_rptr++ & 0xf;
6737 ie->callid = *msg->b_rptr++ << 24;
6738 ie->callid |= *msg->b_rptr++ << 16;
6739 ie->callid |= *msg->b_rptr++ << 8;
6740 ie->callid |= *msg->b_rptr++ << 0;
6741
6742 IE_END(LIJ_CALLID);
6743}
6744
6745/**********************************************************************/
6746
6747DEF_IE_PRINT(net, lij_param)
6748{
6749 static const struct uni_print_tbl lscreen_tbl[] = {
6750 MKT(UNI_LIJ_SCREEN_NETJOIN, netjoin),
6751 EOT()
6752 };
6753
6754 if(uni_print_iehdr("lij_param", &ie->h, cx))
6755 return;
6756 uni_print_tbl("screen", ie->screen, lscreen_tbl, cx);
6757 uni_print_ieend(cx);
6758}
6759
6760DEF_IE_CHECK(net, lij_param)
6761{
6762 cx = cx;
6763
6764 switch(ie->screen) {
6765
6766 case UNI_LIJ_SCREEN_NETJOIN:
6767 break;
6768
6769 default:
6770 return -1;
6771 }
6772
6773 return 0;
6774}
6775
6776DEF_IE_ENCODE(net, lij_param)
6777{
6778 START_IE(lij_param, UNI_IE_LIJ_PARAM, 1);
6779
6780 APP_BYTE(msg, 0x80 | ie->screen);
6781
6782 SET_IE_LEN(msg);
6783 return 0;
6784}
6785
6786DEF_IE_DECODE(net, lij_param)
6787{
6788 IE_START(;);
6789
6790 if(ielen != 1)
6791 goto rej;
6792
6793 ie->screen = *msg->b_rptr++ & 0xf;
6794
6795 IE_END(LIJ_PARAM);
6796}
6797
6798/**********************************************************************/
6799
6800DEF_IE_PRINT(net, lij_seqno)
6801{
6802 if(uni_print_iehdr("lij_seqno", &ie->h, cx))
6803 return;
6804 uni_print_entry(cx, "seqno", "0x%x", ie->seqno);
6805 uni_print_ieend(cx);
6806}
6807
6808DEF_IE_CHECK(net, lij_seqno)
6809{
6810 cx = cx; ie = ie;
6811
6812 return 0;
6813}
6814
6815DEF_IE_ENCODE(net, lij_seqno)
6816{
6817 START_IE(lij_seqno, UNI_IE_LIJ_SEQNO, 4);
6818
6819 APP_32BIT(msg, ie->seqno);
6820
6821 SET_IE_LEN(msg);
6822 return 0;
6823}
6824
6825DEF_IE_DECODE(net, lij_seqno)
6826{
6827 IE_START(;);
6828
6829 if(ielen != 4)
6830 goto rej;
6831
6832 ie->seqno = *msg->b_rptr++ << 24;
6833 ie->seqno |= *msg->b_rptr++ << 16;
6834 ie->seqno |= *msg->b_rptr++ << 8;
6835 ie->seqno |= *msg->b_rptr++ << 0;
6836
6837 IE_END(LIJ_SEQNO);
6838}
6839
6840/*********************************************************************
6841 *
6842 * Connection scope
6843 *
6844 * References for this IE are:
6845 *
6846 * UNI4.0 pp. 57...58
6847 *
6848 * Only NET coding allowed.
6849 */
6850DEF_IE_PRINT(net, cscope)
6851{
6852 static const struct uni_print_tbl type_tbl[] = {
6853 MKT(UNI_CSCOPE_ORG, org),
6854 EOT()
6855 };
6856 static const struct uni_print_tbl scope_tbl[] = {
6857 MKT(UNI_CSCOPE_ORG_LOC, local_network),
6858 MKT(UNI_CSCOPE_ORG_LOC_P1, local_network_plus_one),
6859 MKT(UNI_CSCOPE_ORG_LOC_P2, local_network_plus_two),
6860 MKT(UNI_CSCOPE_ORG_SITE_M1, site_minus_one),
6861 MKT(UNI_CSCOPE_ORG_SITE, intra_site),
6862 MKT(UNI_CSCOPE_ORG_SITE_P1, site_plus_one),
6863 MKT(UNI_CSCOPE_ORG_ORG_M1, organisation_minus_one),
6864 MKT(UNI_CSCOPE_ORG_ORG, intra_organisation),
6865 MKT(UNI_CSCOPE_ORG_ORG_P1, organisation_plus_one),
6866 MKT(UNI_CSCOPE_ORG_COMM_M1, community_minus_one),
6867 MKT(UNI_CSCOPE_ORG_COMM, intra_community),
6868 MKT(UNI_CSCOPE_ORG_COMM_P1, community_plus_one),
6869 MKT(UNI_CSCOPE_ORG_REG, regional),
6870 MKT(UNI_CSCOPE_ORG_INTER, inter_regional),
6871 MKT(UNI_CSCOPE_ORG_GLOBAL, global),
6872 EOT()
6873 };
6874
6875 if(uni_print_iehdr("cscope", &ie->h, cx))
6876 return;
6877
6878 uni_print_tbl("type", ie->type, type_tbl, cx);
6879 if(ie->type == UNI_CSCOPE_ORG)
6880 uni_print_tbl("scope", (u_int)ie->scope, scope_tbl, cx);
6881 else
6882 uni_print_entry(cx, "scope", "0x%02x", ie->scope);
6883
6884 uni_print_ieend(cx);
6885}
6886
6887DEF_IE_CHECK(net, cscope)
6888{
6889 cx = cx;
6890
6891 switch(ie->type) {
6892
6893 default:
6894 return -1;
6895
6896 case UNI_CSCOPE_ORG:
6897 switch(ie->scope) {
6898
6899 default:
6900 return -1;
6901
6902 case UNI_CSCOPE_ORG_LOC:
6903 case UNI_CSCOPE_ORG_LOC_P1:
6904 case UNI_CSCOPE_ORG_LOC_P2:
6905 case UNI_CSCOPE_ORG_SITE_M1:
6906 case UNI_CSCOPE_ORG_SITE:
6907 case UNI_CSCOPE_ORG_SITE_P1:
6908 case UNI_CSCOPE_ORG_ORG_M1:
6909 case UNI_CSCOPE_ORG_ORG:
6910 case UNI_CSCOPE_ORG_ORG_P1:
6911 case UNI_CSCOPE_ORG_COMM_M1:
6912 case UNI_CSCOPE_ORG_COMM:
6913 case UNI_CSCOPE_ORG_COMM_P1:
6914 case UNI_CSCOPE_ORG_REG:
6915 case UNI_CSCOPE_ORG_INTER:
6916 case UNI_CSCOPE_ORG_GLOBAL:
6917 break;
6918 }
6919 break;
6920 }
6921 return 0;
6922}
6923
6924DEF_IE_ENCODE(net, cscope)
6925{
6926 START_IE(cscope, UNI_IE_CSCOPE, 2);
6927
6928 APP_BYTE(msg, ie->type | 0x80);
6929 APP_BYTE(msg, ie->scope);
6930
6931 SET_IE_LEN(msg);
6932 return 0;
6933}
6934
6935DEF_IE_DECODE(net, cscope)
6936{
6937 IE_START(;);
6938 if(ielen != 2)
6939 goto rej;
6940
6941 if((*msg->b_rptr & 0xf0) != 0x80)
6942 goto rej;
6943
6944 ie->type = *msg->b_rptr++ & 0xf;
6945 ie->scope = *msg->b_rptr++;
6946
6947 IE_END(CSCOPE);
6948}
6949
6950/*********************************************************************
6951 *
6952 * Extended Quality of Service
6953 *
6954 * References for this IE are:
6955 *
6956 * UNI4.0 pp. 70...72
6957 *
6958 * Notes:
6959 * Only NET coding.
6960 */
6961DEF_IE_PRINT(net, exqos)
6962{
6963 static const struct uni_print_tbl tab[] = {
6964 MKT(UNI_EXQOS_USER, user),
6965 MKT(UNI_EXQOS_NET, net),
6966 EOT()
6967 };
6968
6969 if(uni_print_iehdr("exqos", &ie->h, cx))
6970 return;
6971
6972 uni_print_tbl("origin", ie->origin, tab, cx);
6973
6974 uni_print_entry(cx, "acceptable", "(");
6975 if(ie->h.present & UNI_EXQOS_FACC_P) {
6976 if(ie->facc == UNI_EXQOS_ANY_CDV)
6977 uni_printf(cx, "ANY");
6978 else
6979 uni_printf(cx, "%d", ie->facc);
6980 }
6981 uni_putc(',', cx);
6982 if(ie->h.present & UNI_EXQOS_BACC_P) {
6983 if(ie->bacc == UNI_EXQOS_ANY_CDV)
6984 uni_printf(cx, "ANY");
6985 else
6986 uni_printf(cx, "%d", ie->bacc);
6987 }
6988 uni_putc(')', cx);
6989
6990 uni_print_entry(cx, "cumulative", "(");
6991 if(ie->h.present & UNI_EXQOS_FCUM_P)
6992 uni_printf(cx, "%d", ie->fcum);
6993 uni_putc(',', cx);
6994 if(ie->h.present & UNI_EXQOS_BCUM_P)
6995 uni_printf(cx, "%d", ie->bcum);
6996 uni_putc(')', cx);
6997
6998 uni_print_entry(cx, "clrid", "(");
6999 if(ie->h.present & UNI_EXQOS_FCLR_P) {
7000 if(ie->fclr == UNI_EXQOS_ANY_CLR)
7001 uni_printf(cx, "ANY");
7002 else
7003 uni_printf(cx, "%d", ie->fclr);
7004 }
7005 uni_putc(',', cx);
7006 if(ie->h.present & UNI_EXQOS_BCLR_P) {
7007 if(ie->bclr == UNI_EXQOS_ANY_CLR)
7008 uni_printf(cx, "ANY");
7009 else
7010 uni_printf(cx, "%d", ie->bclr);
7011 }
7012 uni_putc(')', cx);
7013
7014 uni_print_ieend(cx);
7015}
7016
7017DEF_IE_CHECK(net, exqos)
7018{
7019 cx = cx;
7020
7021 switch(ie->origin) {
7022 case UNI_EXQOS_USER:
7023 case UNI_EXQOS_NET:
7024 break;
7025
7026 default:
7027 return -1;
7028 }
7029 if(ie->h.present & UNI_EXQOS_FACC_P)
7030 if(!(ie->h.present & UNI_EXQOS_FCUM_P))
7031 return -1;
7032 if(ie->h.present & UNI_EXQOS_BACC_P)
7033 if(!(ie->h.present & UNI_EXQOS_BCUM_P))
7034 return -1;
7035
7036 if(ie->h.present & UNI_EXQOS_FACC_P)
7037 if(ie->facc >= 1 << 24)
7038 return -1;
7039 if(ie->h.present & UNI_EXQOS_BACC_P)
7040 if(ie->bacc >= 1 << 24)
7041 return -1;
7042 if(ie->h.present & UNI_EXQOS_FCUM_P)
7043 if(ie->fcum >= 1 << 24)
7044 return -1;
7045 if(ie->h.present & UNI_EXQOS_BCUM_P)
7046 if(ie->bcum >= 1 << 24)
7047 return -1;
7048
7049 if(ie->h.present & UNI_EXQOS_FCLR_P)
7050 if(ie->fclr==0 || (ie->fclr>15 && ie->fclr!=UNI_EXQOS_ANY_CLR))
7051 return -1;
7052 if(ie->h.present & UNI_EXQOS_BCLR_P)
7053 if(ie->bclr==0 || (ie->bclr>15 && ie->bclr!=UNI_EXQOS_ANY_CLR))
7054 return -1;
7055 return 0;
7056}
7057
7058DEF_IE_ENCODE(net, exqos)
7059{
7060 START_IE(exqos, UNI_IE_EXQOS, 21);
7061
7062 APP_BYTE(msg, ie->origin);
7063
7064 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FACC_P,
7065 UNI_EXQOS_FACC_ID, ie->facc);
7066 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BACC_P,
7067 UNI_EXQOS_BACC_ID, ie->bacc);
7068 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FCUM_P,
7069 UNI_EXQOS_FCUM_ID, ie->fcum);
7070 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BCUM_P,
7071 UNI_EXQOS_BCUM_ID, ie->bcum);
7072
7073 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_FCLR_P,
7074 UNI_EXQOS_FCLR_ID, ie->fclr);
7075 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_BCLR_P,
7076 UNI_EXQOS_BCLR_ID, ie->bclr);
7077
7078 SET_IE_LEN(msg);
7079 return 0;
7080}
7081
7082DEF_IE_DECODE(net, exqos)
7083{
7084 IE_START(;);
7085
7086 if(ielen < 1 || ielen > 21)
7087 goto rej;
7088
7089 ie->origin = *msg->b_rptr++;
7090 ielen--;
7091
7092 while(ielen--) {
7093 switch(*msg->b_rptr++) {
7094
7095 default:
7096 goto rej;
7097
7098 DEC_GETF3(EXQOS_FACC, facc, ie->h.present);
7099 DEC_GETF3(EXQOS_BACC, bacc, ie->h.present);
7100 DEC_GETF3(EXQOS_FCUM, fcum, ie->h.present);
7101 DEC_GETF3(EXQOS_BCUM, bcum, ie->h.present);
7102
7103 DEC_GETF1(EXQOS_FCLR, fclr, ie->h.present);
7104 DEC_GETF1(EXQOS_BCLR, bclr, ie->h.present);
7105
7106 }
7107 }
7108 IE_END(EXQOS);
7109}
7110
7111/**************************************************************
7112 *
7113 * Free form IE (for testing mainly)
7114 */
7115DEF_IE_PRINT(itu, unrec)
7116{
7117 u_int i;
7118
7119 if (uni_print_iehdr("unrec", &ie->h, cx))
7120 return;
7121 uni_print_entry(cx, "len", "%u", ie->len);
7122 uni_print_entry(cx, "data", "(");
7123 for (i = 0; i < ie->len; i++)
7124 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->data[i]);
7125 uni_printf(cx, ")");
7126 uni_print_ieend(cx);
7127}
7128
7129DEF_IE_CHECK(itu, unrec)
7130{
7131 cx = cx;
7132
7133 if (ie->len > sizeof(ie->data))
7134 return (-1);
7135
7136 return (0);
7137}
7138
7139DEF_IE_ENCODE(itu, unrec)
7140{
7141 START_IE2(unrec, UNI_IE_UNREC, ie->len, ie->id);
7142
7143 APP_BUF(msg, ie->data, ie->len);
7144
7145 SET_IE_LEN(msg);
7146 return (0);
7147}
7148
7149DEF_IE_DECODE(itu, unrec)
7150{
7151 IE_START(;);
7152
7153 if (ielen > sizeof(ie->data) / sizeof(ie->data[0]) || ielen < 1)
7154 goto rej;
7155
7156 ie->len = ielen;
7157 ielen = 0;
7158 (void)memcpy(ie->data, msg->b_rptr, ie->len);
7159 msg->b_rptr += ie->len;
7160
7161 IE_END(UNREC);
7162}
6251 } else {
6252 msg->b_rptr += 2;
6253 }
6254 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6255 ielen -= 3;
6256 break;
6257
6258 default:
6259 goto rej;
6260 }
6261 }
6262
6263 IE_END(CALLED_SOFT);
6264}
6265
6266/*********************************************************************
6267 *
6268 * Crankback
6269 *
6270 * References for this IE are:
6271 *
6272 * PNNI1.0 pp. 203...206
6273 *
6274 * Only NET coding allowed.
6275 */
6276
6277DEF_IE_PRINT(net, crankback)
6278{
6279 u_int j;
6280
6281 if(uni_print_iehdr("crankback", &ie->h, cx))
6282 return;
6283
6284 uni_print_entry(cx, "level", "%d", ie->level);
6285
6286 switch(ie->type) {
6287
6288 case UNI_CRANKBACK_IF:
6289 uni_print_entry(cx, "type", "interface");
6290 break;
6291
6292 case UNI_CRANKBACK_NODE:
6293 uni_print_entry(cx, "type", "node");
6294 uni_print_entry(cx, "node", "{%d/", ie->id.node.level);
6295 for(j = 0; j < 21; j++)
6296 uni_printf(cx, "%02x", ie->id.node.id[j]);
6297 uni_printf(cx, "}");
6298 uni_print_eol(cx);
6299 break;
6300
6301 case UNI_CRANKBACK_LINK:
6302 uni_print_entry(cx, "type", "link");
6303 uni_print_push_prefix("link", cx);
6304 cx->indent++;
6305
6306 uni_print_entry(cx, "prec", "{%d/", ie->id.link.plevel);
6307 for(j = 0; j < 21; j++)
6308 uni_printf(cx, "%02x", ie->id.link.pid[j]);
6309 uni_printf(cx, "}");
6310 uni_print_eol(cx);
6311
6312 uni_print_entry(cx, "port", "0x%04x", ie->id.link.port);
6313 uni_print_eol(cx);
6314
6315 uni_print_entry(cx, "succ", "{%d/", ie->id.link.slevel);
6316 for(j = 0; j < 21; j++)
6317 uni_printf(cx, "%02x", ie->id.link.sid[j]);
6318 uni_printf(cx, "}");
6319 uni_print_eol(cx);
6320
6321 cx->indent--;
6322 uni_print_pop_prefix(cx);
6323 break;
6324
6325 default:
6326 uni_print_entry(cx, "type", "0x%02x", ie->type);
6327 break;
6328 }
6329
6330 uni_print_entry(cx, "cause", "0x%02x", ie->cause);
6331
6332 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6333 uni_print_push_prefix("topol", cx);
6334 uni_print_entry(cx, "dir", "%d", ie->diag.top.dir);
6335 uni_print_entry(cx, "port", "0x%04x", ie->diag.top.port);
6336 uni_print_entry(cx, "avcr", "%u", ie->diag.top.avcr);
6337 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6338 uni_print_entry(cx, "crm", "%u", ie->diag.top.crm);
6339 uni_print_entry(cx, "vf", "%u", ie->diag.top.vf);
6340 }
6341 uni_print_pop_prefix(cx);
6342 uni_print_eol(cx);
6343 }
6344 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6345 uni_print_push_prefix("qos", cx);
6346 uni_print_entry(cx, "ctd", "%savail", ie->diag.qos.ctd ? "" : "un");
6347 uni_print_entry(cx, "cdv", "%savail", ie->diag.qos.cdv ? "" : "un");
6348 uni_print_entry(cx, "clr", "%savail", ie->diag.qos.clr ? "" : "un");
6349 uni_print_entry(cx, "other", "%savail", ie->diag.qos.other ? "" : "un");
6350 uni_print_pop_prefix(cx);
6351 uni_print_eol(cx);
6352 }
6353
6354 uni_print_eol(cx);
6355 uni_print_ieend(cx);
6356}
6357
6358DEF_IE_CHECK(net, crankback)
6359{
6360 cx = cx;
6361
6362 if(ie->level > 104)
6363 return -1;
6364 switch(ie->type) {
6365 case UNI_CRANKBACK_IF:
6366 break;
6367 case UNI_CRANKBACK_NODE:
6368 if(ie->id.node.level > 104)
6369 return -1;
6370 break;
6371
6372 case UNI_CRANKBACK_LINK:
6373 if(ie->id.link.plevel > 104)
6374 return -1;
6375 if(ie->id.link.slevel > 104)
6376 return -1;
6377 break;
6378
6379 default:
6380 return -1;
6381 }
6382
6383 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6384 if(ie->h.present & UNI_CRANKBACK_QOS_P)
6385 return -1;
6386
6387 if(ie->cause != UNI_CAUSE_CRATE_NAVL)
6388 return -1;
6389 switch(ie->diag.top.dir) {
6390
6391 case 0x00:
6392 case 0x01:
6393 break;
6394
6395 default:
6396 return -1;
6397 }
6398 }
6399 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6400 if(ie->cause != UNI_CAUSE_QOS_NAVL)
6401 return -1;
6402 }
6403 return 0;
6404}
6405
6406DEF_IE_ENCODE(net, crankback)
6407{
6408 START_IE(crankback, UNI_IE_CRANKBACK, 72);
6409
6410 APP_BYTE(msg, ie->level);
6411 APP_BYTE(msg, ie->type);
6412
6413 switch(ie->type) {
6414
6415 case UNI_CRANKBACK_IF:
6416 break;
6417
6418 case UNI_CRANKBACK_NODE:
6419 APP_BYTE(msg, ie->id.node.level);
6420 APP_BUF(msg, ie->id.node.id, 21);
6421 break;
6422
6423 case UNI_CRANKBACK_LINK:
6424 APP_BYTE(msg, ie->id.link.plevel);
6425 APP_BUF(msg, ie->id.link.pid, 21);
6426 APP_32BIT(msg, ie->id.link.port);
6427 APP_BYTE(msg, ie->id.link.slevel);
6428 APP_BUF(msg, ie->id.link.sid, 21);
6429 break;
6430 }
6431
6432 APP_BYTE(msg, ie->cause);
6433
6434 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6435 APP_BYTE(msg, ie->diag.top.dir);
6436 APP_32BIT(msg, ie->diag.top.port);
6437 APP_32BIT(msg, ie->diag.top.avcr);
6438 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6439 APP_32BIT(msg, ie->diag.top.crm);
6440 APP_32BIT(msg, ie->diag.top.vf);
6441 }
6442 }
6443
6444 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6445 APP_BYTE(msg, (ie->diag.qos.ctd << 3)
6446 |(ie->diag.qos.cdv << 2)
6447 |(ie->diag.qos.clr << 1)
6448 |(ie->diag.qos.other));
6449 }
6450 SET_IE_LEN(msg);
6451 return 0;
6452}
6453
6454
6455DEF_IE_DECODE(net, crankback)
6456{
6457 IE_START(;);
6458
6459 if(ielen < 3)
6460 goto rej;
6461
6462 ie->level = *msg->b_rptr++;
6463 ielen--;
6464
6465 ie->type = *msg->b_rptr++;
6466 ielen--;
6467
6468 switch(ie->type) {
6469
6470 default:
6471 goto rej;
6472
6473 case UNI_CRANKBACK_IF:
6474 break;
6475
6476 case UNI_CRANKBACK_NODE:
6477 if(ielen < 22)
6478 goto rej;
6479 ie->id.node.level = *msg->b_rptr++;
6480 (void)memcpy(ie->id.node.id, msg->b_rptr, 21);
6481 msg->b_rptr += 21;
6482 ielen -= 22;
6483 break;
6484
6485 case UNI_CRANKBACK_LINK:
6486 if(ielen < 48)
6487 goto rej;
6488 ie->id.link.plevel = *msg->b_rptr++;
6489 (void)memcpy(ie->id.link.pid, msg->b_rptr, 21);
6490 msg->b_rptr += 21;
6491 ielen -= 22;
6492
6493 ie->id.link.port = *msg->b_rptr++ << 24;
6494 ie->id.link.port |= *msg->b_rptr++ << 16;
6495 ie->id.link.port |= *msg->b_rptr++ << 8;
6496 ie->id.link.port |= *msg->b_rptr++ << 0;
6497 ielen -= 4;
6498
6499 ie->id.link.slevel = *msg->b_rptr++;
6500 (void)memcpy(ie->id.link.sid, msg->b_rptr, 21);
6501 msg->b_rptr += 21;
6502 ielen -= 22;
6503
6504 break;
6505 }
6506
6507 if(ielen < 1)
6508 goto rej;
6509 ie->cause = *msg->b_rptr++;
6510 ielen--;
6511
6512 if(ie->cause == UNI_CAUSE_CRATE_NAVL) {
6513 if(ielen > 0) {
6514 if(ielen != 9 && ielen != 17)
6515 goto rej;
6516 ie->diag.top.dir = *msg->b_rptr++;
6517 ie->diag.top.port = *msg->b_rptr++ << 24;
6518 ie->diag.top.port |= *msg->b_rptr++ << 16;
6519 ie->diag.top.port |= *msg->b_rptr++ << 8;
6520 ie->diag.top.port |= *msg->b_rptr++ << 0;
6521 ie->diag.top.avcr = *msg->b_rptr++ << 24;
6522 ie->diag.top.avcr |= *msg->b_rptr++ << 16;
6523 ie->diag.top.avcr |= *msg->b_rptr++ << 8;
6524 ie->diag.top.avcr |= *msg->b_rptr++ << 0;
6525 ielen -= 9;
6526 ie->h.present |= UNI_CRANKBACK_TOP_P;
6527 if(ielen > 0) {
6528 ie->diag.top.crm = *msg->b_rptr++ << 24;
6529 ie->diag.top.crm |= *msg->b_rptr++ << 16;
6530 ie->diag.top.crm |= *msg->b_rptr++ << 8;
6531 ie->diag.top.crm |= *msg->b_rptr++ << 0;
6532 ie->diag.top.vf = *msg->b_rptr++ << 24;
6533 ie->diag.top.vf |= *msg->b_rptr++ << 16;
6534 ie->diag.top.vf |= *msg->b_rptr++ << 8;
6535 ie->diag.top.vf |= *msg->b_rptr++ << 0;
6536 ie->h.present |= UNI_CRANKBACK_TOPX_P;
6537 ielen -= 8;
6538 }
6539 }
6540 } else if(ie->cause == UNI_CAUSE_QOS_NAVL) {
6541 if(ielen > 0) {
6542 if(ielen != 1)
6543 goto rej;
6544 ie->diag.qos.ctd = *msg->b_rptr >> 3;
6545 ie->diag.qos.cdv = *msg->b_rptr >> 2;
6546 ie->diag.qos.clr = *msg->b_rptr >> 1;
6547 ie->diag.qos.other = *msg->b_rptr >> 0;
6548 ie->h.present |= UNI_CRANKBACK_QOS_P;
6549 ielen -= 1;
6550 }
6551 } else {
6552 if(ielen > 0)
6553 goto rej;
6554 }
6555
6556 IE_END(CRANKBACK);
6557}
6558
6559/*********************************************************************
6560 *
6561 * Designated transit list
6562 *
6563 * References for this IE are:
6564 *
6565 * PNNI1.0 pp. 206...208
6566 *
6567 * Only NET coding allowed.
6568 */
6569DEF_IE_PRINT(net, dtl)
6570{
6571 u_int i, j;
6572 char buf[10];
6573
6574 if(uni_print_iehdr("dtl", &ie->h, cx))
6575 return;
6576
6577 uni_print_entry(cx, "ptr", "%d(%d)", ie->ptr, ie->ptr / UNI_DTL_LOGNP_SIZE);
6578 uni_print_push_prefix("dtl", cx);
6579 cx->indent++;
6580 uni_printf(cx, "{");
6581 for(i = 0; i < ie->num; i++) {
6582 sprintf(buf, "%d", i);
6583 uni_print_entry(cx, buf, "{%d/", ie->dtl[i].node_level);
6584 for(j = 0; j < 21; j++)
6585 uni_printf(cx, "%02x", ie->dtl[i].node_id[j]);
6586 uni_printf(cx, ",%04x}", ie->dtl[i].port_id);
6587 uni_print_eol(cx);
6588 }
6589 cx->indent--;
6590 uni_print_pop_prefix(cx);
6591 uni_print_ieend(cx);
6592}
6593
6594DEF_IE_CHECK(net, dtl)
6595{
6596 u_int i;
6597
6598 cx = cx;
6599
6600 if(ie->ptr % UNI_DTL_LOGNP_SIZE != 0)
6601 return -1;
6602 if(ie->ptr / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6603 return -1;
6604 if(ie->num > UNI_DTL_MAXNUM)
6605 return -1;
6606 for(i = 0; i < ie->num; i++)
6607 if(ie->dtl[i].node_level > 104)
6608 return -1;
6609 return 0;
6610}
6611
6612DEF_IE_ENCODE(net, dtl)
6613{
6614 u_int i;
6615
6616 START_IE(dtl, UNI_IE_DTL, 2 + UNI_DTL_LOGNP_SIZE * ie->num);
6617
6618 APP_16BIT(msg, ie->ptr);
6619
6620 for(i = 0; i < ie->num; i++) {
6621 APP_BYTE(msg, UNI_DTL_LOGNP);
6622 APP_BYTE(msg, ie->dtl[i].node_level);
6623 APP_BUF(msg, ie->dtl[i].node_id, 21);
6624 APP_32BIT(msg, ie->dtl[i].port_id);
6625 }
6626
6627 SET_IE_LEN(msg);
6628 return 0;
6629}
6630
6631
6632DEF_IE_DECODE(net, dtl)
6633{
6634 IE_START(;);
6635
6636 if(ielen < 2)
6637 goto rej;
6638
6639 ie->ptr = *msg->b_rptr++ << 8;
6640 ie->ptr |= *msg->b_rptr++;
6641 ielen -= 2;
6642
6643 if(ielen % UNI_DTL_LOGNP_SIZE != 0)
6644 goto rej;
6645 if(ielen / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6646 goto rej;
6647
6648 ie->num = 0;
6649 while(ielen) {
6650 if(*msg->b_rptr++ != UNI_DTL_LOGNP)
6651 goto rej;
6652 ielen--;
6653
6654 ie->dtl[ie->num].node_level = *msg->b_rptr++;
6655 ielen--;
6656
6657 (void)memcpy(ie->dtl[ie->num].node_id, msg->b_rptr, 21);
6658 msg->b_rptr += 21;
6659 ielen -= 21;
6660
6661 ie->dtl[ie->num].port_id = *msg->b_rptr++ << 24;
6662 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 16;
6663 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 8;
6664 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 0;
6665 ielen -= 4;
6666
6667 ie->num++;
6668 }
6669
6670 IE_END(DTL);
6671}
6672
6673/*********************************************************************
6674 *
6675 * Leaf initiated join call identifier.
6676 * Leaf initiated join parameters.
6677 * Leaf initiated join sequence number.
6678 *
6679 * References for this IE are:
6680 *
6681 * UNI4.0 pp. 46...48
6682 *
6683 * Only NET coding allowed.
6684 */
6685
6686/**********************************************************************/
6687
6688DEF_IE_PRINT(net, lij_callid)
6689{
6690 static const struct uni_print_tbl type_tbl[] = {
6691 MKT(UNI_LIJ_IDTYPE_ROOT, root),
6692 EOT()
6693 };
6694
6695 if(uni_print_iehdr("lij_callid", &ie->h, cx))
6696 return;
6697
6698 uni_print_tbl("type", ie->type, type_tbl, cx);
6699 uni_print_entry(cx, "id", "0x%x", ie->callid);
6700
6701 uni_print_ieend(cx);
6702}
6703
6704DEF_IE_CHECK(net, lij_callid)
6705{
6706 cx = cx;
6707
6708 switch(ie->type) {
6709
6710 case UNI_LIJ_IDTYPE_ROOT:
6711 break;
6712
6713 default:
6714 return -1;
6715 }
6716
6717 return 0;
6718}
6719
6720DEF_IE_ENCODE(net, lij_callid)
6721{
6722 START_IE(lij_callid, UNI_IE_LIJ_CALLID, 5);
6723
6724 APP_BYTE(msg, 0x80 | ie->type);
6725 APP_32BIT(msg, ie->callid);
6726
6727 SET_IE_LEN(msg);
6728 return 0;
6729}
6730
6731DEF_IE_DECODE(net, lij_callid)
6732{
6733 IE_START(;);
6734
6735 if(ielen != 5)
6736 goto rej;
6737
6738 ie->type = *msg->b_rptr++ & 0xf;
6739 ie->callid = *msg->b_rptr++ << 24;
6740 ie->callid |= *msg->b_rptr++ << 16;
6741 ie->callid |= *msg->b_rptr++ << 8;
6742 ie->callid |= *msg->b_rptr++ << 0;
6743
6744 IE_END(LIJ_CALLID);
6745}
6746
6747/**********************************************************************/
6748
6749DEF_IE_PRINT(net, lij_param)
6750{
6751 static const struct uni_print_tbl lscreen_tbl[] = {
6752 MKT(UNI_LIJ_SCREEN_NETJOIN, netjoin),
6753 EOT()
6754 };
6755
6756 if(uni_print_iehdr("lij_param", &ie->h, cx))
6757 return;
6758 uni_print_tbl("screen", ie->screen, lscreen_tbl, cx);
6759 uni_print_ieend(cx);
6760}
6761
6762DEF_IE_CHECK(net, lij_param)
6763{
6764 cx = cx;
6765
6766 switch(ie->screen) {
6767
6768 case UNI_LIJ_SCREEN_NETJOIN:
6769 break;
6770
6771 default:
6772 return -1;
6773 }
6774
6775 return 0;
6776}
6777
6778DEF_IE_ENCODE(net, lij_param)
6779{
6780 START_IE(lij_param, UNI_IE_LIJ_PARAM, 1);
6781
6782 APP_BYTE(msg, 0x80 | ie->screen);
6783
6784 SET_IE_LEN(msg);
6785 return 0;
6786}
6787
6788DEF_IE_DECODE(net, lij_param)
6789{
6790 IE_START(;);
6791
6792 if(ielen != 1)
6793 goto rej;
6794
6795 ie->screen = *msg->b_rptr++ & 0xf;
6796
6797 IE_END(LIJ_PARAM);
6798}
6799
6800/**********************************************************************/
6801
6802DEF_IE_PRINT(net, lij_seqno)
6803{
6804 if(uni_print_iehdr("lij_seqno", &ie->h, cx))
6805 return;
6806 uni_print_entry(cx, "seqno", "0x%x", ie->seqno);
6807 uni_print_ieend(cx);
6808}
6809
6810DEF_IE_CHECK(net, lij_seqno)
6811{
6812 cx = cx; ie = ie;
6813
6814 return 0;
6815}
6816
6817DEF_IE_ENCODE(net, lij_seqno)
6818{
6819 START_IE(lij_seqno, UNI_IE_LIJ_SEQNO, 4);
6820
6821 APP_32BIT(msg, ie->seqno);
6822
6823 SET_IE_LEN(msg);
6824 return 0;
6825}
6826
6827DEF_IE_DECODE(net, lij_seqno)
6828{
6829 IE_START(;);
6830
6831 if(ielen != 4)
6832 goto rej;
6833
6834 ie->seqno = *msg->b_rptr++ << 24;
6835 ie->seqno |= *msg->b_rptr++ << 16;
6836 ie->seqno |= *msg->b_rptr++ << 8;
6837 ie->seqno |= *msg->b_rptr++ << 0;
6838
6839 IE_END(LIJ_SEQNO);
6840}
6841
6842/*********************************************************************
6843 *
6844 * Connection scope
6845 *
6846 * References for this IE are:
6847 *
6848 * UNI4.0 pp. 57...58
6849 *
6850 * Only NET coding allowed.
6851 */
6852DEF_IE_PRINT(net, cscope)
6853{
6854 static const struct uni_print_tbl type_tbl[] = {
6855 MKT(UNI_CSCOPE_ORG, org),
6856 EOT()
6857 };
6858 static const struct uni_print_tbl scope_tbl[] = {
6859 MKT(UNI_CSCOPE_ORG_LOC, local_network),
6860 MKT(UNI_CSCOPE_ORG_LOC_P1, local_network_plus_one),
6861 MKT(UNI_CSCOPE_ORG_LOC_P2, local_network_plus_two),
6862 MKT(UNI_CSCOPE_ORG_SITE_M1, site_minus_one),
6863 MKT(UNI_CSCOPE_ORG_SITE, intra_site),
6864 MKT(UNI_CSCOPE_ORG_SITE_P1, site_plus_one),
6865 MKT(UNI_CSCOPE_ORG_ORG_M1, organisation_minus_one),
6866 MKT(UNI_CSCOPE_ORG_ORG, intra_organisation),
6867 MKT(UNI_CSCOPE_ORG_ORG_P1, organisation_plus_one),
6868 MKT(UNI_CSCOPE_ORG_COMM_M1, community_minus_one),
6869 MKT(UNI_CSCOPE_ORG_COMM, intra_community),
6870 MKT(UNI_CSCOPE_ORG_COMM_P1, community_plus_one),
6871 MKT(UNI_CSCOPE_ORG_REG, regional),
6872 MKT(UNI_CSCOPE_ORG_INTER, inter_regional),
6873 MKT(UNI_CSCOPE_ORG_GLOBAL, global),
6874 EOT()
6875 };
6876
6877 if(uni_print_iehdr("cscope", &ie->h, cx))
6878 return;
6879
6880 uni_print_tbl("type", ie->type, type_tbl, cx);
6881 if(ie->type == UNI_CSCOPE_ORG)
6882 uni_print_tbl("scope", (u_int)ie->scope, scope_tbl, cx);
6883 else
6884 uni_print_entry(cx, "scope", "0x%02x", ie->scope);
6885
6886 uni_print_ieend(cx);
6887}
6888
6889DEF_IE_CHECK(net, cscope)
6890{
6891 cx = cx;
6892
6893 switch(ie->type) {
6894
6895 default:
6896 return -1;
6897
6898 case UNI_CSCOPE_ORG:
6899 switch(ie->scope) {
6900
6901 default:
6902 return -1;
6903
6904 case UNI_CSCOPE_ORG_LOC:
6905 case UNI_CSCOPE_ORG_LOC_P1:
6906 case UNI_CSCOPE_ORG_LOC_P2:
6907 case UNI_CSCOPE_ORG_SITE_M1:
6908 case UNI_CSCOPE_ORG_SITE:
6909 case UNI_CSCOPE_ORG_SITE_P1:
6910 case UNI_CSCOPE_ORG_ORG_M1:
6911 case UNI_CSCOPE_ORG_ORG:
6912 case UNI_CSCOPE_ORG_ORG_P1:
6913 case UNI_CSCOPE_ORG_COMM_M1:
6914 case UNI_CSCOPE_ORG_COMM:
6915 case UNI_CSCOPE_ORG_COMM_P1:
6916 case UNI_CSCOPE_ORG_REG:
6917 case UNI_CSCOPE_ORG_INTER:
6918 case UNI_CSCOPE_ORG_GLOBAL:
6919 break;
6920 }
6921 break;
6922 }
6923 return 0;
6924}
6925
6926DEF_IE_ENCODE(net, cscope)
6927{
6928 START_IE(cscope, UNI_IE_CSCOPE, 2);
6929
6930 APP_BYTE(msg, ie->type | 0x80);
6931 APP_BYTE(msg, ie->scope);
6932
6933 SET_IE_LEN(msg);
6934 return 0;
6935}
6936
6937DEF_IE_DECODE(net, cscope)
6938{
6939 IE_START(;);
6940 if(ielen != 2)
6941 goto rej;
6942
6943 if((*msg->b_rptr & 0xf0) != 0x80)
6944 goto rej;
6945
6946 ie->type = *msg->b_rptr++ & 0xf;
6947 ie->scope = *msg->b_rptr++;
6948
6949 IE_END(CSCOPE);
6950}
6951
6952/*********************************************************************
6953 *
6954 * Extended Quality of Service
6955 *
6956 * References for this IE are:
6957 *
6958 * UNI4.0 pp. 70...72
6959 *
6960 * Notes:
6961 * Only NET coding.
6962 */
6963DEF_IE_PRINT(net, exqos)
6964{
6965 static const struct uni_print_tbl tab[] = {
6966 MKT(UNI_EXQOS_USER, user),
6967 MKT(UNI_EXQOS_NET, net),
6968 EOT()
6969 };
6970
6971 if(uni_print_iehdr("exqos", &ie->h, cx))
6972 return;
6973
6974 uni_print_tbl("origin", ie->origin, tab, cx);
6975
6976 uni_print_entry(cx, "acceptable", "(");
6977 if(ie->h.present & UNI_EXQOS_FACC_P) {
6978 if(ie->facc == UNI_EXQOS_ANY_CDV)
6979 uni_printf(cx, "ANY");
6980 else
6981 uni_printf(cx, "%d", ie->facc);
6982 }
6983 uni_putc(',', cx);
6984 if(ie->h.present & UNI_EXQOS_BACC_P) {
6985 if(ie->bacc == UNI_EXQOS_ANY_CDV)
6986 uni_printf(cx, "ANY");
6987 else
6988 uni_printf(cx, "%d", ie->bacc);
6989 }
6990 uni_putc(')', cx);
6991
6992 uni_print_entry(cx, "cumulative", "(");
6993 if(ie->h.present & UNI_EXQOS_FCUM_P)
6994 uni_printf(cx, "%d", ie->fcum);
6995 uni_putc(',', cx);
6996 if(ie->h.present & UNI_EXQOS_BCUM_P)
6997 uni_printf(cx, "%d", ie->bcum);
6998 uni_putc(')', cx);
6999
7000 uni_print_entry(cx, "clrid", "(");
7001 if(ie->h.present & UNI_EXQOS_FCLR_P) {
7002 if(ie->fclr == UNI_EXQOS_ANY_CLR)
7003 uni_printf(cx, "ANY");
7004 else
7005 uni_printf(cx, "%d", ie->fclr);
7006 }
7007 uni_putc(',', cx);
7008 if(ie->h.present & UNI_EXQOS_BCLR_P) {
7009 if(ie->bclr == UNI_EXQOS_ANY_CLR)
7010 uni_printf(cx, "ANY");
7011 else
7012 uni_printf(cx, "%d", ie->bclr);
7013 }
7014 uni_putc(')', cx);
7015
7016 uni_print_ieend(cx);
7017}
7018
7019DEF_IE_CHECK(net, exqos)
7020{
7021 cx = cx;
7022
7023 switch(ie->origin) {
7024 case UNI_EXQOS_USER:
7025 case UNI_EXQOS_NET:
7026 break;
7027
7028 default:
7029 return -1;
7030 }
7031 if(ie->h.present & UNI_EXQOS_FACC_P)
7032 if(!(ie->h.present & UNI_EXQOS_FCUM_P))
7033 return -1;
7034 if(ie->h.present & UNI_EXQOS_BACC_P)
7035 if(!(ie->h.present & UNI_EXQOS_BCUM_P))
7036 return -1;
7037
7038 if(ie->h.present & UNI_EXQOS_FACC_P)
7039 if(ie->facc >= 1 << 24)
7040 return -1;
7041 if(ie->h.present & UNI_EXQOS_BACC_P)
7042 if(ie->bacc >= 1 << 24)
7043 return -1;
7044 if(ie->h.present & UNI_EXQOS_FCUM_P)
7045 if(ie->fcum >= 1 << 24)
7046 return -1;
7047 if(ie->h.present & UNI_EXQOS_BCUM_P)
7048 if(ie->bcum >= 1 << 24)
7049 return -1;
7050
7051 if(ie->h.present & UNI_EXQOS_FCLR_P)
7052 if(ie->fclr==0 || (ie->fclr>15 && ie->fclr!=UNI_EXQOS_ANY_CLR))
7053 return -1;
7054 if(ie->h.present & UNI_EXQOS_BCLR_P)
7055 if(ie->bclr==0 || (ie->bclr>15 && ie->bclr!=UNI_EXQOS_ANY_CLR))
7056 return -1;
7057 return 0;
7058}
7059
7060DEF_IE_ENCODE(net, exqos)
7061{
7062 START_IE(exqos, UNI_IE_EXQOS, 21);
7063
7064 APP_BYTE(msg, ie->origin);
7065
7066 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FACC_P,
7067 UNI_EXQOS_FACC_ID, ie->facc);
7068 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BACC_P,
7069 UNI_EXQOS_BACC_ID, ie->bacc);
7070 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FCUM_P,
7071 UNI_EXQOS_FCUM_ID, ie->fcum);
7072 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BCUM_P,
7073 UNI_EXQOS_BCUM_ID, ie->bcum);
7074
7075 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_FCLR_P,
7076 UNI_EXQOS_FCLR_ID, ie->fclr);
7077 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_BCLR_P,
7078 UNI_EXQOS_BCLR_ID, ie->bclr);
7079
7080 SET_IE_LEN(msg);
7081 return 0;
7082}
7083
7084DEF_IE_DECODE(net, exqos)
7085{
7086 IE_START(;);
7087
7088 if(ielen < 1 || ielen > 21)
7089 goto rej;
7090
7091 ie->origin = *msg->b_rptr++;
7092 ielen--;
7093
7094 while(ielen--) {
7095 switch(*msg->b_rptr++) {
7096
7097 default:
7098 goto rej;
7099
7100 DEC_GETF3(EXQOS_FACC, facc, ie->h.present);
7101 DEC_GETF3(EXQOS_BACC, bacc, ie->h.present);
7102 DEC_GETF3(EXQOS_FCUM, fcum, ie->h.present);
7103 DEC_GETF3(EXQOS_BCUM, bcum, ie->h.present);
7104
7105 DEC_GETF1(EXQOS_FCLR, fclr, ie->h.present);
7106 DEC_GETF1(EXQOS_BCLR, bclr, ie->h.present);
7107
7108 }
7109 }
7110 IE_END(EXQOS);
7111}
7112
7113/**************************************************************
7114 *
7115 * Free form IE (for testing mainly)
7116 */
7117DEF_IE_PRINT(itu, unrec)
7118{
7119 u_int i;
7120
7121 if (uni_print_iehdr("unrec", &ie->h, cx))
7122 return;
7123 uni_print_entry(cx, "len", "%u", ie->len);
7124 uni_print_entry(cx, "data", "(");
7125 for (i = 0; i < ie->len; i++)
7126 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->data[i]);
7127 uni_printf(cx, ")");
7128 uni_print_ieend(cx);
7129}
7130
7131DEF_IE_CHECK(itu, unrec)
7132{
7133 cx = cx;
7134
7135 if (ie->len > sizeof(ie->data))
7136 return (-1);
7137
7138 return (0);
7139}
7140
7141DEF_IE_ENCODE(itu, unrec)
7142{
7143 START_IE2(unrec, UNI_IE_UNREC, ie->len, ie->id);
7144
7145 APP_BUF(msg, ie->data, ie->len);
7146
7147 SET_IE_LEN(msg);
7148 return (0);
7149}
7150
7151DEF_IE_DECODE(itu, unrec)
7152{
7153 IE_START(;);
7154
7155 if (ielen > sizeof(ie->data) / sizeof(ie->data[0]) || ielen < 1)
7156 goto rej;
7157
7158 ie->len = ielen;
7159 ielen = 0;
7160 (void)memcpy(ie->data, msg->b_rptr, ie->len);
7161 msg->b_rptr += ie->len;
7162
7163 IE_END(UNREC);
7164}