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.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 #define UNUSED(_p) do { (void)(_p); } while (0)
51
52 /*
53 * Define internal functions.
54 */
55 #define DEF_IE_PRINT(Coding, IE) \
56 void uni_ie_print_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
57
58 #define DEF_IE_CHECK(Coding, IE) \
59 int uni_ie_check_##Coding##_##IE(struct uni_ie_##IE *ie, struct unicx *cx)
60
61 #define DEF_IE_ENCODE(Coding, IE) \
62 int uni_ie_encode_##Coding##_##IE(struct uni_msg *msg, struct uni_ie_##IE *ie, struct unicx *cx)
63
64 #define DEF_IE_DECODE(Coding, IE) \
65 int uni_ie_decode_##Coding##_##IE(struct uni_ie_##IE *ie, struct uni_msg *msg, u_int ielen, struct unicx *cx)
66
67 /*
68 * This structure is used to define value->string mappings. MKT() is used
69 * to generate a table entry. EOT() to end the table.
70 */
71 #define MKT(V,N) { #N, V }
72 #define EOT() { NULL, 0 }
73
74 /* library internal functions */
75 static void uni_entry(const char *, struct unicx *);
76 static int uni_print_iehdr(const char *, struct uni_iehdr *h, struct unicx *);
77 static void uni_print_ieend(struct unicx *);
78 static void uni_putc(int, struct unicx *);
79
80
81 /*
82 * Encoding
83 */
84 #define APP_BYTE(M, B) do { \
85 *(M)->b_wptr++ = (B); \
86 } while (0)
87 #define APP_16BIT(M, B) do { \
88 u_int _v = (B); \
89 *(M)->b_wptr++ = _v >> 8; \
90 *(M)->b_wptr++ = _v; \
91 } while (0)
92 #define APP_24BIT(M, B) do { \
93 u_int _v = (B); \
94 *(M)->b_wptr++ = _v >> 16; \
95 *(M)->b_wptr++ = _v >> 8; \
96 *(M)->b_wptr++ = _v; \
97 } while (0)
98 #define APP_32BIT(M, B) do { \
99 u_int _v = (B); \
100 *(M)->b_wptr++ = _v >> 24; \
101 *(M)->b_wptr++ = _v >> 16; \
102 *(M)->b_wptr++ = _v >> 8; \
103 *(M)->b_wptr++ = _v; \
104 } while (0)
105 #define APP_BUF(M, B, L) do { \
106 (void)memcpy((M)->b_wptr, (B), (L)); \
107 (M)->b_wptr += (L); \
108 } while (0)
109
110 #define APP_SUB_BYTE(M, T, B) do { APP_BYTE(M, T); APP_BYTE(M, B); } while (0)
111 #define APP_SUB_16BIT(M, T, B) do { APP_BYTE(M, T); APP_16BIT(M, B); } while (0)
112 #define APP_SUB_24BIT(M, T, B) do { APP_BYTE(M, T); APP_24BIT(M, B); } while (0)
113 #define APP_SUB_32BIT(M, T, B) do { APP_BYTE(M, T); APP_32BIT(M, B); } while (0)
114
115 #define APP_OPT(M, F, P, T) do { \
116 if ((F) & (P)) \
117 APP_BYTE((M), (T)); \
118 } while (0)
119 #define APP_OPT_BYTE(M, F, P, T, B) do { \
120 if ((F) & (P)) \
121 APP_SUB_BYTE((M), (T), (B)); \
122 } while (0)
123 #define APP_OPT_16BIT(M, F, P, T, B) do { \
124 if ((F) & (P)) \
125 APP_SUB_16BIT((M), (T), (B)); \
126 } while (0)
127 #define APP_OPT_24BIT(M, F, P, T, B) do { \
128 if ((F) & (P)) \
129 APP_SUB_24BIT((M), (T), (B)); \
130 } while (0)
131
132 #define START_IE(TYPE,CODE,LEN) \
133 u_int ielen; \
134 \
135 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
136 return (-1); \
137 if (uni_encode_ie_hdr(msg, CODE, &ie->h, (LEN), cx)) \
138 return (0); \
139 \
140 ielen = msg->b_wptr - msg->b_rptr - 2;
141
142 #define START_IE2(TYPE,CODE,LEN,REALCODE) \
143 u_int ielen; \
144 \
145 if (uni_check_ie(CODE, (union uni_ieall *)ie, cx)) \
146 return (-1); \
147 if (uni_encode_ie_hdr(msg, REALCODE, &ie->h, (LEN), cx)) \
148 return (0); \
149 \
150 ielen = msg->b_wptr - msg->b_rptr - 2;
151
152 #define SET_IE_LEN(M) do { \
153 (M)->b_buf[ielen + 0] = \
154 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 8; \
155 (M)->b_buf[ielen + 1] = \
156 (((M)->b_wptr - (M)->b_rptr) - ielen - 2) >> 0; \
157 } while (0)
158
159
160 /***********************************************************************/
161 /*
162 * Decoding
163 */
164 #define IE_START(ERR) \
165 if (IE_ISPRESENT(*ie)) \
166 return (0); \
167 if (ielen == 0) { \
168 IE_SETEMPTY(*ie); \
169 return (0); \
170 }
171
172 #define IE_END(IE) \
173 IE_SETPRESENT(*ie); \
174 if (uni_check_ie(UNI_IE_##IE, (union uni_ieall *)ie, cx) == 0) \
175 return (0); \
176 rej: \
177 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT; \
178 return (1);
179
180 #define DEC_GETF3(ID, F, P) \
181 case UNI_##ID##_ID: \
182 if (ielen < 3) \
183 goto rej; \
184 ielen -= 3; \
185 if (!(P & UNI_##ID##_P)) { \
186 P |= UNI_##ID##_P; \
187 ie->F = *msg->b_rptr++ << 16; \
188 ie->F |= *msg->b_rptr++ << 8; \
189 ie->F |= *msg->b_rptr++; \
190 } else \
191 msg->b_rptr += 3; \
192 break;
193
194 #define DEC_GETF1(ID, F, P) \
195 case UNI_##ID##_ID: \
196 if (ielen < 1) \
197 goto rej; \
198 ielen--; \
199 if (!(P & UNI_##ID##_P)) { \
200 P |= UNI_##ID##_P; \
201 ie->F = *msg->b_rptr++; \
202 } else \
203 msg->b_rptr++; \
204 break;
205
206
207 #define PRINT_NPREFIX (sizeof(((struct unicx *)0)->prefix) / \
208 sizeof(((struct unicx *)0)->prefix[0]))
209
210 /*
211 * This is rather here than in privmsg.c because we need the APP macros.
212 */
213 int
214 uni_encode_msg_hdr(struct uni_msg *msg, struct uni_msghdr *h,
215 enum uni_msgtype type, struct unicx *cx, int *mlen)
216 {
217 u_char byte;
218
219 if (uni_msg_ensure(msg, 9) != 0)
220 return -1;
221
222 APP_BYTE(msg, cx->pnni ? PNNI_PROTO : UNI_PROTO);
223 APP_BYTE(msg, 3);
224 if(h->cref.cref >= 1<<23)
225 return -1;
226 APP_24BIT(msg, h->cref.cref | (h->cref.flag ? 0x800000 : 0));
227 APP_BYTE(msg, type);
228
229 byte = 0x80;
230 if(h->act != UNI_MSGACT_DEFAULT)
231 byte |= 0x10 | (h->act & 3);
232 if(cx->pnni && h->pass)
233 byte |= 0x08;
234 APP_BYTE(msg, byte);
235
236 *mlen = msg->b_wptr - msg->b_rptr;
237 APP_16BIT(msg, 0);
238
239 return 0;
240 }
241
242 /*
243 * Initialize printing. This must be called by all printing routines
244 * that are exported to the user.
245 */
246 void
247 uni_print_init(char *buf, size_t bufsiz, struct unicx *cx)
248 {
249 if (cx->dont_init)
250 return;
251
252 cx->indent = 0;
253 cx->nprefix = 0;
254 cx->doindent = 0;
255 if (cx->tabsiz == 0)
256 cx->tabsiz = 4;
257 cx->buf = buf;
258 cx->bufsiz = bufsiz;
259 }
260
261 /*
262 * Append a character to the buffer if there is still space
263 */
264 static void
265 uni_putc(int c, struct unicx *cx)
266 {
267 if(cx->bufsiz > 1) {
268 *cx->buf++ = c;
269 cx->bufsiz--;
270 *cx->buf = '\0';
271 }
272 }
273
274 void
275 uni_printf(struct unicx *cx, const char *fmt, ...)
276 {
277 u_int n;
278 va_list ap;
279
280 if(cx->bufsiz > 1) {
281 va_start(ap, fmt);
282 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
283 va_end(ap);
284 if(n > 0) {
285 if(n < cx->bufsiz) {
286 cx->bufsiz -= n;
287 cx->buf += n;
288 } else {
289 cx->buf += cx->bufsiz - 1;
290 cx->bufsiz = 1;
291 }
292 }
293 *cx->buf = '\0';
294 }
295 }
296
297 /*
298 * Print mode:
299 * 0 - print all into one line, fully prefixed
300 * 1 - print on multiple lines, full prefixed, but equal level
301 * entries on one line
302 * 2 - like 2, but only partial prefixed
303 * 3 - like 1, but each entry onto a new line
304 * 4 - like 2 + 3
305 */
306
307 /*
308 * If we are in multiline mode, end the current line and set the
309 * flag, that we need indentation. But prevent double new lines.
310 */
311 void
312 uni_print_eol(struct unicx *cx)
313 {
314 if (cx->multiline) {
315 if (!cx->doindent) {
316 uni_putc('\n', cx);
317 cx->doindent = 1;
318 }
319 }
320 }
321
322 /*
323 * New entry. Do the prefixing, indentation and spacing.
324 */
325 static void
326 doprefix(struct unicx *cx, const char *s)
327 {
328 u_int i;
329
330 if(cx->multiline == 0) {
331 uni_putc(' ', cx);
332 for(i = 0; i < cx->nprefix; i++)
333 if(cx->prefix[i])
334 uni_printf(cx, "%s.", cx->prefix[i]);
335 } else if(cx->multiline == 1) {
336 if(cx->doindent) {
337 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
338 cx->doindent = 0;
339 } else
340 uni_putc(' ', cx);
341 for(i = 0; i < cx->nprefix; i++)
342 if(cx->prefix[i])
343 uni_printf(cx, "%s.", cx->prefix[i]);
344 } else if(cx->multiline == 2) {
345 if(cx->doindent) {
346 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
347 cx->doindent = 0;
348 } else
349 uni_putc(' ', cx);
350 } else if(cx->multiline == 3) {
351 if(cx->doindent)
352 cx->doindent = 0;
353 else
354 uni_putc('\n', cx);
355 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
356 for(i = 0; i < cx->nprefix; i++)
357 if(cx->prefix[i])
358 uni_printf(cx, "%s.", cx->prefix[i]);
359 } else if(cx->multiline == 4) {
360 if(cx->doindent)
361 cx->doindent = 0;
362 else
363 uni_putc('\n', cx);
364 uni_printf(cx, "%*s", cx->indent * cx->tabsiz, "");
365 }
366 uni_printf(cx, "%s", s);
367 }
368 static void
369 uni_entry(const char *s, struct unicx *cx)
370 {
371 doprefix(cx, s);
372 uni_putc('=', cx);
373 }
374 void
375 uni_print_flag(const char *s, struct unicx *cx)
376 {
377 doprefix(cx, s);
378 }
379
380
381 /*
382 * Start a deeper level of indendation. If multiline is in effect,
383 * we end the current line.
384 */
385 void
386 uni_print_push_prefix(const char *prefix, struct unicx *cx)
387 {
388 if (cx->nprefix < PRINT_NPREFIX)
389 cx->prefix[cx->nprefix++] = prefix;
390 }
391 void
392 uni_print_pop_prefix(struct unicx *cx)
393 {
394 if (cx->nprefix > 0)
395 cx->nprefix--;
396 }
397
398 void
399 uni_print_tbl(const char *entry, u_int val, const struct uni_print_tbl *tbl,
400 struct unicx *cx)
401 {
402 if (entry)
403 uni_entry(entry, cx);
404 while (tbl->name) {
405 if (tbl->val == val) {
406 uni_printf(cx, "%s", tbl->name);
407 return;
408 }
409 tbl++;
410 }
411 uni_printf(cx, "ERROR(0x%x)", val);
412 }
413
414 void
415 uni_print_entry(struct unicx *cx, const char *e, const char *fmt, ...)
416 {
417 u_int n;
418 va_list ap;
419
420 uni_entry(e, cx);
421
422 if (cx->bufsiz > 1) {
423 va_start(ap, fmt);
424 n = vsnprintf(cx->buf, cx->bufsiz, fmt, ap);
425 va_end(ap);
426 if (n > 0) {
427 if (n < cx->bufsiz) {
428 cx->bufsiz -= n;
429 cx->buf += n;
430 } else {
431 cx->buf += cx->bufsiz - 1;
432 cx->bufsiz = 1;
433 }
434 }
435 *cx->buf = '\0';
436 }
437 }
438
439 /**********************************************************************/
440 /*
441 * Printing information elements.
442 */
443 static int
444 uni_print_iehdr(const char *name, struct uni_iehdr *h, struct unicx *cx)
445 {
446 static const struct uni_print_tbl act_tab[] = {
447 MKT(UNI_IEACT_CLEAR, clear),
448 MKT(UNI_IEACT_IGNORE, ignore),
449 MKT(UNI_IEACT_REPORT, report),
450 MKT(UNI_IEACT_MSG_IGNORE, ignore-msg),
451 MKT(UNI_IEACT_MSG_REPORT, report-msg),
452 MKT(UNI_IEACT_DEFAULT, default),
453 EOT()
454 };
455 static const struct uni_print_tbl cod_tab[] = {
456 MKT(UNI_CODING_ITU, itut),
457 MKT(UNI_CODING_NET, atmf),
458 EOT()
459 };
460
461 uni_print_entry(cx, name, "(");
462 uni_print_tbl(NULL, h->act, act_tab, cx);
463 uni_putc(',', cx);
464 uni_print_tbl(NULL, h->coding, cod_tab, cx);
465 if(cx->pnni && h->pass)
466 uni_printf(cx, ",pass");
467 if(IE_ISEMPTY(*(struct uni_ie_aal *)h)) {
468 uni_printf(cx, ",empty)");
469 uni_print_eol(cx);
470 return 1;
471 }
472 if(IE_ISERROR(*(struct uni_ie_aal *)h)) {
473 uni_printf(cx, ",error)");
474 uni_print_eol(cx);
475 return 1;
476 }
477
478 uni_putc(')', cx);
479
480 uni_print_push_prefix(name, cx);
481 uni_print_eol(cx);
482 cx->indent++;
483
484 return 0;
485 }
486
487 static void
488 uni_print_ieend(struct unicx *cx)
489 {
490 uni_print_pop_prefix(cx);
491 uni_print_eol(cx);
492 cx->indent--;
493 }
494
495 void
496 uni_print_ie_internal(enum uni_ietype code, const union uni_ieall *ie,
497 struct unicx *cx)
498 {
499 const struct iedecl *iedecl;
500
501 if((iedecl = GET_IEDECL(code, ie->h.coding)) != NULL)
502 (*iedecl->print)(ie, cx);
503 }
504
505 void
506 uni_print_ie(char *buf, size_t size, enum uni_ietype code,
507 const union uni_ieall *ie, struct unicx *cx)
508 {
509 uni_print_init(buf, size, cx);
510 uni_print_ie_internal(code, ie, cx);
511 }
512
513 int
514 uni_check_ie(enum uni_ietype code, union uni_ieall *ie, struct unicx *cx)
515 {
516 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
517
518 if (iedecl != NULL)
519 return (iedecl->check(ie, cx));
520 else
521 return (-1);
522 }
523
524 /*
525 * Decode a information element header.
526 * Returns -1 if the message is too short.
527 * Strip the header from the message.
528 * The header is stripped, even if it is too short.
529 */
530 int
531 uni_decode_ie_hdr(enum uni_ietype *ietype, struct uni_iehdr *hdr,
532 struct uni_msg *msg, struct unicx *cx, u_int *ielen)
533 {
534 u_int len;
535
536 *ietype = (enum uni_ietype)0;
537 *ielen = 0;
538 hdr->present = 0;
539 hdr->coding = UNI_CODING_ITU;
540 hdr->act = UNI_IEACT_DEFAULT;
541
542 if ((len = uni_msg_len(msg)) == 0)
543 return (-1);
544
545 *ietype = *msg->b_rptr++;
546
547 if (--len == 0)
548 return (-1);
549
550 hdr->coding = (*msg->b_rptr >> 5) & 3;
551 hdr->present = 0;
552
553 switch (*msg->b_rptr & 0x17) {
554
555 case 0x10: case 0x11: case 0x12:
556 case 0x15: case 0x16:
557 hdr->act = *msg->b_rptr & 0x7;
558 break;
559
560 case 0x00: case 0x01: case 0x02: case 0x03:
561 case 0x04: case 0x05: case 0x06: case 0x07:
562 hdr->act = UNI_IEACT_DEFAULT;
563 break;
564
565 default:
566 /* Q.2931 5.7.2 last sentence */
567 hdr->act = UNI_IEACT_REPORT;
568 break;
569 }
570 if (cx->pnni && (*msg->b_rptr & 0x08))
571 hdr->pass = 1;
572 else
573 hdr->pass = 0;
574 msg->b_rptr++;
575
576 if (--len == 0) {
577 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
578 return (-1);
579 }
580
581 if (len < 2) {
582 msg->b_rptr += len;
583 hdr->present = UNI_IE_ERROR | UNI_IE_PRESENT;
584 return (-1);
585 }
586
587 *ielen = *msg->b_rptr++ << 8;
588 *ielen |= *msg->b_rptr++;
589
590 return (0);
591 }
592
593 /*
594 * Decode the body of an information element.
595 */
596 int
597 uni_decode_ie_body(enum uni_ietype ietype, union uni_ieall *ie,
598 struct uni_msg *msg, u_int ielen, struct unicx *cx)
599 {
600 const struct iedecl *iedecl;
601 u_char *end;
602 int ret;
603
604 if (ielen > uni_msg_len(msg)) {
605 /*
606 * Information element too long -> content error.
607 * Q.2931 5.6.8.2
608 */
609 msg->b_rptr = msg->b_wptr;
610 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
611 return (-1);
612 }
613
614 if ((iedecl = GET_IEDECL(ietype, ie->h.coding)) == NULL) {
615 /*
616 * entirly unknown IE.
617 * Q.2931 5.6.8.1
618 */
619 msg->b_rptr += ielen;
620 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
621 return (-1);
622 }
623
624 if (ielen > iedecl->maxlen) {
625 /*
626 * Information element too long -> content error.
627 * Q.2931 5.6.8.2
628 */
629 msg->b_rptr += iedecl->maxlen;
630 ie->h.present = UNI_IE_ERROR | UNI_IE_PRESENT;
631 return (-1);
632 }
633
634 end = msg->b_rptr + ielen;
635 ret = (*iedecl->decode)(ie, msg, ielen, cx);
636 msg->b_rptr = end;
637
638 return (ret);
639 }
640
641 int
642 uni_encode_ie(enum uni_ietype code, struct uni_msg *msg, union uni_ieall *ie,
643 struct unicx *cx)
644 {
645 const struct iedecl *iedecl = GET_IEDECL(code, ie->h.coding);
646
647 if (iedecl == NULL)
648 return (-1);
649 return (iedecl->encode(msg, ie, cx));
650 }
651
652 int
653 uni_encode_ie_hdr(struct uni_msg *msg, enum uni_ietype type,
654 struct uni_iehdr *h, u_int len, struct unicx *cx)
655 {
656 u_char byte;
657
658 if (uni_msg_ensure(msg, 4 + len) != 0)
659 return -1;
660 *msg->b_wptr++ = type;
661
662 byte = 0x80 | (h->coding << 5);
663 if(h->act != UNI_IEACT_DEFAULT)
664 byte |= 0x10 | (h->act & 7);
665 if(cx->pnni)
666 byte |= h->pass << 3;
667 *msg->b_wptr++ = byte;
668
669 if(h->present & UNI_IE_EMPTY) {
670 *msg->b_wptr++ = 0;
671 *msg->b_wptr++ = 4;
672 return -1;
673 }
674 *msg->b_wptr++ = 0;
675 *msg->b_wptr++ = 0;
676
677 return 0;
678 }
679
680 /*
681 * Printing messages.
682 */
683 static void
684 uni_print_cref_internal(const struct uni_cref *cref, struct unicx *cx)
685 {
686 uni_print_entry(cx, "cref", "%d.", cref->flag);
687 if (cref->cref == CREF_GLOBAL)
688 uni_printf(cx, "GLOBAL");
689 else if (cref->cref == CREF_DUMMY)
690 uni_printf(cx, "DUMMY");
691 else
692 uni_printf(cx, "%d", cref->cref);
693 }
694 void
695 uni_print_cref(char *str, size_t len, const struct uni_cref *cref,
696 struct unicx *cx)
697 {
698 uni_print_init(str, len, cx);
699 uni_print_cref_internal(cref, cx);
700 }
701
702 static void
703 uni_print_msghdr_internal(const struct uni_msghdr *hdr, struct unicx *cx)
704 {
705 static const struct uni_print_tbl tab[] = {
706 MKT(UNI_MSGACT_CLEAR, clear),
707 MKT(UNI_MSGACT_IGNORE, ignore),
708 MKT(UNI_MSGACT_REPORT, report),
709 MKT(UNI_MSGACT_DEFAULT, default),
710 EOT()
711 };
712
713 uni_print_cref_internal(&hdr->cref, cx);
714 uni_print_tbl("act", hdr->act, tab, cx);
715 if (cx->pnni)
716 uni_print_entry(cx, "pass", "%s", hdr->pass ? "yes" : "no");
717 }
718
719 void
720 uni_print_msghdr(char *str, size_t len, const struct uni_msghdr *hdr,
721 struct unicx *cx)
722 {
723 uni_print_init(str, len, cx);
724 uni_print_msghdr_internal(hdr, cx);
725 }
726
727
728 static void
729 uni_print_internal(const struct uni_all *msg, struct unicx *cx)
730 {
731 uni_entry("mtype", cx);
732 if(msg->mtype >= 256 || uni_msgtable[msg->mtype] == NULL) {
733 uni_printf(cx, "0x%02x(ERROR)", msg->mtype);
734 } else {
735 uni_printf(cx, "%s", uni_msgtable[msg->mtype]->name);
736 uni_print_msghdr_internal(&msg->u.hdr, cx);
737 cx->indent++;
738 uni_print_eol(cx);
739 (*uni_msgtable[msg->mtype]->print)(&msg->u, cx);
740 cx->indent--;
741 }
742
743 if(cx->multiline == 0)
744 uni_printf(cx, "\n");
745 }
746
747 void
748 uni_print(char *buf, size_t size, const struct uni_all *all, struct unicx *cx)
749 {
750 uni_print_init(buf, size, cx);
751 uni_print_internal(all, cx);
752 }
753
754 static void
755 uni_print_msg_internal(u_int mtype, const union uni_msgall *msg,
756 struct unicx *cx)
757 {
758
759 uni_entry("mtype", cx);
760 if (mtype >= 256 || uni_msgtable[mtype] == NULL) {
761 uni_printf(cx, "0x%02x(ERROR)", mtype);
762 } else {
763 uni_printf(cx, "%s", uni_msgtable[mtype]->name);
764 uni_print_msghdr_internal(&msg->hdr, cx);
765 cx->indent++;
766 uni_print_eol(cx);
767 (*uni_msgtable[mtype]->print)(msg, cx);
768 cx->indent--;
769 }
770
771 if(cx->multiline == 0)
772 uni_printf(cx, "\n");
773 }
774
775 void
776 uni_print_msg(char *buf, size_t size, u_int mtype, const union uni_msgall *all,
777 struct unicx *cx)
778 {
779 uni_print_init(buf, size, cx);
780 uni_print_msg_internal(mtype, all, cx);
781 }
782
783 void
784 uni_print_cx(char *buf, size_t size, struct unicx *cx)
785 {
786 static const char *acttab[] = {
787 "clr", /* 0x00 */
788 "ign", /* 0x01 */
789 "rep", /* 0x02 */
790 "x03", /* 0x03 */
791 "x04", /* 0x04 */
792 "mig", /* 0x05 */
793 "mrp", /* 0x06 */
794 "x07", /* 0x07 */
795 "def", /* 0x08 */
796 };
797
798 static const char *errtab[] = {
799 [UNI_IERR_UNK] = "unk", /* unknown IE */
800 [UNI_IERR_LEN] = "len", /* length error */
801 [UNI_IERR_BAD] = "bad", /* content error */
802 [UNI_IERR_ACC] = "acc", /* access element discarded */
803 [UNI_IERR_MIS] = "mis", /* missing IE */
804 };
805
806 u_int i;
807
808 uni_print_init(buf, size, cx);
809
810 uni_printf(cx, "q2932 %d\n", cx->q2932);
811 uni_printf(cx, "pnni %d\n", cx->pnni);
812 uni_printf(cx, "git_hard %d\n", cx->git_hard);
813 uni_printf(cx, "bearer_hard %d\n", cx->bearer_hard);
814 uni_printf(cx, "cause_hard %d\n", cx->cause_hard);
815
816 uni_printf(cx, "multiline %d\n", cx->multiline);
817 uni_printf(cx, "tabsiz %d\n", cx->tabsiz);
818
819 uni_printf(cx, "errcnt %d (", cx->errcnt);
820 for(i = 0; i < cx->errcnt; i++) {
821 uni_printf(cx, "%02x[%s,%s%s]", cx->err[i].ie,
822 errtab[cx->err[i].err], acttab[cx->err[i].act],
823 cx->err[i].man ? ",M" : "");
824 if(i != cx->errcnt - 1)
825 uni_putc(' ', cx);
826 }
827 uni_printf(cx, ")\n");
828 }
829
830 #include <netnatm/msg/uni_ietab.h>
831
832 /*********************************************************************
833 *
834 * Cause
835 *
836 * References for this IE are:
837 *
838 * Q.2931 pp. 69 (just a pointer to Q.2610)
839 * Q.2610 (this is a small diff to Q.850)
840 * Q.850 !!
841 * UNI4.0 pp. 15
842 * PNNI1.0 p. 198
843 *
844 * ITU-T and NET coding for different values.
845 */
846 static const struct causetab {
847 const char *str;
848 enum uni_diag diag;
849 } itu_causes[128] = {
850
851 #define D(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
852 #define N(NAME,VAL,DIAG,STD,STR)
853
854 UNI_DECLARE_CAUSE_VALUES
855
856 #undef D
857 #undef N
858
859 }, net_causes[128] = {
860
861 #define D(NAME,VAL,DIAG,STD,STR)
862 #define N(NAME,VAL,DIAG,STD,STR) [UNI_CAUSE_##NAME] = { STR, UNI_DIAG_##DIAG },
863
864 UNI_DECLARE_CAUSE_VALUES
865
866 #undef D
867 #undef N
868
869 };
870
871 enum uni_diag
872 uni_diag(enum uni_cause cause, enum uni_coding code)
873 {
874 if ((int)cause >= 128)
875 return (UNI_DIAG_NONE);
876
877 if (code == UNI_CODING_NET)
878 if (net_causes[cause].str != NULL)
879 return (net_causes[cause].diag);
880 if (itu_causes[cause].str != NULL)
881 return (itu_causes[cause].diag);
882 return (UNI_DIAG_NONE);
883 }
884
885 /**********************************************************************/
886
887 static void
888 print_cause(struct unicx *cx, struct uni_ie_cause *ie,
889 const struct causetab *tab1, const struct causetab *tab2)
890 {
891 static const struct uni_print_tbl loc_tbl[] = {
892 MKT(UNI_CAUSE_LOC_USER, user),
893 MKT(UNI_CAUSE_LOC_PRIVLOC, priv-net:loc-user),
894 MKT(UNI_CAUSE_LOC_PUBLOC, pub-net:loc-user),
895 MKT(UNI_CAUSE_LOC_TRANSIT, transit-net),
896 MKT(UNI_CAUSE_LOC_PUBREM, pub-net:rem-user),
897 MKT(UNI_CAUSE_LOC_PRIVREM, priv-net:rem-user),
898 MKT(UNI_CAUSE_LOC_INTERNAT, int-net),
899 MKT(UNI_CAUSE_LOC_BEYOND, beyond),
900 EOT()
901 };
902 static const struct uni_print_tbl pu_tbl[] = {
903 MKT(UNI_CAUSE_PU_PROVIDER, provider),
904 MKT(UNI_CAUSE_PU_USER, user),
905 EOT()
906 };
907 static const struct uni_print_tbl na_tbl[] = {
908 MKT(UNI_CAUSE_NA_NORMAL, normal),
909 MKT(UNI_CAUSE_NA_ABNORMAL, abnormal),
910 EOT()
911 };
912 static const struct uni_print_tbl cond_tbl[] = {
913 MKT(UNI_CAUSE_COND_UNKNOWN, unknown),
914 MKT(UNI_CAUSE_COND_PERM, permanent),
915 MKT(UNI_CAUSE_COND_TRANS, transient),
916 EOT()
917 };
918 static const struct uni_print_tbl rej_tbl[] = {
919 MKT(UNI_CAUSE_REASON_USER, user),
920 MKT(UNI_CAUSE_REASON_IEMISS, ie-missing),
921 MKT(UNI_CAUSE_REASON_IESUFF, ie-not-suff),
922 EOT()
923 };
924 char buf[100], *s;
925 u_int i;
926
927 if (uni_print_iehdr("cause", &ie->h, cx))
928 return;
929
930 if ((int)ie->cause < 128 && tab1[ie->cause].str)
931 strcpy(buf, tab1[ie->cause].str);
932 else if ((int)ie->cause < 128 && tab2 != NULL && tab2[ie->cause].str != NULL)
933 strcpy(buf, tab2[ie->cause].str);
934 else {
935 sprintf(buf, "UNKNOWN-%u", ie->cause);
936 }
937
938 for (s = buf; *s != '\0'; s++)
939 if (*s == ' ')
940 *s = '_';
941 uni_print_entry(cx, "cause", "%s", buf);
942
943 uni_print_tbl("loc", ie->loc, loc_tbl, cx);
944
945 if (ie->h.present & UNI_CAUSE_COND_P) {
946 uni_print_tbl("pu", ie->u.cond.pu, pu_tbl, cx);
947 uni_print_tbl("na", ie->u.cond.na, na_tbl, cx);
948 uni_print_tbl("condition", ie->u.cond.cond, cond_tbl, cx);
949 }
950 if (ie->h.present & UNI_CAUSE_REJ_P) {
951 uni_print_tbl("reject", ie->u.rej.reason, rej_tbl, cx);
952 }
953 if (ie->h.present & UNI_CAUSE_REJ_USER_P) {
954 uni_print_entry(cx, "user", "%u", ie->u.rej.user);
955 }
956 if (ie->h.present & UNI_CAUSE_REJ_IE_P) {
957 uni_print_entry(cx, "ie", "%u", ie->u.rej.ie);
958 }
959 if (ie->h.present & UNI_CAUSE_IE_P) {
960 uni_print_entry(cx, "ie", "(");
961 for (i = 0; i < ie->u.ie.len; i++) {
962 if (i)
963 uni_putc(',', cx);
964 uni_printf(cx, "0x%02x", ie->u.ie.ie[i]);
965 }
966 uni_putc(')', cx);
967 }
968 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
969 uni_print_entry(cx, "traffic", "(");
970 for (i = 0; i < ie->u.traffic.len; i++) {
971 if (i)
972 uni_putc(',', cx);
973 uni_printf(cx, "0x%02x", ie->u.traffic.traffic[i]);
974 }
975 uni_putc(')', cx);
976 }
977 if (ie->h.present & UNI_CAUSE_VPCI_P) {
978 uni_print_entry(cx, "vpci", "(%u,%u)", ie->u.vpci.vpci, ie->u.vpci.vci);
979 }
980 if (ie->h.present & UNI_CAUSE_MTYPE_P) {
981 uni_print_entry(cx, "mtype", "%u", ie->u.mtype);
982 }
983 if (ie->h.present & UNI_CAUSE_TIMER_P) {
984 for (i = 0, s = buf; i < 3; i++) {
985 if (ie->u.timer[i] < ' ') {
986 *s++ = '^';
987 *s++ = ie->u.timer[i] + '@';
988 } else if (ie->u.timer[i] <= '~')
989 *s++ = ie->u.timer[i];
990 else {
991 *s++ = '\\';
992 *s++ = ie->u.timer[i] / 0100 + '';
993 *s++ = (ie->u.timer[i] % 0100) / 010 + '';
994 *s++ = ie->u.timer[i] % 010 + '';
995 }
996 }
997 *s++ = '\0';
998 uni_print_entry(cx, "timer", "\"%s\"", buf);
999 }
1000 if (ie->h.present & UNI_CAUSE_TNS_P) {
1001 uni_print_eol(cx);
1002 uni_print_ie_internal(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx);
1003 }
1004 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1005 uni_print_eol(cx);
1006 uni_print_ie_internal(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx);
1007 }
1008 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1009 uni_print_entry(cx, "attr", "(");
1010 for (i = 0; i < ie->u.attr.nattr; i++) {
1011 uni_printf(cx, "(%u", ie->u.attr.attr[i][0]);
1012 if (!(ie->u.attr.attr[i][0] & 0x80)) {
1013 uni_printf(cx, ",%u", ie->u.attr.attr[i][1]);
1014 if (!(ie->u.attr.attr[i][1] & 0x80))
1015 uni_printf(cx, ",%u",
1016 ie->u.attr.attr[i][2]);
1017 }
1018 uni_putc(')', cx);
1019 }
1020 }
1021
1022 uni_print_ieend(cx);
1023 }
1024
1025 DEF_IE_PRINT(itu, cause)
1026 {
1027 print_cause(cx, ie, itu_causes, NULL);
1028 }
1029 DEF_IE_PRINT(net, cause)
1030 {
1031 print_cause(cx, ie, net_causes, itu_causes);
1032 }
1033
1034 const char *
1035 uni_ie_cause2str(enum uni_coding coding, u_int cause)
1036 {
1037 if (cause < 128) {
1038 if (coding == UNI_CODING_ITU)
1039 return (itu_causes[cause].str);
1040 if (coding == UNI_CODING_NET) {
1041 if (net_causes[cause].str != NULL)
1042 return (net_causes[cause].str);
1043 return (itu_causes[cause].str);
1044 }
1045 }
1046 return (NULL);
1047 }
1048
1049 /**********************************************************************/
1050
1051 static int
1052 check_cause(struct uni_ie_cause *ie, struct unicx *cx,
1053 const struct causetab *tab1, const struct causetab *tab2)
1054 {
1055 static const u_int mask =
1056 UNI_CAUSE_COND_P | UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P |
1057 UNI_CAUSE_REJ_IE_P | UNI_CAUSE_IE_P | UNI_CAUSE_TRAFFIC_P |
1058 UNI_CAUSE_VPCI_P | UNI_CAUSE_MTYPE_P | UNI_CAUSE_TIMER_P |
1059 UNI_CAUSE_TNS_P | UNI_CAUSE_NUMBER_P | UNI_CAUSE_ATTR_P |
1060 UNI_CAUSE_PARAM_P;
1061
1062 const struct causetab *ptr;
1063
1064 if ((int)ie->cause >= 128)
1065 return (-1);
1066
1067 switch (ie->loc) {
1068 default:
1069 return (-1);
1070
1071 case UNI_CAUSE_LOC_USER:
1072 case UNI_CAUSE_LOC_PRIVLOC:
1073 case UNI_CAUSE_LOC_PUBLOC:
1074 case UNI_CAUSE_LOC_TRANSIT:
1075 case UNI_CAUSE_LOC_PUBREM:
1076 case UNI_CAUSE_LOC_PRIVREM:
1077 case UNI_CAUSE_LOC_INTERNAT:
1078 case UNI_CAUSE_LOC_BEYOND:
1079 break;
1080 }
1081
1082 if (tab1[ie->cause].str != NULL)
1083 ptr = &tab1[ie->cause];
1084 else if (tab2 != NULL && tab2[ie->cause].str != NULL)
1085 ptr = &tab2[ie->cause];
1086 else
1087 return (cx->cause_hard ? -1 : 0);
1088
1089 switch (ptr->diag) {
1090
1091 case UNI_DIAG_NONE:
1092 switch (ie->h.present & mask) {
1093 default:
1094 if (cx->cause_hard)
1095 return (-1);
1096 break;
1097
1098 case 0:
1099 break;
1100 }
1101 break;
1102
1103 case UNI_DIAG_COND:
1104 switch (ie->h.present & mask) {
1105 default:
1106 if (cx->cause_hard)
1107 return (-1);
1108 break;
1109
1110 case 0:
1111 case UNI_CAUSE_COND_P:
1112 break;
1113 }
1114 break;
1115
1116 case UNI_DIAG_REJ:
1117 switch (ie->h.present & mask) {
1118 default:
1119 if (cx->cause_hard)
1120 return (-1);
1121 break;
1122
1123 case 0:
1124 case UNI_CAUSE_REJ_P:
1125 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1126 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1127 break;
1128 }
1129 break;
1130
1131 case UNI_DIAG_CRATE:
1132 switch (ie->h.present & mask) {
1133 default:
1134 if (cx->cause_hard)
1135 return (-1);
1136 break;
1137
1138 case 0:
1139 case UNI_CAUSE_TRAFFIC_P:
1140 break;
1141 }
1142 break;
1143
1144 case UNI_DIAG_IE:
1145 switch (ie->h.present & mask) {
1146 default:
1147 if (cx->cause_hard)
1148 return (-1);
1149 break;
1150
1151 case 0:
1152 case UNI_CAUSE_IE_P:
1153 break;
1154 }
1155 break;
1156
1157 case UNI_DIAG_CHANID:
1158 switch (ie->h.present & mask) {
1159 default:
1160 if (cx->cause_hard)
1161 return (-1);
1162 break;
1163
1164 case 0:
1165 case UNI_CAUSE_VPCI_P:
1166 break;
1167 }
1168 break;
1169
1170 case UNI_DIAG_MTYPE:
1171 switch (ie->h.present & mask) {
1172 default:
1173 if (cx->cause_hard)
1174 return (-1);
1175 break;
1176
1177 case 0:
1178 case UNI_CAUSE_MTYPE_P:
1179 break;
1180 }
1181 break;
1182
1183 case UNI_DIAG_TIMER:
1184 switch (ie->h.present & mask) {
1185 default:
1186 if (cx->cause_hard)
1187 return (-1);
1188 break;
1189
1190 case 0:
1191 case UNI_CAUSE_TIMER_P:
1192 break;
1193 }
1194 break;
1195
1196 case UNI_DIAG_TNS:
1197 switch (ie->h.present & mask) {
1198 default:
1199 if (cx->cause_hard)
1200 return (-1);
1201 break;
1202
1203 case 0:
1204 case UNI_CAUSE_TNS_P:
1205 break;
1206 }
1207 break;
1208
1209 case UNI_DIAG_NUMBER:
1210 switch (ie->h.present & mask) {
1211 default:
1212 if (cx->cause_hard)
1213 return (-1);
1214 break;
1215
1216 case 0:
1217 case UNI_CAUSE_NUMBER_P:
1218 break;
1219 }
1220 break;
1221
1222 case UNI_DIAG_ATTR:
1223 switch (ie->h.present & mask) {
1224 default:
1225 if (cx->cause_hard)
1226 return (-1);
1227 break;
1228
1229 case 0:
1230 case UNI_CAUSE_ATTR_P:
1231 break;
1232 }
1233 break;
1234
1235 case UNI_DIAG_PARAM:
1236 switch (ie->h.present & mask) {
1237 default:
1238 if (cx->cause_hard)
1239 return (-1);
1240 break;
1241
1242 case 0:
1243 case UNI_CAUSE_PARAM_P:
1244 break;
1245 }
1246 break;
1247 }
1248
1249 if (ie->h.present & UNI_CAUSE_COND_P) {
1250 switch (ie->u.cond.pu) {
1251 default:
1252 return (-1);
1253
1254 case UNI_CAUSE_PU_PROVIDER:
1255 case UNI_CAUSE_PU_USER:
1256 break;
1257 }
1258 switch (ie->u.cond.na) {
1259 default:
1260 return (-1);
1261
1262 case UNI_CAUSE_NA_NORMAL:
1263 case UNI_CAUSE_NA_ABNORMAL:
1264 break;
1265 }
1266 switch (ie->u.cond.cond) {
1267 default:
1268 return (-1);
1269
1270 case UNI_CAUSE_COND_UNKNOWN:
1271 case UNI_CAUSE_COND_PERM:
1272 case UNI_CAUSE_COND_TRANS:
1273 break;
1274 }
1275 }
1276 if (ie->h.present & UNI_CAUSE_REJ_P) {
1277 switch (ie->u.rej.reason) {
1278 default:
1279 return (-1);
1280
1281 case UNI_CAUSE_REASON_USER:
1282 switch (ie->h.present & mask) {
1283 default:
1284 return (-1);
1285
1286 case UNI_CAUSE_REJ_P:
1287 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_USER_P:
1288 break;
1289 }
1290 break;
1291
1292 case UNI_CAUSE_REASON_IEMISS:
1293 case UNI_CAUSE_REASON_IESUFF:
1294 switch (ie->h.present & mask) {
1295 default:
1296 return (-1);
1297
1298 case UNI_CAUSE_REJ_P:
1299 case UNI_CAUSE_REJ_P | UNI_CAUSE_REJ_IE_P:
1300 break;
1301 }
1302 break;
1303 }
1304 }
1305 if (ie->h.present & UNI_CAUSE_IE_P) {
1306 if (ie->u.ie.len == 0 || ie->u.ie.len > UNI_CAUSE_IE_N)
1307 return (-1);
1308 }
1309 if (ie->h.present & UNI_CAUSE_TRAFFIC_P) {
1310 if (ie->u.traffic.len == 0 ||
1311 ie->u.traffic.len > UNI_CAUSE_TRAFFIC_N)
1312 return (-1);
1313 }
1314
1315 if (ie->h.present & UNI_CAUSE_TNS_P) {
1316 if (uni_check_ie(UNI_IE_TNS, (union uni_ieall *)&ie->u.tns, cx))
1317 return (-1);
1318 }
1319 if (ie->h.present & UNI_CAUSE_NUMBER_P) {
1320 if(uni_check_ie(UNI_IE_CALLED, (union uni_ieall *)&ie->u.number, cx))
1321 return (-1);
1322 }
1323 if (ie->h.present & UNI_CAUSE_ATTR_P) {
1324 if(ie->u.attr.nattr > UNI_CAUSE_ATTR_N || ie->u.attr.nattr == 0)
1325 return (-1);
1326 }
1327 if (ie->h.present & UNI_CAUSE_PARAM_P) {
1328 UNUSED(cx);
1329 }
1330
1331 return (0);
1332 }
1333
1334 DEF_IE_CHECK(itu, cause)
1335 {
1336 return (check_cause(ie, cx, itu_causes, NULL));
1337 }
1338 DEF_IE_CHECK(net, cause)
1339 {
1340 return (check_cause(ie, cx, net_causes, itu_causes));
1341 }
1342 /**********************************************************************/
1343
1344 static int
1345 encode_cause(struct uni_msg *msg, struct uni_ie_cause *ie, struct unicx *cx)
1346 {
1347 u_int i;
1348
1349 START_IE(cause, UNI_IE_CAUSE, 30);
1350
1351 if (IE_ISERROR(*ie)) {
1352 APP_BYTE(msg, 0x00 | ie->loc);
1353 } else {
1354 APP_BYTE(msg, 0x80 | ie->loc);
1355 }
1356 APP_BYTE(msg, 0x80 | ie->cause);
1357
1358 if (ie->h.present & UNI_CAUSE_COND_P)
1359 APP_BYTE(msg, 0x80 | (ie->u.cond.pu << 3) |
1360 (ie->u.cond.na << 2) | ie->u.cond.cond);
1361
1362 else if (ie->h.present & UNI_CAUSE_REJ_P) {
1363 APP_BYTE(msg, 0x80 | (ie->u.rej.reason << 2) | ie->u.rej.cond);
1364 if (ie->h.present & UNI_CAUSE_REJ_USER_P)
1365 APP_BYTE(msg, ie->u.rej.user);
1366 else if (ie->h.present & UNI_CAUSE_REJ_IE_P)
1367 APP_BYTE(msg, ie->u.rej.ie);
1368
1369 } else if(ie->h.present & UNI_CAUSE_IE_P)
1370 APP_BUF(msg, ie->u.ie.ie, ie->u.ie.len);
1371
1372 else if (ie->h.present & UNI_CAUSE_TRAFFIC_P)
1373 APP_BUF(msg, ie->u.traffic.traffic, ie->u.traffic.len);
1374
1375 else if (ie->h.present & UNI_CAUSE_VPCI_P) {
1376 APP_BYTE(msg, (ie->u.vpci.vpci >> 8));
1377 APP_BYTE(msg, (ie->u.vpci.vpci >> 0));
1378 APP_BYTE(msg, (ie->u.vpci.vci >> 8));
1379 APP_BYTE(msg, (ie->u.vpci.vci >> 0));
1380
1381 } else if (ie->h.present & UNI_CAUSE_MTYPE_P)
1382 APP_BYTE(msg, ie->u.mtype);
1383
1384 else if (ie->h.present & UNI_CAUSE_TIMER_P) {
1385 APP_BYTE(msg, ie->u.timer[0]);
1386 APP_BYTE(msg, ie->u.timer[1]);
1387 APP_BYTE(msg, ie->u.timer[2]);
1388
1389 } else if (ie->h.present & UNI_CAUSE_TNS_P)
1390 uni_encode_ie(UNI_IE_TNS, msg,
1391 (union uni_ieall *)&ie->u.tns, cx);
1392
1393 else if (ie->h.present & UNI_CAUSE_NUMBER_P)
1394 uni_encode_ie(UNI_IE_CALLED, msg,
1395 (union uni_ieall *)&ie->u.number, cx);
1396
1397 else if (ie->h.present & UNI_CAUSE_ATTR_P) {
1398 for (i = 0; i < ie->u.attr.nattr; i++) {
1399 APP_BYTE(msg, ie->u.attr.attr[i][0]);
1400 if (!ie->u.attr.attr[i][0]) {
1401 APP_BYTE(msg, ie->u.attr.attr[i][1]);
1402 if (!ie->u.attr.attr[i][1])
1403 APP_BYTE(msg, ie->u.attr.attr[i][2]);
1404 }
1405 }
1406 } else if (ie->h.present & UNI_CAUSE_PARAM_P)
1407 APP_BYTE(msg, ie->u.param);
1408
1409 SET_IE_LEN(msg);
1410
1411 return (0);
1412 }
1413
1414 DEF_IE_ENCODE(itu, cause)
1415 {
1416 return encode_cause(msg, ie, cx);
1417 }
1418 DEF_IE_ENCODE(net, cause)
1419 {
1420 return encode_cause(msg, ie, cx);
1421 }
1422
1423 /**********************************************************************/
1424
1425 static int
1426 decode_cause(struct uni_ie_cause *ie, struct uni_msg *msg, u_int ielen,
1427 struct unicx *cx, const struct causetab *tab1, const struct causetab *tab2)
1428 {
1429 u_char c;
1430 const struct causetab *ptr;
1431 enum uni_ietype ietype;
1432 u_int xielen;
1433
1434 IE_START(;);
1435
1436 if(ielen < 2 || ielen > 30)
1437 goto rej;
1438
1439 c = *msg->b_rptr++;
1440 ielen--;
1441 if(!(c & 0x80))
1442 goto rej;
1443 ie->loc = c & 0xf;
1444
1445 c = *msg->b_rptr++;
1446 ielen--;
1447 if(!(c & 0x80))
1448 goto rej;
1449 ie->cause = c & 0x7f;
1450
1451 if(tab1[ie->cause].str != NULL)
1452 ptr = &tab1[ie->cause];
1453 else if(tab2 != NULL && tab2[ie->cause].str != NULL)
1454 ptr = &tab2[ie->cause];
1455 else {
1456 ptr = NULL;
1457 ielen = 0; /* ignore diags */
1458 }
1459
1460 if(ielen) {
1461 switch(ptr->diag) {
1462
1463 case UNI_DIAG_NONE:
1464 break;
1465
1466 case UNI_DIAG_COND:
1467 if(ielen < 1)
1468 goto rej;
1469 c = *msg->b_rptr++;
1470 ielen--;
1471
1472 ie->h.present |= UNI_CAUSE_COND_P;
1473 ie->u.cond.pu = (c >> 3) & 1;
1474 ie->u.cond.na = (c >> 2) & 1;
1475 ie->u.cond.cond = c & 3;
1476
1477 if(!(c & 0x80))
1478 goto rej;
1479 break;
1480
1481 case UNI_DIAG_REJ:
1482 if(ielen < 1)
1483 goto rej;
1484 c = *msg->b_rptr++;
1485 ielen--;
1486
1487 ie->h.present |= UNI_CAUSE_REJ_P;
1488 ie->u.rej.reason = (c >> 2) & 0x1f;
1489 ie->u.rej.cond = c & 3;
1490
1491 if(!(c & 0x80))
1492 goto rej;
1493
1494 if(ielen > 0) {
1495 c = *msg->b_rptr++;
1496 ielen--;
1497
1498 switch(ie->u.rej.reason) {
1499
1500 case UNI_CAUSE_REASON_USER:
1501 ie->h.present |= UNI_CAUSE_REJ_USER_P;
1502 ie->u.rej.user = c;
1503 break;
1504
1505 case UNI_CAUSE_REASON_IEMISS:
1506 case UNI_CAUSE_REASON_IESUFF:
1507 ie->h.present |= UNI_CAUSE_REJ_IE_P;
1508 ie->u.rej.ie = c;
1509 break;
1510 }
1511 }
1512 break;
1513
1514 case UNI_DIAG_CRATE:
1515 ie->h.present |= UNI_CAUSE_TRAFFIC_P;
1516 while(ielen && ie->u.traffic.len < UNI_CAUSE_TRAFFIC_N) {
1517 ie->u.traffic.traffic[ie->u.traffic.len++] =
1518 *msg->b_rptr++;
1519 ielen--;
1520 }
1521 break;
1522
1523 case UNI_DIAG_IE:
1524 ie->h.present |= UNI_CAUSE_IE_P;
1525 while(ielen && ie->u.ie.len < UNI_CAUSE_IE_N) {
1526 ie->u.ie.ie[ie->u.ie.len++] = *msg->b_rptr++;
1527 ielen--;
1528 }
1529 break;
1530
1531 case UNI_DIAG_CHANID:
1532 if(ielen < 4)
1533 break;
1534 ie->h.present |= UNI_CAUSE_VPCI_P;
1535 ie->u.vpci.vpci = *msg->b_rptr++ << 8;
1536 ie->u.vpci.vpci |= *msg->b_rptr++;
1537 ie->u.vpci.vci = *msg->b_rptr++ << 8;
1538 ie->u.vpci.vci |= *msg->b_rptr++;
1539 ielen -= 4;
1540 break;
1541
1542 case UNI_DIAG_MTYPE:
1543 ie->h.present |= UNI_CAUSE_MTYPE_P;
1544 ie->u.mtype = *msg->b_rptr++;
1545 ielen--;
1546 break;
1547
1548 case UNI_DIAG_TIMER:
1549 if(ielen < 3)
1550 break;
1551 ie->h.present |= UNI_CAUSE_TIMER_P;
1552 ie->u.timer[0] = *msg->b_rptr++;
1553 ie->u.timer[1] = *msg->b_rptr++;
1554 ie->u.timer[2] = *msg->b_rptr++;
1555 ielen -= 3;
1556 break;
1557
1558 case UNI_DIAG_TNS:
1559 if(ielen < 4)
1560 break;
1561 if(uni_decode_ie_hdr(&ietype, &ie->u.tns.h, msg, cx, &xielen))
1562 break;
1563 if(ietype != UNI_IE_TNS)
1564 break;
1565 if(uni_decode_ie_body(ietype,
1566 (union uni_ieall *)&ie->u.tns, msg, xielen, cx))
1567 break;
1568 ie->h.present |= UNI_CAUSE_TNS_P;
1569 break;
1570
1571 case UNI_DIAG_NUMBER:
1572 if(ielen < 4)
1573 break;
1574 if(uni_decode_ie_hdr(&ietype, &ie->u.number.h, msg, cx, &xielen))
1575 break;
1576 if(ietype != UNI_IE_CALLED)
1577 break;
1578 if(uni_decode_ie_body(ietype,
1579 (union uni_ieall *)&ie->u.number, msg, xielen, cx))
1580 break;
1581 ie->h.present |= UNI_CAUSE_NUMBER_P;
1582 break;
1583
1584 case UNI_DIAG_ATTR:
1585 ie->h.present |= UNI_CAUSE_ATTR_P;
1586 while(ielen > 0 && ie->u.attr.nattr < UNI_CAUSE_ATTR_N) {
1587 c = *msg->b_rptr++;
1588 ie->u.attr.attr[ie->u.attr.nattr][0] = c;
1589 ielen--;
1590 if(ielen > 0 && !(c & 0x80)) {
1591 c = *msg->b_rptr++;
1592 ie->u.attr.attr[ie->u.attr.nattr][1] = c;
1593 ielen--;
1594 if(ielen > 0 && !(c & 0x80)) {
1595 c = *msg->b_rptr++;
1596 ie->u.attr.attr[ie->u.attr.nattr][2] = c;
1597 ielen--;
1598 }
1599 }
1600 }
1601 break;
1602
1603 case UNI_DIAG_PARAM:
1604 ie->h.present |= UNI_CAUSE_PARAM_P;
1605 ie->u.param = *msg->b_rptr++;
1606 ielen--;
1607 break;
1608 }
1609 }
1610
1611 IE_END(CAUSE);
1612 }
1613
1614 DEF_IE_DECODE(itu, cause)
1615 {
1616 return decode_cause(ie, msg, ielen, cx, itu_causes, NULL);
1617 }
1618 DEF_IE_DECODE(net, cause)
1619 {
1620 return decode_cause(ie, msg, ielen, cx, net_causes, itu_causes);
1621 }
1622
1623 /*********************************************************************
1624 *
1625 * Callstate
1626 *
1627 * References for this IE are:
1628 *
1629 * Q.2931 pp. 59...60
1630 * UNI4.0 pp. 14
1631 *
1632 * Only ITU-T coding allowed.
1633 */
1634 DEF_IE_PRINT(itu, callstate)
1635 {
1636 static const struct uni_print_tbl tbl[] = {
1637 MKT(UNI_CALLSTATE_U0, U0/N0/REST0),
1638 MKT(UNI_CALLSTATE_U1, U1/N1),
1639 MKT(UNI_CALLSTATE_U3, U3/N3),
1640 MKT(UNI_CALLSTATE_U4, U4/N4),
1641 MKT(UNI_CALLSTATE_U6, U6/N6),
1642 MKT(UNI_CALLSTATE_U7, U7/N7),
1643 MKT(UNI_CALLSTATE_U8, U8/N8),
1644 MKT(UNI_CALLSTATE_U9, U9/N9),
1645 MKT(UNI_CALLSTATE_U10, U10/N10),
1646 MKT(UNI_CALLSTATE_U11, U11/N11),
1647 MKT(UNI_CALLSTATE_U12, U12/N12),
1648 MKT(UNI_CALLSTATE_REST1,REST1),
1649 MKT(UNI_CALLSTATE_REST2,REST2),
1650 MKT(UNI_CALLSTATE_U13, U13/N13),
1651 MKT(UNI_CALLSTATE_U14, U14/N14),
1652 EOT()
1653 };
1654
1655 if(uni_print_iehdr("callstate", &ie->h, cx))
1656 return;
1657 uni_print_tbl("state", ie->state, tbl, cx);
1658 uni_print_ieend(cx);
1659 }
1660
1661 DEF_IE_CHECK(itu, callstate)
1662 {
1663 UNUSED(cx);
1664
1665 switch(ie->state) {
1666 default:
1667 return -1;
1668
1669 case UNI_CALLSTATE_U0:
1670 case UNI_CALLSTATE_U1:
1671 case UNI_CALLSTATE_U3:
1672 case UNI_CALLSTATE_U4:
1673 case UNI_CALLSTATE_U6:
1674 case UNI_CALLSTATE_U7:
1675 case UNI_CALLSTATE_U8:
1676 case UNI_CALLSTATE_U9:
1677 case UNI_CALLSTATE_U10:
1678 case UNI_CALLSTATE_U11:
1679 case UNI_CALLSTATE_U12:
1680 case UNI_CALLSTATE_REST1:
1681 case UNI_CALLSTATE_REST2:
1682 case UNI_CALLSTATE_U13:
1683 case UNI_CALLSTATE_U14:
1684 break;
1685 }
1686
1687 return 0;
1688 }
1689
1690 DEF_IE_ENCODE(itu, callstate)
1691 {
1692 START_IE(callstate, UNI_IE_CALLSTATE, 1);
1693
1694 APP_BYTE(msg, ie->state);
1695
1696 SET_IE_LEN(msg);
1697 return 0;
1698 }
1699
1700 DEF_IE_DECODE(itu, callstate)
1701 {
1702 IE_START(;);
1703
1704 if(ielen != 1)
1705 goto rej;
1706
1707 ie->state = *msg->b_rptr++ & 0x3f;
1708 ielen--;
1709
1710 IE_END(CALLSTATE);
1711 }
1712
1713 /*********************************************************************
1714 *
1715 * Facility Information.
1716 *
1717 * References for this IE are:
1718 *
1719 * Q.2932.1
1720 *
1721 * The standard allows only ROSE as protocol. We allow everything up to the
1722 * maximum size.
1723 *
1724 * Only ITU-T coding allowed.
1725 */
1726 DEF_IE_PRINT(itu, facility)
1727 {
1728 u_int i;
1729
1730 if(uni_print_iehdr("facility", &ie->h, cx))
1731 return;
1732
1733 if(ie->proto == UNI_FACILITY_ROSE)
1734 uni_print_entry(cx, "proto", "rose");
1735 else
1736 uni_print_entry(cx, "proto", "0x%02x", ie->proto);
1737
1738 uni_print_entry(cx, "len", "%u", ie->len);
1739 uni_print_entry(cx, "info", "(");
1740 for(i = 0; i < ie->len; i++)
1741 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->apdu[i]);
1742 uni_printf(cx, ")");
1743
1744 uni_print_ieend(cx);
1745 }
1746
1747 DEF_IE_CHECK(itu, facility)
1748 {
1749 UNUSED(cx);
1750
1751 if(ie->len > UNI_FACILITY_MAXAPDU)
1752 return -1;
1753
1754 return 0;
1755 }
1756
1757 DEF_IE_ENCODE(itu, facility)
1758 {
1759 START_IE(facility, UNI_IE_FACILITY, 1 + ie->len);
1760
1761 APP_BYTE(msg, ie->proto | 0x80);
1762 APP_BUF(msg, ie->apdu, ie->len);
1763
1764 SET_IE_LEN(msg);
1765 return 0;
1766 }
1767
1768 DEF_IE_DECODE(itu, facility)
1769 {
1770 u_char c;
1771
1772 IE_START(;);
1773
1774 if(ielen > UNI_FACILITY_MAXAPDU + 1 || ielen < 1)
1775 goto rej;
1776
1777 ie->proto = (c = *msg->b_rptr++) & 0x1f;
1778 ielen--;
1779 if((c & 0xe0) != 0x80)
1780 goto rej;
1781
1782 ie->len = ielen;
1783 ielen = 0;
1784 (void)memcpy(ie->apdu, msg->b_rptr, ie->len);
1785 msg->b_rptr += ie->len;
1786
1787 IE_END(FACILITY);
1788 }
1789
1790 /*********************************************************************
1791 *
1792 * Notification Indicator
1793 *
1794 * References for this IE are:
1795 *
1796 * Q.2931 p. 76
1797 * UNI4.0 p. 17
1798 *
1799 * Only ITU-T coding allowed.
1800 */
1801
1802 DEF_IE_PRINT(itu, notify)
1803 {
1804 u_int i;
1805
1806 if(uni_print_iehdr("notify", &ie->h, cx))
1807 return;
1808 uni_print_entry(cx, "len", "%u", ie->len);
1809 uni_print_entry(cx, "info", "(");
1810 for(i = 0; i < ie->len; i++)
1811 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->notify[i]);
1812 uni_printf(cx, ")");
1813 uni_print_ieend(cx);
1814 }
1815
1816 DEF_IE_CHECK(itu, notify)
1817 {
1818 UNUSED(cx);
1819
1820 if(ie->len > UNI_NOTIFY_MAXLEN)
1821 return -1;
1822
1823 return 0;
1824 }
1825
1826 DEF_IE_ENCODE(itu, notify)
1827 {
1828 START_IE(notify, UNI_IE_NOTIFY, ie->len);
1829
1830 APP_BUF(msg, ie->notify, ie->len);
1831 if (IE_ISERROR(*ie)) {
1832 /* make it too long */
1833 u_int i = ie->len;
1834
1835 while (i < UNI_NOTIFY_MAXLEN + 1) {
1836 APP_BYTE(msg, 0x00);
1837 i++;
1838 }
1839 }
1840
1841 SET_IE_LEN(msg);
1842 return (0);
1843 }
1844
1845 DEF_IE_DECODE(itu, notify)
1846 {
1847 IE_START(;);
1848
1849 if (ielen > UNI_NOTIFY_MAXLEN || ielen < 1)
1850 goto rej;
1851
1852 ie->len = ielen;
1853 ielen = 0;
1854 (void)memcpy(ie->notify, msg->b_rptr, ie->len);
1855 msg->b_rptr += ie->len;
1856
1857 IE_END(NOTIFY);
1858 }
1859
1860 /*********************************************************************
1861 *
1862 * End-to-end transit delay.
1863 *
1864 * References for this IE are:
1865 *
1866 * Q.2931 pp. 70...71
1867 * UNI4.0 pp. 69...70
1868 * PNNI1.0 pp. 198...200
1869 *
1870 * Not clear, whether the new indicator should be used with NET coding or
1871 * not.
1872 *
1873 * Only ITU-T coding allowed.
1874 */
1875
1876 static void
1877 print_eetd(struct uni_ie_eetd *ie, struct unicx *cx)
1878 {
1879 if (uni_print_iehdr("eetd", &ie->h, cx))
1880 return;
1881
1882 if (ie->h.present & UNI_EETD_CUM_P)
1883 uni_print_entry(cx, "cum", "%u", ie->cumulative);
1884 if (ie->h.present & UNI_EETD_MAX_P) {
1885 if (ie->maximum == UNI_EETD_ANYMAX)
1886 uni_print_entry(cx, "max", "any");
1887 else
1888 uni_print_entry(cx, "max", "%u", ie->maximum);
1889 }
1890 if (ie->h.present & UNI_EETD_PCTD_P)
1891 uni_print_entry(cx, "pnni_cum", "%u", ie->pctd);
1892 if (ie->h.present & UNI_EETD_PMTD_P)
1893 uni_print_entry(cx, "pnni_max", "%u", ie->pmtd);
1894 if (ie->h.present & UNI_EETD_NET_P)
1895 uni_print_flag("netgen", cx);
1896
1897 uni_print_ieend(cx);
1898 }
1899 DEF_IE_PRINT(itu, eetd)
1900 {
1901 print_eetd(ie, cx);
1902 }
1903 DEF_IE_PRINT(net, eetd)
1904 {
1905 print_eetd(ie, cx);
1906 }
1907
1908 DEF_IE_CHECK(itu, eetd)
1909 {
1910
1911 UNUSED(cx);
1912
1913 if (!(ie->h.present & UNI_EETD_CUM_P))
1914 return (-1);
1915 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1916 return (-1);
1917 return (0);
1918 }
1919
1920 DEF_IE_CHECK(net, eetd)
1921 {
1922
1923 if (!cx->pnni) {
1924 if (!(ie->h.present & UNI_EETD_CUM_P))
1925 return (-1);
1926 if (ie->h.present & (UNI_EETD_PMTD_P | UNI_EETD_PCTD_P))
1927 return (-1);
1928 } else {
1929 if (ie->h.present & UNI_EETD_MAX_P)
1930 return (-1);
1931 if ((ie->h.present & UNI_EETD_CUM_P) &&
1932 (ie->h.present & UNI_EETD_PCTD_P))
1933 return (-1);
1934 }
1935 return (0);
1936 }
1937
1938 DEF_IE_ENCODE(itu, eetd)
1939 {
1940 START_IE(eetd, UNI_IE_EETD, 9);
1941
1942 if (ie->h.present & UNI_EETD_CUM_P) {
1943 APP_BYTE(msg, UNI_EETD_CTD_ID);
1944 APP_16BIT(msg, ie->cumulative);
1945 }
1946 if (ie->h.present & UNI_EETD_MAX_P) {
1947 APP_BYTE(msg, UNI_EETD_MTD_ID);
1948 APP_16BIT(msg, ie->maximum);
1949 }
1950 if (ie->h.present & UNI_EETD_PMTD_P) {
1951 APP_BYTE(msg, UNI_EETD_PMTD_ID);
1952 APP_24BIT(msg, ie->pmtd);
1953 }
1954 if (ie->h.present & UNI_EETD_PCTD_P) {
1955 APP_BYTE(msg, UNI_EETD_PCTD_ID);
1956 APP_24BIT(msg, ie->pctd);
1957 }
1958 if (ie->h.present & UNI_EETD_NET_P) {
1959 APP_BYTE(msg, UNI_EETD_NET_ID);
1960 }
1961
1962 SET_IE_LEN(msg);
1963 return (0);
1964 }
1965
1966 DEF_IE_ENCODE(net, eetd)
1967 {
1968 return (uni_ie_encode_itu_eetd(msg, ie, cx));
1969 }
1970
1971 DEF_IE_DECODE(itu, eetd)
1972 {
1973 IE_START(;);
1974
1975 while (ielen > 0) {
1976 switch (ielen--, *msg->b_rptr++) {
1977
1978 case UNI_EETD_CTD_ID:
1979 if (ielen < 2)
1980 goto rej;
1981 ie->h.present |= UNI_EETD_CUM_P;
1982 ie->cumulative = *msg->b_rptr++ << 8;
1983 ie->cumulative |= *msg->b_rptr++;
1984 ielen -= 2;
1985 break;
1986
1987 case UNI_EETD_MTD_ID:
1988 if (ielen < 2)
1989 goto rej;
1990 ie->h.present |= UNI_EETD_MAX_P;
1991 ie->maximum = *msg->b_rptr++ << 8;
1992 ie->maximum |= *msg->b_rptr++;
1993 ielen -= 2;
1994 break;
1995
1996 case UNI_EETD_PCTD_ID:
1997 if (ielen < 3)
1998 goto rej;
1999 ie->h.present |= UNI_EETD_PCTD_P;
2000 ie->pctd = *msg->b_rptr++ << 16;
2001 ie->pctd |= *msg->b_rptr++ << 8;
2002 ie->pctd |= *msg->b_rptr++;
2003 ielen -= 3;
2004 break;
2005
2006 case UNI_EETD_PMTD_ID:
2007 if (ielen < 3)
2008 goto rej;
2009 ie->h.present |= UNI_EETD_PMTD_P;
2010 ie->pmtd = *msg->b_rptr++ << 16;
2011 ie->pmtd |= *msg->b_rptr++ << 8;
2012 ie->pmtd |= *msg->b_rptr++;
2013 ielen -= 3;
2014 break;
2015
2016 case UNI_EETD_NET_ID:
2017 ie->h.present |= UNI_EETD_NET_P;
2018 break;
2019
2020 default:
2021 goto rej;
2022 }
2023 }
2024
2025 IE_END(EETD);
2026 }
2027 DEF_IE_DECODE(net, eetd)
2028 {
2029 return (uni_ie_decode_itu_eetd(ie, msg, ielen, cx));
2030 }
2031
2032 /*********************************************************************
2033 *
2034 * Called address
2035 * Called subaddress
2036 * Calling address
2037 * Calling subaddress
2038 * Connected address
2039 * Connected subaddress
2040 *
2041 * References for this IE are:
2042 *
2043 * Q.2931 pp. 60...68
2044 * ...A4 pp. 27...36
2045 * UNI4.0 pp. 14...15
2046 * Q.2951 pp. 28...40
2047 *
2048 * It is assumed, that the coding of the addr arrays is ok.
2049 *
2050 * Only ITU-T coding allowed.
2051 */
2052
2053 static const struct uni_print_tbl screen_tbl[] = {
2054 MKT(UNI_ADDR_SCREEN_NOT, no),
2055 MKT(UNI_ADDR_SCREEN_PASSED, passed),
2056 MKT(UNI_ADDR_SCREEN_FAILED, failed),
2057 MKT(UNI_ADDR_SCREEN_NET, network),
2058 EOT()
2059 };
2060 static const struct uni_print_tbl pres_tbl[] = {
2061 MKT(UNI_ADDR_PRES, allowed),
2062 MKT(UNI_ADDR_RESTRICT, restricted),
2063 MKT(UNI_ADDR_NONUMBER, no-number),
2064 EOT()
2065 };
2066
2067
2068 static void
2069 print_addr(struct unicx *cx, struct uni_addr *addr)
2070 {
2071 static const struct uni_print_tbl plan_tbl[] = {
2072 MKT(UNI_ADDR_UNKNOWN, unknown),
2073 MKT(UNI_ADDR_E164, E164),
2074 MKT(UNI_ADDR_ATME, ATME),
2075 MKT(UNI_ADDR_DATA, data),
2076 MKT(UNI_ADDR_PRIVATE, private),
2077 EOT()
2078 };
2079 static const struct uni_print_tbl type_tbl[] = {
2080 MKT(UNI_ADDR_UNKNOWN, unknown),
2081 MKT(UNI_ADDR_INTERNATIONAL, international),
2082 MKT(UNI_ADDR_NATIONAL, national),
2083 MKT(UNI_ADDR_NETWORK, network),
2084 MKT(UNI_ADDR_SUBSCR, subscriber),
2085 MKT(UNI_ADDR_ABBR, abbreviated),
2086 EOT()
2087 };
2088 u_int i;
2089
2090 uni_print_entry(cx, "addr", "(");
2091 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2092 uni_putc(',', cx);
2093 uni_print_tbl(NULL, addr->plan, plan_tbl, cx);
2094 uni_putc(',', cx);
2095 if(addr->plan == UNI_ADDR_E164) {
2096 uni_putc('"', cx);
2097 for(i = 0; i < addr->len; i++) {
2098 if(addr->addr[i] < ' ')
2099 uni_printf(cx, "^%c", addr->addr[i] + '@');
2100 else if(addr->addr[i] <= '~')
2101 uni_putc(addr->addr[i], cx);
2102 else
2103 uni_printf(cx, "\\%03o", addr->addr[i]);
2104 }
2105 uni_putc('"', cx);
2106
2107 } else if(addr->plan == UNI_ADDR_ATME) {
2108 for(i = 0; i < addr->len; i++)
2109 uni_printf(cx, "%02x", addr->addr[i]);
2110 }
2111 uni_putc(')', cx);
2112 }
2113
2114 static void
2115 print_addrsub(struct unicx *cx, struct uni_subaddr *addr)
2116 {
2117 static const struct uni_print_tbl type_tbl[] = {
2118 MKT(UNI_SUBADDR_NSAP, NSAP),
2119 MKT(UNI_SUBADDR_ATME, ATME),
2120 MKT(UNI_SUBADDR_USER, USER),
2121 EOT()
2122 };
2123 u_int i;
2124
2125 uni_print_entry(cx, "addr", "(");
2126 uni_print_tbl(NULL, addr->type, type_tbl, cx);
2127 uni_putc(',', cx);
2128
2129 for(i = 0; i < addr->len; i++)
2130 uni_printf(cx, "%02x", addr->addr[i]);
2131
2132 uni_putc(')', cx);
2133 }
2134
2135 static int
2136 check_addr(struct uni_addr *addr)
2137 {
2138 u_int i;
2139
2140 switch(addr->plan) {
2141 default:
2142 return -1;
2143
2144 case UNI_ADDR_E164:
2145 if(addr->type != UNI_ADDR_INTERNATIONAL)
2146 return -1;
2147 if(addr->len > 15 || addr->len == 0)
2148 return -1;
2149 for(i = 0; i < addr->len; i++)
2150 if(addr->addr[i] == 0 || (addr->addr[i] & 0x80))
2151 return -1;
2152 break;
2153
2154 case UNI_ADDR_ATME:
2155 if(addr->type != UNI_ADDR_UNKNOWN)
2156 return -1;
2157 if(addr->len != 20)
2158 return -1;
2159 break;
2160 }
2161
2162 return 0;
2163 }
2164
2165 static int
2166 check_subaddr(struct uni_subaddr *addr)
2167 {
2168 switch(addr->type) {
2169 default:
2170 return -1;
2171
2172 case UNI_SUBADDR_NSAP:
2173 if(addr->len != 20)
2174 return -1;
2175 break;
2176
2177 case UNI_SUBADDR_ATME:
2178 if(addr->len > 20)
2179 return -1;
2180 break;
2181 }
2182 return 0;
2183 }
2184
2185 static int
2186 check_screen(enum uni_addr_screen screen, enum uni_addr_pres pres)
2187 {
2188 switch(pres) {
2189 default:
2190 return -1;
2191
2192 case UNI_ADDR_PRES:
2193 case UNI_ADDR_RESTRICT:
2194 case UNI_ADDR_NONUMBER:
2195 break;
2196 }
2197 switch(screen) {
2198 default:
2199 return -1;
2200
2201 case UNI_ADDR_SCREEN_NOT:
2202 case UNI_ADDR_SCREEN_PASSED:
2203 case UNI_ADDR_SCREEN_FAILED:
2204 case UNI_ADDR_SCREEN_NET:
2205 break;
2206 }
2207
2208 return 0;
2209 }
2210
2211 static void
2212 encode_addr(struct uni_msg *msg, struct uni_addr *addr, u_int flag,
2213 enum uni_addr_screen screen, enum uni_addr_pres pres, int err)
2214 {
2215 u_char ext = err ? 0x00 : 0x80;
2216
2217 if (flag) {
2218 APP_BYTE(msg, (addr->type << 4) | addr->plan);
2219 APP_BYTE(msg, ext | (pres << 5) | (screen));
2220 } else {
2221 APP_BYTE(msg, ext | (addr->type << 4) | addr->plan);
2222 }
2223 APP_BUF(msg, addr->addr, addr->len);
2224 }
2225
2226 static void
2227 encode_subaddr(struct uni_msg *msg, struct uni_subaddr *addr)
2228 {
2229 APP_BYTE(msg, 0x80|(addr->type<<4));
2230 APP_BUF(msg, addr->addr, addr->len);
2231 }
2232
2233 static int
2234 decode_addr(struct uni_addr *addr, u_int ielen, struct uni_msg *msg, u_int plan)
2235 {
2236 addr->plan = plan & 0xf;
2237 addr->type = (plan >> 4) & 0x7;
2238
2239 switch(addr->plan) {
2240
2241 case UNI_ADDR_E164:
2242 if(ielen > 15 || ielen == 0)
2243 return -1;
2244 addr->addr[ielen] = 0;
2245 break;
2246
2247 case UNI_ADDR_ATME:
2248 if(ielen != 20)
2249 return -1;
2250 break;
2251
2252 default:
2253 return -1;
2254 }
2255 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2256 addr->len = ielen;
2257 msg->b_rptr += ielen;
2258
2259 return 0;
2260 }
2261
2262 static int
2263 decode_subaddr(struct uni_subaddr *addr, u_int ielen, struct uni_msg *msg,
2264 u_int type)
2265 {
2266 switch(addr->type = (type >> 4) & 0x7) {
2267
2268 case UNI_SUBADDR_NSAP:
2269 if(ielen == 0 || ielen > 20)
2270 return -1;
2271 break;
2272
2273 case UNI_SUBADDR_ATME:
2274 if(ielen != 20)
2275 return -1;
2276 break;
2277
2278 default:
2279 return -1;
2280 }
2281 if(!(type & 0x80))
2282 return -1;
2283 if((type & 0x7) != 0)
2284 return -1;
2285
2286 addr->len = ielen;
2287 (void)memcpy(addr->addr, msg->b_rptr, ielen);
2288 msg->b_rptr += ielen;
2289
2290 return 0;
2291 }
2292
2293 /**********************************************************************/
2294
2295 DEF_IE_PRINT(itu, called)
2296 {
2297 if (uni_print_iehdr("called", &ie->h, cx))
2298 return;
2299 print_addr(cx, &ie->addr);
2300 uni_print_ieend(cx);
2301 }
2302
2303 DEF_IE_CHECK(itu, called)
2304 {
2305 UNUSED(cx);
2306
2307 if (check_addr(&ie->addr))
2308 return (-1);
2309 return (0);
2310 }
2311
2312 DEF_IE_ENCODE(itu, called)
2313 {
2314 START_IE(called, UNI_IE_CALLED, 21);
2315 encode_addr(msg, &ie->addr, 0, 0, 0, IE_ISERROR(*ie));
2316 SET_IE_LEN(msg);
2317 return (0);
2318 }
2319
2320 DEF_IE_DECODE(itu, called)
2321 {
2322 u_char c;
2323 IE_START(;);
2324
2325 if (ielen > 21 || ielen < 1)
2326 goto rej;
2327
2328 c = *msg->b_rptr++;
2329 ielen--;
2330
2331 if (!(c & 0x80))
2332 goto rej;
2333
2334 if (decode_addr(&ie->addr, ielen, msg, c))
2335 goto rej;
2336
2337 IE_END(CALLED);
2338 }
2339
2340 /**********************************************************************/
2341
2342 DEF_IE_PRINT(itu, calledsub)
2343 {
2344 if(uni_print_iehdr("calledsub", &ie->h, cx))
2345 return;
2346 print_addrsub(cx, &ie->addr);
2347 uni_print_ieend(cx);
2348 }
2349
2350 DEF_IE_CHECK(itu, calledsub)
2351 {
2352 UNUSED(cx);
2353
2354 if(check_subaddr(&ie->addr))
2355 return -1;
2356 return 0;
2357 }
2358
2359 DEF_IE_ENCODE(itu, calledsub)
2360 {
2361 START_IE(calledsub, UNI_IE_CALLEDSUB, 21);
2362 encode_subaddr(msg, &ie->addr);
2363 SET_IE_LEN(msg);
2364 return 0;
2365 }
2366
2367 DEF_IE_DECODE(itu, calledsub)
2368 {
2369 u_char c;
2370
2371 IE_START(;);
2372
2373 if(ielen > 21)
2374 goto rej;
2375
2376 c = *msg->b_rptr++;
2377 ielen--;
2378
2379 if(decode_subaddr(&ie->addr, ielen, msg, c))
2380 goto rej;
2381
2382 IE_END(CALLEDSUB);
2383 }
2384
2385 /**********************************************************************/
2386
2387 DEF_IE_PRINT(itu, calling)
2388 {
2389 if(uni_print_iehdr("calling", &ie->h, cx))
2390 return;
2391 print_addr(cx, &ie->addr);
2392
2393 if(ie->h.present & UNI_CALLING_SCREEN_P) {
2394 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2395 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2396 }
2397
2398 uni_print_ieend(cx);
2399 }
2400
2401 DEF_IE_CHECK(itu, calling)
2402 {
2403 UNUSED(cx);
2404
2405 if(check_addr(&ie->addr))
2406 return -1;
2407
2408 if(ie->h.present & UNI_CALLING_SCREEN_P)
2409 if(check_screen(ie->screen, ie->pres))
2410 return -1;
2411 return 0;
2412 }
2413
2414 DEF_IE_ENCODE(itu, calling)
2415 {
2416 START_IE(calling, UNI_IE_CALLING, 22);
2417 encode_addr(msg, &ie->addr, ie->h.present & UNI_CALLING_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2418 SET_IE_LEN(msg);
2419 return 0;
2420 }
2421
2422 DEF_IE_DECODE(itu, calling)
2423 {
2424 u_char c, plan;
2425
2426 IE_START(;);
2427
2428 if(ielen > 22 || ielen < 1)
2429 goto rej;
2430
2431 plan = *msg->b_rptr++;
2432 ielen--;
2433
2434 if(!(plan & 0x80)) {
2435 if(ielen == 0)
2436 goto rej;
2437 ielen--;
2438 c = *msg->b_rptr++;
2439
2440 ie->h.present |= UNI_CALLING_SCREEN_P;
2441 ie->pres = (c >> 5) & 0x3;
2442 ie->screen = c & 0x3;
2443
2444 if(!(c & 0x80))
2445 goto rej;
2446 }
2447
2448 if(decode_addr(&ie->addr, ielen, msg, plan))
2449 goto rej;
2450
2451 IE_END(CALLING);
2452 }
2453
2454 /**********************************************************************/
2455
2456 DEF_IE_PRINT(itu, callingsub)
2457 {
2458 if(uni_print_iehdr("callingsub", &ie->h, cx))
2459 return;
2460 print_addrsub(cx, &ie->addr);
2461 uni_print_ieend(cx);
2462 }
2463
2464 DEF_IE_CHECK(itu, callingsub)
2465 {
2466 UNUSED(cx);
2467
2468 if(check_subaddr(&ie->addr))
2469 return -1;
2470 return 0;
2471 }
2472
2473 DEF_IE_ENCODE(itu, callingsub)
2474 {
2475 START_IE(callingsub, UNI_IE_CALLINGSUB, 21);
2476 encode_subaddr(msg, &ie->addr);
2477 SET_IE_LEN(msg);
2478 return 0;
2479 }
2480
2481 DEF_IE_DECODE(itu, callingsub)
2482 {
2483 u_char c;
2484
2485 IE_START(;);
2486
2487 if(ielen > 21)
2488 goto rej;
2489
2490 c = *msg->b_rptr++;
2491 ielen--;
2492
2493 if(decode_subaddr(&ie->addr, ielen, msg, c))
2494 goto rej;
2495
2496 IE_END(CALLINGSUB);
2497 }
2498
2499 /**********************************************************************/
2500
2501 DEF_IE_PRINT(itu, conned)
2502 {
2503 if(uni_print_iehdr("conned", &ie->h, cx))
2504 return;
2505 print_addr(cx, &ie->addr);
2506
2507 if(ie->h.present & UNI_CONNED_SCREEN_P) {
2508 uni_print_tbl("screening", ie->screen, screen_tbl, cx);
2509 uni_print_tbl("presentation", ie->pres, pres_tbl, cx);
2510 }
2511
2512 uni_print_ieend(cx);
2513 }
2514
2515 DEF_IE_CHECK(itu, conned)
2516 {
2517 UNUSED(cx);
2518
2519 if(check_addr(&ie->addr))
2520 return -1;
2521
2522 if(ie->h.present & UNI_CONNED_SCREEN_P)
2523 if(check_screen(ie->screen, ie->pres))
2524 return -1;
2525 return 0;
2526 }
2527
2528 DEF_IE_ENCODE(itu, conned)
2529 {
2530 START_IE(conned, UNI_IE_CONNED, 22);
2531 encode_addr(msg, &ie->addr, ie->h.present & UNI_CONNED_SCREEN_P, ie->screen, ie->pres, IE_ISERROR(*ie));
2532 SET_IE_LEN(msg);
2533 return 0;
2534 }
2535
2536 DEF_IE_DECODE(itu, conned)
2537 {
2538 u_char c, plan;
2539
2540 IE_START(;);
2541
2542 if(ielen > 22 || ielen < 1)
2543 goto rej;
2544
2545 plan = *msg->b_rptr++;
2546 ielen--;
2547
2548 if(!(plan & 0x80)) {
2549 if(ielen == 0)
2550 goto rej;
2551 ielen--;
2552 c = *msg->b_rptr++;
2553
2554 ie->h.present |= UNI_CONNED_SCREEN_P;
2555 ie->pres = (c >> 5) & 0x3;
2556 ie->screen = c & 0x3;
2557
2558 if(!(c & 0x80))
2559 goto rej;
2560 }
2561
2562 if(decode_addr(&ie->addr, ielen, msg, plan))
2563 goto rej;
2564
2565 IE_END(CONNED);
2566 }
2567
2568 /**********************************************************************/
2569
2570 DEF_IE_PRINT(itu, connedsub)
2571 {
2572 if(uni_print_iehdr("connedsub", &ie->h, cx))
2573 return;
2574 print_addrsub(cx, &ie->addr);
2575 uni_print_ieend(cx);
2576 }
2577
2578 DEF_IE_CHECK(itu, connedsub)
2579 {
2580 UNUSED(cx);
2581
2582 if(check_subaddr(&ie->addr))
2583 return -1;
2584 return 0;
2585 }
2586
2587 DEF_IE_ENCODE(itu, connedsub)
2588 {
2589 START_IE(connedsub, UNI_IE_CONNEDSUB, 21);
2590 encode_subaddr(msg, &ie->addr);
2591 SET_IE_LEN(msg);
2592 return 0;
2593 }
2594
2595 DEF_IE_DECODE(itu, connedsub)
2596 {
2597 u_char c;
2598
2599 IE_START(;);
2600
2601 if(ielen > 21)
2602 goto rej;
2603
2604 c = *msg->b_rptr++;
2605 ielen--;
2606
2607 if(decode_subaddr(&ie->addr, ielen, msg, c))
2608 goto rej;
2609
2610 IE_END(CONNEDSUB);
2611 }
2612
2613 /*********************************************************************
2614 *
2615 * Endpoint reference.
2616 *
2617 * References for this IE are:
2618 *
2619 * Q.2971 p. 14
2620 *
2621 * Only ITU-T coding allowed.
2622 */
2623
2624 DEF_IE_PRINT(itu, epref)
2625 {
2626 if(uni_print_iehdr("epref", &ie->h, cx))
2627 return;
2628 uni_print_entry(cx, "epref", "(%u,%u)", ie->flag, ie->epref);
2629 uni_print_ieend(cx);
2630 }
2631
2632 DEF_IE_CHECK(itu, epref)
2633 {
2634 UNUSED(cx);
2635
2636 if(ie->epref >= (2<<15))
2637 return -1;
2638
2639 return 0;
2640 }
2641
2642 DEF_IE_ENCODE(itu, epref)
2643 {
2644 START_IE(epref, UNI_IE_EPREF, 3);
2645
2646 if (IE_ISERROR(*ie))
2647 APP_BYTE(msg, 0xff);
2648 else
2649 APP_BYTE(msg, 0);
2650 APP_BYTE(msg, (ie->flag << 7) | ((ie->epref >> 8) & 0x7f));
2651 APP_BYTE(msg, (ie->epref & 0xff));
2652
2653 SET_IE_LEN(msg);
2654 return 0;
2655 }
2656
2657 DEF_IE_DECODE(itu, epref)
2658 {
2659 u_char c;
2660
2661 IE_START(;);
2662
2663 if(ielen != 3)
2664 goto rej;
2665 if(*msg->b_rptr++ != 0)
2666 goto rej;
2667
2668 c = *msg->b_rptr++;
2669 ie->flag = (c & 0x80) ? 1 : 0;
2670 ie->epref = (c & 0x7f) << 8;
2671 ie->epref |= *msg->b_rptr++;
2672
2673 IE_END(EPREF);
2674 }
2675
2676 /*********************************************************************
2677 *
2678 * Endpoint state.
2679 *
2680 * References for this IE are:
2681 *
2682 * Q.2971 pp. 14...15
2683 *
2684 * Only ITU-T coding allowed.
2685 */
2686
2687 DEF_IE_PRINT(itu, epstate)
2688 {
2689 static const struct uni_print_tbl tbl[] = {
2690 MKT(UNI_EPSTATE_NULL, null),
2691 MKT(UNI_EPSTATE_ADD_INIT, add-initiated),
2692 MKT(UNI_EPSTATE_ALERT_DLVD, alerting-delivered),
2693 MKT(UNI_EPSTATE_ADD_RCVD, add-received),
2694 MKT(UNI_EPSTATE_ALERT_RCVD, alerting-received),
2695 MKT(UNI_EPSTATE_ACTIVE, active),
2696 MKT(UNI_EPSTATE_DROP_INIT, drop-initiated),
2697 MKT(UNI_EPSTATE_DROP_RCVD, drop-received),
2698 EOT()
2699 };
2700
2701 if(uni_print_iehdr("epstate", &ie->h, cx))
2702 return;
2703 uni_print_tbl("state", ie->state, tbl, cx);
2704 uni_print_ieend(cx);
2705 }
2706
2707 DEF_IE_CHECK(itu, epstate)
2708 {
2709 UNUSED(cx);
2710
2711 switch(ie->state) {
2712 default:
2713 return -1;
2714
2715 case UNI_EPSTATE_NULL:
2716 case UNI_EPSTATE_ADD_INIT:
2717 case UNI_EPSTATE_ALERT_DLVD:
2718 case UNI_EPSTATE_ADD_RCVD:
2719 case UNI_EPSTATE_ALERT_RCVD:
2720 case UNI_EPSTATE_DROP_INIT:
2721 case UNI_EPSTATE_DROP_RCVD:
2722 case UNI_EPSTATE_ACTIVE:
2723 break;
2724 }
2725
2726 return 0;
2727 }
2728
2729 DEF_IE_ENCODE(itu, epstate)
2730 {
2731 START_IE(epstate, UNI_IE_EPSTATE, 1);
2732
2733 APP_BYTE(msg, ie->state);
2734
2735 SET_IE_LEN(msg);
2736 return 0;
2737 }
2738
2739 DEF_IE_DECODE(itu, epstate)
2740 {
2741 IE_START(;);
2742
2743 if(ielen != 1)
2744 goto rej;
2745
2746 ie->state = *msg->b_rptr++ & 0x3f;
2747
2748 IE_END(EPSTATE);
2749 }
2750
2751 /*********************************************************************
2752 *
2753 * ATM adaptation layer parameters
2754 *
2755 * References for this IE are:
2756 *
2757 * Q.2931 pp. 43...49
2758 * Q.2931 Amd 2
2759 * UNI4.0 p. 9
2760 *
2761 * UNI4.0 states, that AAL2 is not supported. However we keep it. No
2762 * parameters are associated with AAL2.
2763 *
2764 * Amd2 not checked. XXX
2765 *
2766 * Only ITU-T coding allowed.
2767 */
2768 DEF_IE_PRINT(itu, aal)
2769 {
2770 static const struct uni_print_tbl aal_tbl[] = {
2771 MKT(UNI_AAL_0, VOICE),
2772 MKT(UNI_AAL_1, 1),
2773 MKT(UNI_AAL_2, 2),
2774 MKT(UNI_AAL_4, 3/4),
2775 MKT(UNI_AAL_5, 5),
2776 MKT(UNI_AAL_USER, USER),
2777 EOT()
2778 };
2779 static const struct uni_print_tbl subtype_tbl[] = {
2780 MKT(UNI_AAL1_SUB_NULL, null),
2781 MKT(UNI_AAL1_SUB_VOICE, voice),
2782 MKT(UNI_AAL1_SUB_CIRCUIT, circuit),
2783 MKT(UNI_AAL1_SUB_HQAUDIO, hqaudio),
2784 MKT(UNI_AAL1_SUB_VIDEO, video),
2785 EOT()
2786 };
2787 static const struct uni_print_tbl cbr_rate_tbl[] = {
2788 MKT(UNI_AAL1_CBR_64, 64),
2789 MKT(UNI_AAL1_CBR_1544, 1544(DS1)),
2790 MKT(UNI_AAL1_CBR_6312, 6312(DS2)),
2791 MKT(UNI_AAL1_CBR_32064, 32064),
2792 MKT(UNI_AAL1_CBR_44736, 44736(DS3)),
2793 MKT(UNI_AAL1_CBR_97728, 97728),
2794 MKT(UNI_AAL1_CBR_2048, 2048(E1)),
2795 MKT(UNI_AAL1_CBR_8448, 8448(E2)),
2796 MKT(UNI_AAL1_CBR_34368, 34368(E3)),
2797 MKT(UNI_AAL1_CBR_139264, 139264),
2798 MKT(UNI_AAL1_CBR_N64, Nx64),
2799 MKT(UNI_AAL1_CBR_N8, Nx8),
2800 EOT()
2801 };
2802 static const struct uni_print_tbl screc_tbl[] = {
2803 MKT(UNI_AAL1_SCREC_NULL, null),
2804 MKT(UNI_AAL1_SCREC_SRTS, srts),
2805 MKT(UNI_AAL1_SCREC_ACLK, aclk),
2806 EOT()
2807 };
2808 static const struct uni_print_tbl ecm_tbl[] = {
2809 MKT(UNI_AAL1_ECM_NULL, null),
2810 MKT(UNI_AAL1_ECM_LOSS, loss),
2811 MKT(UNI_AAL1_ECM_DELAY, delay),
2812 EOT()
2813 };
2814 static const struct uni_print_tbl sscs_tbl[] = {
2815 MKT(UNI_AAL_SSCS_NULL, null),
2816 MKT(UNI_AAL_SSCS_SSCOPA, sscopa),
2817 MKT(UNI_AAL_SSCS_SSCOPU, sscopu),
2818 MKT(UNI_AAL_SSCS_FRAME, frame),
2819 EOT()
2820 };
2821
2822 if(uni_print_iehdr("aal", &ie->h, cx))
2823 return;
2824 uni_print_tbl("type", ie->type, aal_tbl, cx);
2825
2826 switch(ie->type) {
2827
2828 case UNI_AAL_0:
2829 uni_print_push_prefix("", cx);
2830 cx->indent++;
2831 break;
2832
2833 case UNI_AAL_2:
2834 uni_print_push_prefix("2", cx);
2835 cx->indent++;
2836 break;
2837
2838 case UNI_AAL_1:
2839 uni_print_push_prefix("1", cx);
2840 cx->indent++;
2841 uni_print_tbl("subtype", ie->u.aal1.subtype, subtype_tbl, cx);
2842 uni_print_tbl("cbr_rate", ie->u.aal1.cbr_rate, cbr_rate_tbl, cx);
2843 if(ie->h.present & UNI_AAL1_MULT_P)
2844 uni_print_entry(cx, "mult", "%u", ie->u.aal1.mult);
2845 if(ie->h.present & UNI_AAL1_SCREC_P)
2846 uni_print_tbl("screc", ie->u.aal1.screc, screc_tbl, cx);
2847 if(ie->h.present & UNI_AAL1_ECM_P)
2848 uni_print_tbl("ecm", ie->u.aal1.ecm, ecm_tbl, cx);
2849 if(ie->h.present & UNI_AAL1_BSIZE_P)
2850 uni_print_entry(cx, "bsize", "%u", ie->u.aal1.bsize);
2851 if(ie->h.present & UNI_AAL1_PART_P)
2852 uni_print_entry(cx, "part", "%u", ie->u.aal1.part);
2853 break;
2854
2855 case UNI_AAL_4:
2856 uni_print_push_prefix("4", cx);
2857 cx->indent++;
2858 if(ie->h.present & UNI_AAL4_CPCS_P)
2859 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal4.fwd_cpcs,
2860 ie->u.aal4.bwd_cpcs);
2861 if(ie->h.present & UNI_AAL4_MID_P)
2862 uni_print_entry(cx, "mid", "(%u,%u)", ie->u.aal4.mid_low,
2863 ie->u.aal4.mid_high);
2864 if(ie->h.present & UNI_AAL4_SSCS_P)
2865 uni_print_tbl("sscs", ie->u.aal4.sscs, sscs_tbl, cx);
2866 break;
2867
2868 case UNI_AAL_5:
2869 uni_print_push_prefix("5", cx);
2870 cx->indent++;
2871 if(ie->h.present & UNI_AAL5_CPCS_P)
2872 uni_print_entry(cx, "cpcs", "(%u,%u)", ie->u.aal5.fwd_cpcs,
2873 ie->u.aal5.bwd_cpcs);
2874 if(ie->h.present & UNI_AAL5_SSCS_P)
2875 uni_print_tbl("sscs", ie->u.aal5.sscs, sscs_tbl, cx);
2876 break;
2877
2878 case UNI_AAL_USER:
2879 uni_print_push_prefix("user", cx);
2880 cx->indent++;
2881 if(ie->u.aalu.len > 4) {
2882 uni_print_entry(cx, "info", "ERROR(len=%u)", ie->u.aalu.len);
2883 } else {
2884 u_int i;
2885
2886 uni_print_entry(cx, "info", "(");
2887 for(i = 0; i < ie->u.aalu.len; i++)
2888 uni_printf(cx, "%s%u", !i?"":",", ie->u.aalu.user[i]);
2889 uni_printf(cx, ")");
2890 }
2891 break;
2892 }
2893 cx->indent--;
2894 uni_print_pop_prefix(cx);
2895 uni_print_eol(cx);
2896
2897 uni_print_ieend(cx);
2898 }
2899
2900 DEF_IE_CHECK(itu, aal)
2901 {
2902 UNUSED(cx);
2903
2904 if(ie->type == UNI_AAL_0) {
2905 ;
2906 } else if(ie->type == UNI_AAL_1) {
2907 switch(ie->u.aal1.subtype) {
2908
2909 default:
2910 return -1;
2911
2912 case UNI_AAL1_SUB_NULL:
2913 case UNI_AAL1_SUB_VOICE:
2914 case UNI_AAL1_SUB_CIRCUIT:
2915 case UNI_AAL1_SUB_HQAUDIO:
2916 case UNI_AAL1_SUB_VIDEO:
2917 break;
2918 }
2919 switch(ie->u.aal1.cbr_rate) {
2920
2921 default:
2922 return -1;
2923
2924 case UNI_AAL1_CBR_64:
2925 case UNI_AAL1_CBR_1544:
2926 case UNI_AAL1_CBR_6312:
2927 case UNI_AAL1_CBR_32064:
2928 case UNI_AAL1_CBR_44736:
2929 case UNI_AAL1_CBR_97728:
2930 case UNI_AAL1_CBR_2048:
2931 case UNI_AAL1_CBR_8448:
2932 case UNI_AAL1_CBR_34368:
2933 case UNI_AAL1_CBR_139264:
2934 if((ie->h.present & UNI_AAL1_MULT_P))
2935 return -1;
2936 break;
2937
2938 case UNI_AAL1_CBR_N64:
2939 if(!(ie->h.present & UNI_AAL1_MULT_P))
2940 return -1;
2941 if(ie->u.aal1.mult < 2)
2942 return -1;
2943 break;
2944
2945 case UNI_AAL1_CBR_N8:
2946 if(!(ie->h.present & UNI_AAL1_MULT_P))
2947 return -1;
2948 if(ie->u.aal1.mult == 0 || ie->u.aal1.mult > 7)
2949 return -1;
2950 break;
2951 }
2952 if(ie->h.present & UNI_AAL1_SCREC_P) {
2953 switch(ie->u.aal1.screc) {
2954
2955 default:
2956 return -1;
2957
2958 case UNI_AAL1_SCREC_NULL:
2959 case UNI_AAL1_SCREC_SRTS:
2960 case UNI_AAL1_SCREC_ACLK:
2961 break;
2962 }
2963 }
2964 if(ie->h.present & UNI_AAL1_ECM_P) {
2965 switch(ie->u.aal1.ecm) {
2966
2967 default:
2968 return -1;
2969
2970 case UNI_AAL1_ECM_NULL:
2971 case UNI_AAL1_ECM_LOSS:
2972 case UNI_AAL1_ECM_DELAY:
2973 break;
2974 }
2975 }
2976 if(ie->h.present & UNI_AAL1_BSIZE_P) {
2977 if(ie->u.aal1.bsize == 0)
2978 return -1;
2979 }
2980 if(ie->h.present & UNI_AAL1_PART_P) {
2981 if(ie->u.aal1.part == 0 || ie->u.aal1.part > 47)
2982 return -1;
2983 }
2984
2985 } else if(ie->type == UNI_AAL_2) {
2986 ;
2987
2988 } else if(ie->type == UNI_AAL_4) {
2989 if(ie->h.present & UNI_AAL4_MID_P) {
2990 if(ie->u.aal4.mid_low >= 1024)
2991 return -1;
2992 if(ie->u.aal4.mid_high >= 1024)
2993 return -1;
2994 if(ie->u.aal4.mid_low > ie->u.aal4.mid_high)
2995 return -1;
2996 }
2997 if(ie->h.present & UNI_AAL4_SSCS_P) {
2998 switch(ie->u.aal4.sscs) {
2999
3000 default:
3001 return -1;
3002
3003 case UNI_AAL_SSCS_NULL:
3004 case UNI_AAL_SSCS_SSCOPA:
3005 case UNI_AAL_SSCS_SSCOPU:
3006 case UNI_AAL_SSCS_FRAME:
3007 break;
3008 }
3009 }
3010
3011 } else if(ie->type == UNI_AAL_5) {
3012 if(ie->h.present & UNI_AAL5_SSCS_P) {
3013 switch(ie->u.aal5.sscs) {
3014
3015 default:
3016 return -1;
3017
3018 case UNI_AAL_SSCS_NULL:
3019 case UNI_AAL_SSCS_SSCOPA:
3020 case UNI_AAL_SSCS_SSCOPU:
3021 case UNI_AAL_SSCS_FRAME:
3022 break;
3023 }
3024 }
3025
3026 } else if(ie->type == UNI_AAL_USER) {
3027 if(ie->u.aalu.len > 4)
3028 return -1;
3029
3030 } else
3031 return -1;
3032
3033 return 0;
3034 }
3035
3036 DEF_IE_ENCODE(itu, aal)
3037 {
3038 START_IE(aal, UNI_IE_AAL, 16);
3039
3040 APP_BYTE(msg, ie->type);
3041 switch(ie->type) {
3042
3043 case UNI_AAL_0:
3044 break;
3045
3046 case UNI_AAL_1:
3047 APP_SUB_BYTE(msg,
3048 UNI_AAL_SUB_ID, ie->u.aal1.subtype);
3049 APP_SUB_BYTE(msg,
3050 UNI_AAL_CBR_ID, ie->u.aal1.cbr_rate);
3051 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_MULT_P,
3052 UNI_AAL_MULT_ID, ie->u.aal1.mult);
3053 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_SCREC_P,
3054 UNI_AAL_SCREC_ID, ie->u.aal1.screc);
3055 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_ECM_P,
3056 UNI_AAL_ECM_ID, ie->u.aal1.ecm);
3057 APP_OPT_16BIT(msg, ie->h.present, UNI_AAL1_BSIZE_P,
3058 UNI_AAL_BSIZE_ID, ie->u.aal1.bsize);
3059 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL1_PART_P,
3060 UNI_AAL_PART_ID, ie->u.aal1.part);
3061 break;
3062
3063 case UNI_AAL_2:
3064 break;
3065
3066 case UNI_AAL_4:
3067 if(ie->h.present & UNI_AAL4_CPCS_P) {
3068 APP_SUB_16BIT(msg,
3069 UNI_AAL_FWDCPCS_ID, ie->u.aal4.fwd_cpcs);
3070 APP_SUB_16BIT(msg,
3071 UNI_AAL_BWDCPCS_ID, ie->u.aal4.bwd_cpcs);
3072 }
3073 if(ie->h.present & UNI_AAL4_MID_P) {
3074 APP_BYTE(msg, UNI_AAL_MID_ID);
3075 APP_16BIT(msg, ie->u.aal4.mid_low);
3076 APP_16BIT(msg, ie->u.aal4.mid_high);
3077 }
3078 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL4_SSCS_P,
3079 UNI_AAL_SSCS_ID, ie->u.aal4.sscs);
3080 break;
3081
3082 case UNI_AAL_5:
3083 if(ie->h.present & UNI_AAL5_CPCS_P) {
3084 APP_SUB_16BIT(msg,
3085 UNI_AAL_FWDCPCS_ID, ie->u.aal5.fwd_cpcs);
3086 APP_SUB_16BIT(msg,
3087 UNI_AAL_BWDCPCS_ID, ie->u.aal5.bwd_cpcs);
3088 }
3089 APP_OPT_BYTE(msg, ie->h.present, UNI_AAL5_SSCS_P,
3090 UNI_AAL_SSCS_ID, ie->u.aal5.sscs);
3091 break;
3092
3093 case UNI_AAL_USER:
3094 APP_BUF(msg, ie->u.aalu.user, ie->u.aalu.len);
3095 break;
3096
3097 default:
3098 return -1;
3099 }
3100
3101 SET_IE_LEN(msg);
3102 return 0;
3103 }
3104
3105 /*
3106 * XXX What should we do with multiple subtype occurences? Ignore
3107 * or reject. Currently we reject.
3108 */
3109 static int
3110 decode_aal_1(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3111 {
3112 int subtype_p, cbr_p;
3113
3114 subtype_p = cbr_p = 0;
3115
3116 while(ielen-- > 0) {
3117 switch(*msg->b_rptr++) {
3118
3119 case UNI_AAL_SUB_ID:
3120 if(ielen == 0 || subtype_p)
3121 return -1;
3122 ielen--;
3123 subtype_p = 1;
3124 ie->u.aal1.subtype = *msg->b_rptr++;
3125 break;
3126
3127 case UNI_AAL_CBR_ID:
3128 if(ielen == 0 || cbr_p)
3129 return -1;
3130 ielen--;
3131 cbr_p = 1;
3132 ie->u.aal1.cbr_rate = *msg->b_rptr++;
3133 break;
3134
3135 case UNI_AAL_MULT_ID:
3136 if(ielen < 2 || (ie->h.present & UNI_AAL1_MULT_P))
3137 return -1;
3138 ielen -= 2;
3139 ie->h.present |= UNI_AAL1_MULT_P;
3140 ie->u.aal1.mult = *msg->b_rptr++ << 8;
3141 ie->u.aal1.mult |= *msg->b_rptr++;
3142 break;
3143
3144 case UNI_AAL_SCREC_ID:
3145 if(ielen == 0 || (ie->h.present & UNI_AAL1_SCREC_P))
3146 return -1;
3147 ielen--;
3148 ie->h.present |= UNI_AAL1_SCREC_P;
3149 ie->u.aal1.screc = *msg->b_rptr++;
3150 break;
3151
3152 case UNI_AAL_ECM_ID:
3153 if(ielen == 0 || (ie->h.present & UNI_AAL1_ECM_P))
3154 return -1;
3155 ielen--;
3156 ie->h.present |= UNI_AAL1_ECM_P;
3157 ie->u.aal1.ecm = *msg->b_rptr++;
3158 break;
3159
3160 case UNI_AAL_BSIZE_ID:
3161 if(ielen < 2 || (ie->h.present & UNI_AAL1_BSIZE_P))
3162 return -1;
3163 ielen -= 2;
3164 ie->h.present |= UNI_AAL1_BSIZE_P;
3165 ie->u.aal1.bsize = *msg->b_rptr++ << 8;
3166 ie->u.aal1.bsize |= *msg->b_rptr++;
3167 break;
3168
3169 case UNI_AAL_PART_ID:
3170 if(ielen == 0 || (ie->h.present & UNI_AAL1_PART_P))
3171 return -1;
3172 ielen--;
3173 ie->h.present |= UNI_AAL1_PART_P;
3174 ie->u.aal1.part = *msg->b_rptr++;
3175 break;
3176
3177 default:
3178 return -1;
3179 }
3180 }
3181 if(!subtype_p || !cbr_p)
3182 return -1;
3183
3184 return 0;
3185 }
3186
3187 static int
3188 decode_aal_4(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3189 {
3190 int fcpcs_p, bcpcs_p;
3191
3192 fcpcs_p = bcpcs_p = 0;
3193
3194 while(ielen-- > 0) {
3195 switch(*msg->b_rptr++) {
3196
3197 case UNI_AAL_FWDCPCS_ID:
3198 if(ielen < 2 || fcpcs_p)
3199 return -1;
3200 ielen -= 2;
3201 fcpcs_p = 1;
3202 ie->u.aal4.fwd_cpcs = *msg->b_rptr++ << 8;
3203 ie->u.aal4.fwd_cpcs |= *msg->b_rptr++;
3204 break;
3205
3206 case UNI_AAL_BWDCPCS_ID:
3207 if(ielen < 2 || bcpcs_p)
3208 return -1;
3209 ielen -= 2;
3210 bcpcs_p = 1;
3211 ie->u.aal4.bwd_cpcs = *msg->b_rptr++ << 8;
3212 ie->u.aal4.bwd_cpcs |= *msg->b_rptr++;
3213 break;
3214
3215 case UNI_AAL_MID_ID:
3216 if(ielen < 4 || (ie->h.present & UNI_AAL4_MID_P))
3217 return -1;
3218 ielen -= 4;
3219 ie->h.present |= UNI_AAL4_MID_P;
3220 ie->u.aal4.mid_low = *msg->b_rptr++ << 8;
3221 ie->u.aal4.mid_low |= *msg->b_rptr++;
3222 ie->u.aal4.mid_high = *msg->b_rptr++ << 8;
3223 ie->u.aal4.mid_high |= *msg->b_rptr++;
3224 break;
3225
3226 case UNI_AAL_SSCS_ID:
3227 if(ielen == 0 || (ie->h.present & UNI_AAL4_SSCS_P))
3228 return -1;
3229 ielen--;
3230 ie->h.present |= UNI_AAL4_SSCS_P;
3231 ie->u.aal4.sscs = *msg->b_rptr++;
3232 break;
3233
3234 default:
3235 return -1;
3236 }
3237 }
3238
3239 if(fcpcs_p ^ bcpcs_p)
3240 return -1;
3241 if(fcpcs_p)
3242 ie->h.present |= UNI_AAL4_CPCS_P;
3243
3244 return 0;
3245 }
3246
3247 static int
3248 decode_aal_5(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3249 {
3250 int fcpcs_p, bcpcs_p;
3251
3252 fcpcs_p = bcpcs_p = 0;
3253
3254 while(ielen-- > 0) {
3255 switch(*msg->b_rptr++) {
3256
3257 case UNI_AAL_FWDCPCS_ID:
3258 if(ielen < 2 || fcpcs_p)
3259 return -1;
3260 ielen -= 2;
3261 fcpcs_p = 1;
3262 ie->u.aal5.fwd_cpcs = *msg->b_rptr++ << 8;
3263 ie->u.aal5.fwd_cpcs |= *msg->b_rptr++;
3264 break;
3265
3266 case UNI_AAL_BWDCPCS_ID:
3267 if(ielen < 2 || bcpcs_p)
3268 return -1;
3269 ielen -= 2;
3270 bcpcs_p = 1;
3271 ie->u.aal5.bwd_cpcs = *msg->b_rptr++ << 8;
3272 ie->u.aal5.bwd_cpcs |= *msg->b_rptr++;
3273 break;
3274
3275 case UNI_AAL_SSCS_ID:
3276 if(ielen == 0 || (ie->h.present & UNI_AAL5_SSCS_P))
3277 return -1;
3278 ielen--;
3279 ie->h.present |= UNI_AAL5_SSCS_P;
3280 ie->u.aal5.sscs = *msg->b_rptr++;
3281 break;
3282
3283 default:
3284 return -1;
3285 }
3286 }
3287
3288 if(fcpcs_p ^ bcpcs_p)
3289 return -1;
3290 if(fcpcs_p)
3291 ie->h.present |= UNI_AAL5_CPCS_P;
3292
3293 return 0;
3294 }
3295
3296 static int
3297 decode_aal_user(struct uni_ie_aal *ie, struct uni_msg *msg, u_int ielen)
3298 {
3299 if(ielen > 4)
3300 return -1;
3301
3302 ie->u.aalu.len = 0;
3303 while(ielen--)
3304 ie->u.aalu.user[ie->u.aalu.len++] = *msg->b_rptr++;
3305
3306 return 0;
3307 }
3308
3309 DEF_IE_DECODE(itu, aal)
3310 {
3311 u_char c;
3312
3313 IE_START(DISC_ACC_ERR(AAL));
3314
3315 if(ielen < 1 || ielen > 21)
3316 goto rej;
3317
3318 c = *msg->b_rptr++;
3319 ielen--;
3320
3321 switch(c) {
3322
3323 case UNI_AAL_0:
3324 ie->type = c;
3325 break;
3326
3327 case UNI_AAL_1:
3328 ie->type = c;
3329 if(decode_aal_1(ie, msg, ielen))
3330 goto rej;
3331 break;
3332
3333 case UNI_AAL_2:
3334 ie->type = c;
3335 break;
3336
3337 case UNI_AAL_4:
3338 ie->type = c;
3339 if(decode_aal_4(ie, msg, ielen))
3340 goto rej;
3341 break;
3342
3343 case UNI_AAL_5:
3344 ie->type = c;
3345 if(decode_aal_5(ie, msg, ielen))
3346 goto rej;
3347 break;
3348
3349 case UNI_AAL_USER:
3350 ie->type = c;
3351 if(decode_aal_user(ie, msg, ielen))
3352 goto rej;
3353 break;
3354
3355 default:
3356 goto rej;
3357 }
3358
3359 IE_END(AAL);
3360 }
3361
3362 /*********************************************************************
3363 *
3364 * Traffic descriptor.
3365 * Alternate traffic descriptor.
3366 * Minimum traffic descriptor.
3367 *
3368 * References for this IE are:
3369 *
3370 * Q.2931 pp. 49...51
3371 * Q.2961
3372 * Q.2962
3373 * UNI4.0 pp. 9...10, 106...109
3374 *
3375 * The Q.s specify the coding. UNI4.0 adds frame discard and best-effort.
3376 * Appendix in UNI4.0 lists the allowed combinations.
3377 *
3378 * PCR0 PCR1 SCR/MBS0 SCR/MBS1 BE TAG FDISC ABR
3379 * 1 CBR.1 - Y - - - N Y/N -
3380 * 2 CBR.2 - Y - - - N Y/N - (*)
3381 * 3 CBR.3 Y Y - - - Y Y/N - (*)
3382 * 4 rt-VBR.1 - Y - Y - N Y/N -
3383 * 5 rt-VBR.2 - Y Y - - N Y/N -
3384 * 6 rt-VBR.3 - Y Y - - Y Y/N -
3385 * 7 rt-VBR.4 Y Y - - - Y/N Y/N - (*)
3386 * 8 rt-VBR.5 - Y - - - N Y/N - (*)
3387 * 9 rt-VBR.6 - Y - Y - N Y/N - (*)
3388 * 10 nrt-VBR.1 - Y - Y - N Y/N -
3389 * 11 nrt-VBR.2 - Y Y - - N Y/N -
3390 * 12 nrt-VBR.3 - Y Y - - Y Y/N -
3391 * 13 nrt-VBR.4 Y Y - - - Y/N Y/N - (*)
3392 * 14 nrt-VBR.5 - Y - - - N Y/N - (*)
3393 * 15 nrt-VBR.6 - Y - Y - N Y/N - (*)
3394 * 16 ABR - Y - - - N Y/N O (*)
3395 * 17 UBR.1 - Y - - Y N Y/N -
3396 * 18 UBR.2 - Y - - Y Y Y/N -
3397 *
3398 * Allow ITU-T and NET coding, because its not clear, whether the
3399 * new fields in UNI4.0 should be used with NET coding or not.
3400 * Does not allow for experimental codings yet.
3401 */
3402
3403 static void
3404 print_ie_traffic_common(struct unicx *cx, u_int present, struct uni_xtraffic *ie)
3405 {
3406 uni_print_entry(cx, "fwd", "(");
3407 if(present & UNI_TRAFFIC_FPCR0_P)
3408 uni_printf(cx, "%u", ie->fpcr0);
3409 uni_putc(',', cx);
3410 if(present & UNI_TRAFFIC_FPCR1_P)
3411 uni_printf(cx, "%u", ie->fpcr1);
3412 uni_putc(',', cx);
3413 if(present & UNI_TRAFFIC_FSCR0_P)
3414 uni_printf(cx, "%u", ie->fscr0);
3415 uni_putc(',', cx);
3416 if(present & UNI_TRAFFIC_FSCR1_P)
3417 uni_printf(cx, "%u", ie->fscr1);
3418 uni_putc(',', cx);
3419 if(present & UNI_TRAFFIC_FMBS0_P)
3420 uni_printf(cx, "%u", ie->fmbs0);
3421 uni_putc(',', cx);
3422 if(present & UNI_TRAFFIC_FMBS1_P)
3423 uni_printf(cx, "%u", ie->fmbs1);
3424 uni_putc(',', cx);
3425 if(present & UNI_TRAFFIC_FABR1_P)
3426 uni_printf(cx, "%u", ie->fabr1);
3427 uni_printf(cx, ")");
3428
3429 uni_print_entry(cx, "bwd", "(");
3430 if(present & UNI_TRAFFIC_BPCR0_P)
3431 uni_printf(cx, "%u", ie->bpcr0);
3432 uni_putc(',', cx);
3433 if(present & UNI_TRAFFIC_BPCR1_P)
3434 uni_printf(cx, "%u", ie->bpcr1);
3435 uni_putc(',', cx);
3436 if(present & UNI_TRAFFIC_BSCR0_P)
3437 uni_printf(cx, "%u", ie->bscr0);
3438 uni_putc(',', cx);
3439 if(present & UNI_TRAFFIC_BSCR1_P)
3440 uni_printf(cx, "%u", ie->bscr1);
3441 uni_putc(',', cx);
3442 if(present & UNI_TRAFFIC_BMBS0_P)
3443 uni_printf(cx, "%u", ie->bmbs0);
3444 uni_putc(',', cx);
3445 if(present & UNI_TRAFFIC_BMBS1_P)
3446 uni_printf(cx, "%u", ie->bmbs1);
3447 uni_putc(',', cx);
3448 if(present & UNI_TRAFFIC_BABR1_P)
3449 uni_printf(cx, "%u", ie->babr1);
3450 uni_printf(cx, ")");
3451
3452 if(present & UNI_TRAFFIC_BEST_P)
3453 uni_print_flag("best_effort", cx);
3454 if(present & UNI_TRAFFIC_MOPT_P) {
3455 uni_print_entry(cx, "tag", "(");
3456 if(ie->ftag)
3457 uni_printf(cx, "fwd");
3458 uni_putc(',', cx);
3459 if(ie->btag)
3460 uni_printf(cx, "bwd");
3461 uni_putc(')', cx);
3462
3463 uni_print_entry(cx, "disc", "(");
3464 if(ie->fdisc)
3465 uni_printf(cx, "fwd");
3466 uni_putc(',', cx);
3467 if(ie->bdisc)
3468 uni_printf(cx, "bwd");
3469 uni_putc(')', cx);
3470 }
3471 }
3472
3473 struct tallow {
3474 u_int mask;
3475 int mopt_flag;
3476 u_char mopt_mask, mopt_val;
3477 };
3478
3479 static int
3480 check_traffic(u_int mask, u_int mopt, struct tallow *a)
3481 {
3482 if(mask != a->mask)
3483 return 0;
3484
3485 if(a->mopt_flag == 0) {
3486 /* not allowed */
3487 if(mopt == 0xffff)
3488 return 1;
3489 return 0;
3490 }
3491
3492 if(a->mopt_flag < 0) {
3493 /* optional */
3494 if(mopt == 0xffff)
3495 return 1;
3496 if((mopt & a->mopt_mask) == a->mopt_val)
3497 return 1;
3498 return 0;
3499 }
3500
3501 /* required */
3502 if(mopt == 0xffff)
3503 return 0;
3504 if((mopt & a->mopt_mask) == a->mopt_val)
3505 return 1;
3506 return 0;
3507 }
3508
3509 static int
3510 check_ie_traffic_common(struct uni_xtraffic *ie, u_int present,
3511 struct unicx *cx __unused)
3512 {
3513 static u_int fmask =
3514 UNI_TRAFFIC_FPCR0_P | UNI_TRAFFIC_FPCR1_P |
3515 UNI_TRAFFIC_FSCR0_P | UNI_TRAFFIC_FSCR1_P |
3516 UNI_TRAFFIC_FMBS0_P | UNI_TRAFFIC_FMBS1_P |
3517 UNI_TRAFFIC_FABR1_P;
3518 static u_int bmask =
3519 UNI_TRAFFIC_BPCR0_P | UNI_TRAFFIC_BPCR1_P |
3520 UNI_TRAFFIC_BSCR0_P | UNI_TRAFFIC_BSCR1_P |
3521 UNI_TRAFFIC_BMBS0_P | UNI_TRAFFIC_BMBS1_P |
3522 UNI_TRAFFIC_BABR1_P;
3523 #define DTAB(U,X) \
3524 { U##X##PCR1_P, \
3525 -1, U##X##TAG, 0 }, /* 1, 2, 8, 14 */ \
3526 { U##X##PCR0_P | U##X##PCR1_P, \
3527 +1, U##X##TAG, U##X##TAG }, /* 3 */ \
3528 { U##X##PCR1_P | U##X##SCR1_P | U##X##MBS1_P, \
3529 -1, U##X##TAG, 0 }, /* 4, 9, 10, 15 */ \
3530 { U##X##PCR1_P | U##X##SCR0_P | U##X##MBS0_P, \
3531 -1, 0, 0 }, /* 5, 6, 11, 12 */ \
3532 { U##X##PCR0_P | U##X##PCR1_P, \
3533 -1, 0, 0 }, /* 7, 13 */ \
3534 { U##X##PCR1_P | U##X##ABR1_P, \
3535 -1, U##X##TAG, 0 }, /* 16a */
3536 #define DTABSIZE 6
3537
3538 static struct tallow allow[2][DTABSIZE] = {
3539 { DTAB(UNI_TRAFFIC_, F) },
3540 { DTAB(UNI_TRAFFIC_, B) },
3541 };
3542 #undef DTAB
3543
3544 u_int f, b, p, m;
3545 int i;
3546
3547 f = present & fmask;
3548 b = present & bmask;
3549 p = present & (fmask | bmask);
3550 m = (present & UNI_TRAFFIC_MOPT_P)
3551 ? ( (ie->ftag ? UNI_TRAFFIC_FTAG : 0)
3552 | (ie->btag ? UNI_TRAFFIC_BTAG : 0)
3553 | (ie->fdisc ? UNI_TRAFFIC_FDISC : 0)
3554 | (ie->bdisc ? UNI_TRAFFIC_BDISC : 0))
3555 : 0xffff;
3556
3557
3558 if(present & UNI_TRAFFIC_BEST_P) {
3559 /*
3560 * Lines 17 and 18
3561 */
3562 if(p != (UNI_TRAFFIC_FPCR1_P | UNI_TRAFFIC_BPCR1_P))
3563 return -1;
3564 return 0;
3565 }
3566
3567 /*
3568 * Check forward and backward independent. There must be a higher
3569 * level checking in the CAC
3570 */
3571 for(i = 0; i < DTABSIZE; i++)
3572 if(check_traffic(f, m, &allow[0][i]))
3573 break;
3574 if(i == DTABSIZE)
3575 return -1;
3576
3577 for(i = 0; i < DTABSIZE; i++)
3578 if(check_traffic(b, m, &allow[1][i]))
3579 break;
3580 if(i == DTABSIZE)
3581 return -1;
3582
3583 return 0;
3584 }
3585
3586 static int
3587 encode_traffic_common(struct uni_msg *msg, struct uni_xtraffic *ie,
3588 u_int present, struct unicx *cx __unused)
3589 {
3590 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR0_P,
3591 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3592 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR0_P,
3593 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3594 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FPCR1_P,
3595 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3596 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BPCR1_P,
3597 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3598 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR0_P,
3599 UNI_TRAFFIC_FSCR0_ID, ie->fscr0);
3600 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR0_P,
3601 UNI_TRAFFIC_BSCR0_ID, ie->bscr0);
3602 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FSCR1_P,
3603 UNI_TRAFFIC_FSCR1_ID, ie->fscr1);
3604 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BSCR1_P,
3605 UNI_TRAFFIC_BSCR1_ID, ie->bscr1);
3606 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS0_P,
3607 UNI_TRAFFIC_FMBS0_ID, ie->fmbs0);
3608 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS0_P,
3609 UNI_TRAFFIC_BMBS0_ID, ie->bmbs0);
3610 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FMBS1_P,
3611 UNI_TRAFFIC_FMBS1_ID, ie->fmbs1);
3612 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BMBS1_P,
3613 UNI_TRAFFIC_BMBS1_ID, ie->bmbs1);
3614 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_FABR1_P,
3615 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3616 APP_OPT_24BIT(msg, present, UNI_TRAFFIC_BABR1_P,
3617 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3618
3619 APP_OPT(msg, present, UNI_TRAFFIC_BEST_P,
3620 UNI_TRAFFIC_BEST_ID);
3621 APP_OPT_BYTE(msg, present, UNI_TRAFFIC_MOPT_P,
3622 UNI_TRAFFIC_MOPT_ID,
3623 (ie->ftag ? UNI_TRAFFIC_FTAG : 0) |
3624 (ie->btag ? UNI_TRAFFIC_BTAG : 0) |
3625 (ie->fdisc ? UNI_TRAFFIC_FDISC : 0) |
3626 (ie->fdisc ? UNI_TRAFFIC_BDISC : 0));
3627
3628 return 0;
3629 }
3630
3631 static int
3632 decode_traffic_common(struct uni_xtraffic *ie, struct uni_msg *msg,
3633 u_int ielen, u_int *present)
3634 {
3635 u_char c;
3636
3637 while(ielen--) {
3638 switch(c = *msg->b_rptr++) {
3639
3640 default:
3641 rej:
3642 return -1;
3643
3644 DEC_GETF3(TRAFFIC_FPCR0, fpcr0, *present);
3645 DEC_GETF3(TRAFFIC_BPCR0, bpcr0, *present);
3646 DEC_GETF3(TRAFFIC_FPCR1, fpcr1, *present);
3647 DEC_GETF3(TRAFFIC_BPCR1, bpcr1, *present);
3648 DEC_GETF3(TRAFFIC_FSCR0, fscr0, *present);
3649 DEC_GETF3(TRAFFIC_BSCR0, bscr0, *present);
3650 DEC_GETF3(TRAFFIC_FSCR1, fscr1, *present);
3651 DEC_GETF3(TRAFFIC_BSCR1, bscr1, *present);
3652 DEC_GETF3(TRAFFIC_FMBS0, fmbs0, *present);
3653 DEC_GETF3(TRAFFIC_BMBS0, bmbs0, *present);
3654 DEC_GETF3(TRAFFIC_BMBS1, bmbs1, *present);
3655 DEC_GETF3(TRAFFIC_FABR1, fabr1, *present);
3656 DEC_GETF3(TRAFFIC_BABR1, babr1, *present);
3657
3658 case UNI_TRAFFIC_BEST_ID:
3659 *present |= UNI_TRAFFIC_BEST_P;
3660 break;
3661
3662 case UNI_TRAFFIC_MOPT_ID:
3663 if(ielen == 0)
3664 return -1;
3665 ielen--;
3666 if(!(*present & UNI_TRAFFIC_MOPT_P)) {
3667 *present |= UNI_TRAFFIC_MOPT_P;
3668 ie->ftag = (*msg->b_rptr&UNI_TRAFFIC_FTAG)?1:0;
3669 ie->btag = (*msg->b_rptr&UNI_TRAFFIC_BTAG)?1:0;
3670 ie->fdisc = (*msg->b_rptr&UNI_TRAFFIC_FDISC)?1:0;
3671 ie->bdisc = (*msg->b_rptr&UNI_TRAFFIC_BDISC)?1:0;
3672 }
3673 msg->b_rptr++;
3674 break;
3675 }
3676 }
3677 return 0;
3678 }
3679
3680
3681 /*****************************************************************/
3682
3683 DEF_IE_PRINT(itu, traffic)
3684 {
3685 if(uni_print_iehdr("traffic", &ie->h, cx))
3686 return;
3687 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3688 uni_print_ieend(cx);
3689 }
3690
3691 DEF_IE_CHECK(itu, traffic)
3692 {
3693 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3694 }
3695
3696 DEF_IE_ENCODE(itu, traffic)
3697 {
3698 START_IE(traffic, UNI_IE_TRAFFIC, 26);
3699 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3700 SET_IE_LEN(msg);
3701 return 0;
3702 }
3703
3704 DEF_IE_DECODE(itu, traffic)
3705 {
3706 IE_START(;);
3707
3708 if(ielen > 30)
3709 goto rej;
3710
3711 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3712 goto rej;
3713
3714 IE_END(TRAFFIC);
3715 }
3716
3717 /*****************************************************************/
3718
3719 DEF_IE_PRINT(itu, atraffic)
3720 {
3721 if(uni_print_iehdr("atraffic", &ie->h, cx))
3722 return;
3723 print_ie_traffic_common(cx, ie->h.present, &ie->t);
3724 uni_print_ieend(cx);
3725 }
3726
3727 DEF_IE_CHECK(itu, atraffic)
3728 {
3729 return check_ie_traffic_common(&ie->t, ie->h.present, cx);
3730 }
3731
3732 DEF_IE_ENCODE(itu, atraffic)
3733 {
3734 START_IE(traffic, UNI_IE_ATRAFFIC, 26);
3735 encode_traffic_common(msg, &ie->t, ie->h.present, cx);
3736 SET_IE_LEN(msg);
3737 return 0;
3738 }
3739
3740 DEF_IE_DECODE(itu, atraffic)
3741 {
3742 IE_START(;);
3743
3744 if(ielen > 30)
3745 goto rej;
3746
3747 if(decode_traffic_common(&ie->t, msg, ielen, &ie->h.present))
3748 goto rej;
3749
3750 IE_END(ATRAFFIC);
3751 }
3752
3753 /*****************************************************************/
3754
3755 DEF_IE_PRINT(itu, mintraffic)
3756 {
3757 if(uni_print_iehdr("mintraffic", &ie->h, cx))
3758 return;
3759
3760 uni_print_entry(cx, "pcr0", "(");
3761 if(ie->h.present & UNI_MINTRAFFIC_FPCR0_P)
3762 uni_printf(cx, "%u", ie->fpcr0);
3763 uni_putc(',', cx);
3764 if(ie->h.present & UNI_MINTRAFFIC_BPCR0_P)
3765 uni_printf(cx, "%u", ie->bpcr0);
3766 uni_putc(')', cx);
3767
3768 uni_print_entry(cx, "pcr1", "(");
3769 if(ie->h.present & UNI_MINTRAFFIC_FPCR1_P)
3770 uni_printf(cx, "%u", ie->fpcr1);
3771 uni_putc(',', cx);
3772 if(ie->h.present & UNI_MINTRAFFIC_BPCR1_P)
3773 uni_printf(cx, "%u", ie->bpcr1);
3774 uni_putc(')', cx);
3775
3776 uni_print_entry(cx, "abr1", "(");
3777 if(ie->h.present & UNI_MINTRAFFIC_FABR1_P)
3778 uni_printf(cx, "%u", ie->fabr1);
3779 uni_putc(',', cx);
3780 if(ie->h.present & UNI_MINTRAFFIC_BABR1_P)
3781 uni_printf(cx, "%u", ie->babr1);
3782 uni_printf(cx, ")");
3783
3784 uni_print_ieend(cx);
3785 }
3786
3787 DEF_IE_CHECK(itu, mintraffic)
3788 {
3789 u_int abr;
3790 u_int xbr;
3791 UNUSED(cx);
3792
3793 abr = ie->h.present & (UNI_MINTRAFFIC_FABR1_P|UNI_MINTRAFFIC_BABR1_P);
3794 xbr = ie->h.present & (UNI_MINTRAFFIC_FPCR0_P|UNI_MINTRAFFIC_BPCR0_P|
3795 UNI_MINTRAFFIC_FPCR1_P|UNI_MINTRAFFIC_BPCR1_P);
3796
3797 if(abr && xbr)
3798 return -1;
3799
3800 return 0;
3801 }
3802
3803 DEF_IE_ENCODE(itu, mintraffic)
3804 {
3805 START_IE(mintraffic, UNI_IE_MINTRAFFIC, 16);
3806
3807 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR0_P,
3808 UNI_TRAFFIC_FPCR0_ID, ie->fpcr0);
3809 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR0_P,
3810 UNI_TRAFFIC_BPCR0_ID, ie->bpcr0);
3811 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FPCR1_P,
3812 UNI_TRAFFIC_FPCR1_ID, ie->fpcr1);
3813 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BPCR1_P,
3814 UNI_TRAFFIC_BPCR1_ID, ie->bpcr1);
3815 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_FABR1_P,
3816 UNI_TRAFFIC_FABR1_ID, ie->fabr1);
3817 APP_OPT_24BIT(msg, ie->h.present, UNI_MINTRAFFIC_BABR1_P,
3818 UNI_TRAFFIC_BABR1_ID, ie->babr1);
3819
3820 SET_IE_LEN(msg);
3821 return 0;
3822 }
3823
3824 DEF_IE_DECODE(itu, mintraffic)
3825 {
3826 u_char c;
3827
3828 IE_START(;);
3829
3830 if(ielen > 20)
3831 goto rej;
3832
3833 while(ielen--) {
3834 switch(c = *msg->b_rptr++) {
3835
3836 default:
3837 goto rej;
3838
3839 DEC_GETF3(MINTRAFFIC_FPCR0, fpcr0, ie->h.present);
3840 DEC_GETF3(MINTRAFFIC_BPCR0, bpcr0, ie->h.present);
3841 DEC_GETF3(MINTRAFFIC_FPCR1, fpcr1, ie->h.present);
3842 DEC_GETF3(MINTRAFFIC_BPCR1, bpcr1, ie->h.present);
3843 DEC_GETF3(MINTRAFFIC_FABR1, fabr1, ie->h.present);
3844 DEC_GETF3(MINTRAFFIC_BABR1, babr1, ie->h.present);
3845 }
3846 }
3847
3848 IE_END(MINTRAFFIC);
3849 }
3850
3851 /*****************************************************************/
3852
3853 DEF_IE_PRINT(net, mdcr)
3854 {
3855 static const struct uni_print_tbl origin_tbl[] = {
3856 MKT(UNI_MDCR_ORIGIN_USER, user),
3857 MKT(UNI_MDCR_ORIGIN_NET, net),
3858 EOT()
3859 };
3860
3861 if(uni_print_iehdr("mdcr", &ie->h, cx))
3862 return;
3863
3864 uni_print_tbl("origin", ie->origin, origin_tbl, cx);
3865 uni_print_entry(cx, "mdcr", "(");
3866 uni_printf(cx, "%u", ie->fmdcr);
3867 uni_putc(',', cx);
3868 uni_printf(cx, "%u", ie->bmdcr);
3869 uni_putc(')', cx);
3870
3871 uni_print_ieend(cx);
3872 }
3873
3874 DEF_IE_CHECK(net, mdcr)
3875 {
3876 UNUSED(cx);
3877
3878 if ((ie->origin != UNI_MDCR_ORIGIN_USER &&
3879 ie->origin != UNI_MDCR_ORIGIN_NET) ||
3880 ie->fmdcr >= (1 << 24) || ie->bmdcr >= (1 << 24))
3881 return (-1);
3882
3883 return (0);
3884 }
3885
3886 DEF_IE_ENCODE(net, mdcr)
3887 {
3888 START_IE(mdcr, UNI_IE_MDCR, 9);
3889
3890 APP_BYTE(msg, ie->origin);
3891 APP_SUB_24BIT(msg, UNI_TRAFFIC_FMDCR_ID, ie->fmdcr);
3892 APP_SUB_24BIT(msg, UNI_TRAFFIC_BMDCR_ID, ie->bmdcr);
3893
3894 SET_IE_LEN(msg);
3895 return (0);
3896 }
3897
3898 DEF_IE_DECODE(net, mdcr)
3899 {
3900 u_char c;
3901 #define UNI_TRAFFIC_FMDCR_P 0x01
3902 #define UNI_TRAFFIC_BMDCR_P 0x02
3903 u_int p = 0;
3904
3905 IE_START(;);
3906
3907 if(ielen != 9)
3908 goto rej;
3909
3910 ie->origin = *msg->b_rptr++;
3911 ielen--;
3912
3913 while(ielen--) {
3914 switch(c = *msg->b_rptr++) {
3915
3916 default:
3917 goto rej;
3918
3919 DEC_GETF3(TRAFFIC_FMDCR, fmdcr, p);
3920 DEC_GETF3(TRAFFIC_BMDCR, bmdcr, p);
3921 }
3922 }
3923 if (p != (UNI_TRAFFIC_FMDCR_P | UNI_TRAFFIC_BMDCR_P))
3924 goto rej;
3925
3926 IE_END(MDCR);
3927 }
3928
3929 /*********************************************************************
3930 *
3931 * Connection identifier
3932 *
3933 * References for this IE are:
3934 *
3935 * Q.2931 pp. 69...70
3936 * UNI4.0 pp. 15...16
3937 * PNNI1.0 p. 198
3938 *
3939 * Only ITU-T coding allowed.
3940 */
3941
3942 DEF_IE_PRINT(itu, connid)
3943 {
3944 static const struct uni_print_tbl tbl[] = {
3945 MKT(UNI_CONNID_VCI, exclusive),
3946 MKT(UNI_CONNID_ANYVCI, any),
3947 MKT(UNI_CONNID_NOVCI, no),
3948 EOT()
3949 };
3950 static const struct uni_print_tbl assoc_tbl[] = {
3951 MKT(UNI_CONNID_ASSOC, associated),
3952 MKT(UNI_CONNID_NONASSOC,non-associated),
3953 EOT()
3954 };
3955
3956 if(uni_print_iehdr("connid", &ie->h, cx))
3957 return;
3958
3959 uni_print_tbl("mode", ie->assoc, assoc_tbl, cx);
3960 uni_print_entry(cx, "connid", "(%u,", ie->vpci);
3961 if(ie->type == UNI_CONNID_VCI)
3962 uni_printf(cx, "%u", ie->vci);
3963 else
3964 uni_print_tbl(NULL, ie->type, tbl, cx);
3965 uni_printf(cx, ")");
3966
3967 uni_print_ieend(cx);
3968 }
3969
3970 DEF_IE_CHECK(itu, connid)
3971 {
3972 UNUSED(cx);
3973 switch(ie->type) {
3974 default:
3975 return -1;
3976 case UNI_CONNID_VCI:
3977 case UNI_CONNID_ANYVCI:
3978 case UNI_CONNID_NOVCI:
3979 break;
3980 }
3981
3982 #if 0
3983 /*
3984 * This field must be checked by the application to fulfil
3985 * Q.2931Amd4 27) 5.2.3 last sentence
3986 */
3987 switch(ie->assoc) {
3988
3989 case UNI_CONNID_ASSOC:
3990 if(!cx->cx.pnni)
3991 return -1;
3992 break;
3993
3994 case UNI_CONNID_NONASSOC:
3995 break;
3996
3997 default:
3998 return -1;
3999 }
4000 #endif
4001 return 0;
4002 }
4003
4004 DEF_IE_ENCODE(itu, connid)
4005 {
4006 START_IE(connid, UNI_IE_CONNID, 5);
4007
4008 APP_BYTE(msg, 0x80 | (ie->assoc << 3) | ie->type);
4009 APP_BYTE(msg, ie->vpci >> 8);
4010 APP_BYTE(msg, ie->vpci >> 0);
4011 APP_BYTE(msg, ie->vci >> 8);
4012 APP_BYTE(msg, ie->vci >> 0);
4013
4014 SET_IE_LEN(msg);
4015 return 0;
4016 }
4017
4018 DEF_IE_DECODE(itu, connid)
4019 {
4020 u_char c;
4021
4022 IE_START(;);
4023
4024 if(ielen != 5)
4025 goto rej;
4026
4027 c = *msg->b_rptr++;
4028 if((c & 0x80) == 0)
4029 goto rej;
4030 ie->assoc = (c >> 3) & 3;
4031 ie->type = c & 7;
4032 ie->vpci = *msg->b_rptr++ << 8;
4033 ie->vpci |= *msg->b_rptr++;
4034 ie->vci = *msg->b_rptr++ << 8;
4035 ie->vci |= *msg->b_rptr++;
4036
4037 IE_END(CONNID);
4038 }
4039
4040 /*********************************************************************
4041 *
4042 * Quality of Service
4043 *
4044 * References for this IE are:
4045 *
4046 * Q.2931 pp. 72
4047 * UNI4.0 pp. 16...17
4048 */
4049
4050 static void
4051 print_qos(struct unicx *cx, struct uni_ie_qos *ie)
4052 {
4053 static const struct uni_print_tbl class_tbl[] = {
4054 MKT(UNI_QOS_CLASS0, Class0),
4055 MKT(UNI_QOS_CLASS1, Class1),
4056 MKT(UNI_QOS_CLASS2, Class2),
4057 MKT(UNI_QOS_CLASS3, Class3),
4058 MKT(UNI_QOS_CLASS4, Class4),
4059 EOT()
4060 };
4061
4062 if(uni_print_iehdr("qos", &ie->h, cx))
4063 return;
4064
4065 uni_print_tbl("fwd", ie->fwd, class_tbl, cx);
4066 uni_print_tbl("bwd", ie->bwd, class_tbl, cx);
4067
4068 uni_print_ieend(cx);
4069 }
4070
4071 DEF_IE_PRINT(itu, qos)
4072 {
4073 print_qos(cx, ie);
4074 }
4075 DEF_IE_PRINT(net, qos)
4076 {
4077 print_qos(cx, ie);
4078 }
4079
4080 DEF_IE_CHECK(itu, qos)
4081 {
4082 UNUSED(cx);
4083
4084 switch(ie->fwd) {
4085 default:
4086 return -1;
4087
4088 case UNI_QOS_CLASS0:
4089 break;
4090 }
4091 switch(ie->bwd) {
4092 default:
4093 return -1;
4094
4095 case UNI_QOS_CLASS0:
4096 break;
4097 }
4098 return 0;
4099 }
4100
4101 DEF_IE_CHECK(net, qos)
4102 {
4103 UNUSED(cx);
4104
4105 switch(ie->fwd) {
4106 default:
4107 return -1;
4108
4109 case UNI_QOS_CLASS1:
4110 case UNI_QOS_CLASS2:
4111 case UNI_QOS_CLASS3:
4112 case UNI_QOS_CLASS4:
4113 break;
4114 }
4115 switch(ie->bwd) {
4116 default:
4117 return -1;
4118
4119 case UNI_QOS_CLASS1:
4120 case UNI_QOS_CLASS2:
4121 case UNI_QOS_CLASS3:
4122 case UNI_QOS_CLASS4:
4123 break;
4124 }
4125 return 0;
4126 }
4127
4128 DEF_IE_ENCODE(itu, qos)
4129 {
4130 START_IE(qos, UNI_IE_QOS, 2);
4131
4132 APP_BYTE(msg, ie->fwd);
4133 APP_BYTE(msg, ie->bwd);
4134
4135 SET_IE_LEN(msg);
4136 return 0;
4137 }
4138 DEF_IE_ENCODE(net, qos)
4139 {
4140 START_IE(qos, UNI_IE_QOS, 2);
4141
4142 APP_BYTE(msg, ie->fwd);
4143 APP_BYTE(msg, ie->bwd);
4144
4145 SET_IE_LEN(msg);
4146 return 0;
4147 }
4148
4149 DEF_IE_DECODE(itu, qos)
4150 {
4151 IE_START(;);
4152
4153 if(ielen != 2)
4154 goto rej;
4155
4156 ie->fwd = *msg->b_rptr++;
4157 ie->bwd = *msg->b_rptr++;
4158
4159 IE_END(QOS);
4160 }
4161
4162 DEF_IE_DECODE(net, qos)
4163 {
4164 IE_START(;);
4165
4166 if(ielen != 2)
4167 goto rej;
4168
4169 ie->fwd = *msg->b_rptr++;
4170 ie->bwd = *msg->b_rptr++;
4171
4172 IE_END(QOS);
4173 }
4174
4175 /*********************************************************************
4176 *
4177 * Broadband Lower Layer Information
4178 *
4179 * References for this IE are:
4180 *
4181 * Q.2931 pp. 53...54
4182 * UNI4.0 p. 12
4183 *
4184 * Only ITU-T coding allowed.
4185 */
4186
4187 DEF_IE_PRINT(itu, bhli)
4188 {
4189 static const struct uni_print_tbl type_tbl[] = {
4190 MKT(UNI_BHLI_ISO, iso),
4191 MKT(UNI_BHLI_USER, user),
4192 MKT(UNI_BHLI_VENDOR, vendor),
4193 EOT()
4194 };
4195 u_int i;
4196
4197 if(uni_print_iehdr("bhli", &ie->h, cx))
4198 return;
4199
4200 uni_print_tbl("type", ie->type, type_tbl, cx);
4201 uni_print_entry(cx, "len", "%d", ie->len);
4202 uni_print_entry(cx, "info", "(");
4203 for(i = 0; i < ie->len; i++)
4204 uni_printf(cx, ",0x%02x", ie->info[i]);
4205 uni_printf(cx, ")");
4206
4207 uni_print_ieend(cx);
4208 }
4209
4210 DEF_IE_CHECK(itu, bhli)
4211 {
4212 UNUSED(cx);
4213
4214 switch(ie->type) {
4215 default:
4216 return -1;
4217
4218 case UNI_BHLI_ISO:
4219 case UNI_BHLI_USER:
4220 case UNI_BHLI_VENDOR:
4221 break;
4222 }
4223 if(ie->len > 8)
4224 return -1;
4225
4226 return 0;
4227 }
4228
4229 DEF_IE_ENCODE(itu, bhli)
4230 {
4231 START_IE(bhli, UNI_IE_BHLI, 9);
4232
4233 APP_BYTE(msg, 0x80 | ie->type);
4234 APP_BUF(msg, ie->info, ie->len);
4235
4236 SET_IE_LEN(msg);
4237 return 0;
4238 }
4239
4240 DEF_IE_DECODE(itu, bhli)
4241 {
4242 u_char c;
4243
4244 IE_START(;);
4245
4246 if(ielen > 9)
4247 goto rej;
4248
4249 c = *msg->b_rptr++;
4250 ielen--;
4251
4252 if(!(c & 0x80))
4253 goto rej;
4254 ie->type = c & 0x7f;
4255 ie->len = ielen;
4256 (void)memcpy(ie->info, msg->b_rptr, ielen);
4257 msg->b_rptr += ielen;
4258
4259 IE_END(BHLI);
4260 }
4261
4262 /*********************************************************************
4263 *
4264 * Broadband bearer capabilities
4265 *
4266 * References for this IE are:
4267 *
4268 * Q.2931 pp. 51...52
4269 * Q.2931 Amd 1
4270 * UNI4.0 pp. 10...12, 106...109
4271 *
4272 * UNI4.0 changed the meaning of byte 5a. Instead of 3 bit traffic type and
4273 * 2 bit timing requirements there are now 7 bits ATM transfer capabilities.
4274 * However the old format is still supported: it should be recognized on
4275 * input, but never be generated on output. Mapping is left to the user of
4276 * UNI.
4277 *
4278 * Amd 1 not checked XXX.
4279 *
4280 * The Appendix in UNI4.0 lists all the supported combinations of various
4281 * traffic IE's. The check function implements part of it.
4282 *
4283 * A C X VP
4284 * 1 CBR.1 7 . 7 7
4285 * 2 CBR.2 - . 4,5,6 5 (*)
4286 * 3 CBR.3 - . 4,5,6 5 (*)
4287 * 4 rt-VBR.1 . 19 19 19
4288 * 5 rt-VBR.2 . 9 1,9 9
4289 * 6 rt-VBR.3 . 9 1,9 9
4290 * 7 rt-VBR.4 . . 1,9 . (*)
4291 * 8 rt-VBR.5 . . 1,9 . (*)
4292 * 9 rt-VBR.6 . 9 1,9 9 (*)
4293 * 10 nrt-VBR.1 . 11 11 11
4294 * 11 nrt-VBR.2 . - -,0,2,8,10 -,10
4295 * 12 nrt-VBR.3 . - -,0,2,8,10 -,10
4296 * 13 nrt-VBR.4 . - -,0,2,8,10 . (*)
4297 * 14 nrt-VBR.5 . - -,0,2,8,10 . (*)
4298 * 15 nrt-VBR.6 . - -,0,2,8,10 -,10(*)
4299 * 16 ABR . 12 12 12
4300 * 17 UBR.1 . - -,0,2,8,10 -,10
4301 * 18 UBR.2 . - -,0,2,8,10 -,10
4302 *
4303 * (*) compatibility
4304 *
4305 * Only ITU-T coding allowed.
4306 */
4307
4308 DEF_IE_PRINT(itu, bearer)
4309 {
4310 static const struct uni_print_tbl bclass_tbl[] = {
4311 MKT(UNI_BEARER_A, bcob-A),
4312 MKT(UNI_BEARER_C, bcob-C),
4313 MKT(UNI_BEARER_X, bcob-X),
4314 MKT(UNI_BEARER_TVP, transparent-VP),
4315 EOT()
4316 };
4317 static const struct uni_print_tbl atc_tbl[] = {
4318 MKT(UNI_BEARER_ATC_CBR, cbr),
4319 MKT(UNI_BEARER_ATC_CBR1, cbr1),
4320 MKT(UNI_BEARER_ATC_VBR, vbr),
4321 MKT(UNI_BEARER_ATC_VBR1, vbr1),
4322 MKT(UNI_BEARER_ATC_NVBR, nvbr),
4323 MKT(UNI_BEARER_ATC_NVBR1, nvbr1),
4324 MKT(UNI_BEARER_ATC_ABR, abr),
4325
4326 MKT(UNI_BEARER_ATCX_0, x0),
4327 MKT(UNI_BEARER_ATCX_1, x1),
4328 MKT(UNI_BEARER_ATCX_2, x2),
4329 MKT(UNI_BEARER_ATCX_4, x4),
4330 MKT(UNI_BEARER_ATCX_6, x6),
4331 MKT(UNI_BEARER_ATCX_8, x8),
4332 EOT()
4333 };
4334 static const struct uni_print_tbl cfg_tbl[] = {
4335 MKT(UNI_BEARER_P2P, p2p),
4336 MKT(UNI_BEARER_MP, mp),
4337 EOT()
4338 };
4339 static const struct uni_print_tbl clip_tbl[] = {
4340 MKT(UNI_BEARER_NOCLIP, no),
4341 MKT(UNI_BEARER_CLIP, yes),
4342 EOT()
4343 };
4344
4345 if(uni_print_iehdr("bearer", &ie->h, cx))
4346 return;
4347
4348 uni_print_tbl("class", ie->bclass, bclass_tbl, cx);
4349
4350 if(ie->h.present & UNI_BEARER_ATC_P) {
4351 uni_print_tbl("atc", ie->atc, atc_tbl, cx);
4352 }
4353 uni_print_tbl("clip", ie->clip, clip_tbl, cx);
4354 uni_print_tbl("cfg", ie->cfg, cfg_tbl, cx);
4355
4356 uni_print_ieend(cx);
4357 }
4358
4359 #define QTYPE(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATC_##A)
4360 #define QTYPEX(C,A) ((UNI_BEARER_##C << 8) | UNI_BEARER_ATCX_##A)
4361 #define QTYPE0(C) ((UNI_BEARER_##C << 8) | (1 << 16))
4362 DEF_IE_CHECK(itu, bearer)
4363 {
4364 UNUSED(cx);
4365
4366 switch((ie->bclass << 8) |
4367 ((ie->h.present & UNI_BEARER_ATC_P) == 0
4368 ? (1 << 16)
4369 : ie->atc)) {
4370
4371 default:
4372 return -1;
4373
4374 case QTYPE (A, CBR1): /* 1 */
4375 case QTYPE (X, CBR1): /* 1 */
4376 case QTYPE (TVP, CBR1): /* 1 */
4377
4378 case QTYPE0(A): /* 2,3 */
4379 case QTYPEX(X, 4): /* 2,3 */
4380 case QTYPE (X, CBR): /* 2,3 */
4381 case QTYPEX(X, 6): /* 2,3 */
4382 case QTYPE (TVP, CBR): /* 2,3 */
4383
4384 case QTYPE (C, VBR1): /* 4 */
4385 case QTYPE (X, VBR1): /* 4 */
4386 case QTYPE (TVP, VBR1): /* 4 */
4387
4388 case QTYPE (C, VBR): /* 5,6,9 */
4389 case QTYPEX(X, 1): /* 5,6,7,8,9 */
4390 case QTYPE (X, VBR): /* 5,6,7,8,9 */
4391 case QTYPE (TVP, VBR): /* 5,6,9 */
4392
4393 case QTYPE (C, NVBR1): /* 10 */
4394 case QTYPE (X, NVBR1): /* 10 */
4395 case QTYPE (TVP, NVBR1): /* 10 */
4396
4397 case QTYPE0(C): /* 11,12,13,14,15,17,18 */
4398 case QTYPE0(X): /* 11,12,13,14,15,17,18 */
4399 case QTYPEX(X, 0): /* 11,12,13,14,15,17,18 */
4400 case QTYPEX(X, 2): /* 11,12,13,14,15,17,18 */
4401 case QTYPEX(X, 8): /* 11,12,13,14,15,17,18 */
4402 case QTYPE (X, NVBR): /* 11,12,13,14,15,17,18 */
4403 case QTYPE0(TVP): /* 11,12,15,17,18 */
4404 case QTYPE (TVP, NVBR): /* 11,12,15,17,18 */
4405
4406 case QTYPE (C, ABR): /* 16 */
4407 case QTYPE (X, ABR): /* 16 */
4408 case QTYPE (TVP, ABR): /* 16 */
4409 break;
4410 }
4411
4412 switch(ie->clip) {
4413 default:
4414 return -1;
4415
4416 case UNI_BEARER_NOCLIP:
4417 case UNI_BEARER_CLIP:
4418 break;
4419 }
4420 switch(ie->cfg) {
4421 default:
4422 return -1;
4423
4424 case UNI_BEARER_P2P:
4425 case UNI_BEARER_MP:
4426 break;
4427 }
4428
4429 return 0;
4430 }
4431 #undef QTYPE
4432 #undef QTYPEX
4433 #undef QTYPE0
4434
4435 DEF_IE_ENCODE(itu, bearer)
4436 {
4437 START_IE(bearer, UNI_IE_BEARER, 3);
4438
4439 APP_BYTE(msg, ie->bclass |
4440 ((ie->h.present & UNI_BEARER_ATC_P) ? 0:0x80));
4441 APP_OPT(msg, ie->h.present, UNI_BEARER_ATC_P,
4442 0x80 | ie->atc);
4443 APP_BYTE(msg, 0x80 | (ie->clip << 5) | ie->cfg);
4444
4445 SET_IE_LEN(msg);
4446 return 0;
4447 }
4448
4449 DEF_IE_DECODE(itu, bearer)
4450 {
4451 u_char c;
4452
4453 IE_START(;);
4454
4455 if(ielen != 2 && ielen != 3)
4456 goto rej;
4457
4458 c = *msg->b_rptr++;
4459 ielen--;
4460 ie->bclass = c & 0x1f;
4461 if(!(c & 0x80)) {
4462 c = *msg->b_rptr++;
4463 ielen--;
4464 ie->h.present |= UNI_BEARER_ATC_P;
4465
4466 switch(c & 0x7f) {
4467 /*
4468 * Real legal values
4469 */
4470 case UNI_BEARER_ATC_CBR:
4471 case UNI_BEARER_ATC_CBR1:
4472 case UNI_BEARER_ATC_VBR:
4473 case UNI_BEARER_ATC_VBR1:
4474 case UNI_BEARER_ATC_NVBR:
4475 case UNI_BEARER_ATC_NVBR1:
4476 case UNI_BEARER_ATC_ABR:
4477 break;
4478
4479 /*
4480 * Compat values
4481 */
4482 case UNI_BEARER_ATCX_0:
4483 case UNI_BEARER_ATCX_1:
4484 case UNI_BEARER_ATCX_2:
4485 case UNI_BEARER_ATCX_4:
4486 case UNI_BEARER_ATCX_6:
4487 case UNI_BEARER_ATCX_8:
4488 break;
4489
4490 default:
4491 goto rej;
4492 }
4493
4494 if(!(c & 0x80))
4495 goto rej;
4496
4497 ie->atc = c & 0x7f;
4498 }
4499 if(ielen == 0)
4500 goto rej;
4501 c = *msg->b_rptr++;
4502 ielen--;
4503 if(!(c & 0x80))
4504 goto rej;
4505 ie->clip = (c >> 5) & 0x3;
4506 ie->cfg = c & 0x3;
4507
4508 IE_END(BEARER);
4509 }
4510
4511 /*********************************************************************
4512 *
4513 * Broadband Lower Layer Information
4514 *
4515 * References for this IE are:
4516 *
4517 * Q.2931 pp. 54...59
4518 * UNI4.0 pp. 12...14
4519 *
4520 * UNI4.0 states, that layer 1 info is not supported.
4521 * We allow a layer 1 protocol identifier.
4522 *
4523 * UNI4.0 states, that the layer information subelements are NOT position
4524 * dependent. We allow them in any order on input, but generate always the
4525 * definit order on output.
4526 *
4527 * Only ITU-T coding allowed.
4528 */
4529
4530 DEF_IE_PRINT(itu, blli)
4531 {
4532 static const struct uni_print_tbl l2_tbl[] = {
4533 MKT(UNI_BLLI_L2_BASIC, basic),
4534 MKT(UNI_BLLI_L2_Q921, Q921),
4535 MKT(UNI_BLLI_L2_X25LL, X25-LL),
4536 MKT(UNI_BLLI_L2_X25ML, X25-ML),
4537 MKT(UNI_BLLI_L2_LABP, LAPB),
4538 MKT(UNI_BLLI_L2_HDLC_ARM, HDLC-ARM),
4539 MKT(UNI_BLLI_L2_HDLC_NRM, HDLC-NRM),
4540 MKT(UNI_BLLI_L2_HDLC_ABM, HDLC-ABM),
4541 MKT(UNI_BLLI_L2_LAN, LAN),
4542 MKT(UNI_BLLI_L2_X75, X75),
4543 MKT(UNI_BLLI_L2_Q922, Q922),
4544 MKT(UNI_BLLI_L2_USER, user),
4545 MKT(UNI_BLLI_L2_ISO7776, ISO7776),
4546 EOT()
4547 };
4548 static const struct uni_print_tbl l2mode_tbl[] = {
4549 MKT(UNI_BLLI_L2NORM, normal),
4550 MKT(UNI_BLLI_L2EXT, extended),
4551 EOT()
4552 };
4553 static const struct uni_print_tbl l3_tbl[] = {
4554 MKT(UNI_BLLI_L3_X25, X25),
4555 MKT(UNI_BLLI_L3_ISO8208, ISO8208),
4556 MKT(UNI_BLLI_L3_X223, X223),
4557 MKT(UNI_BLLI_L3_CLMP, CLMP),
4558 MKT(UNI_BLLI_L3_T70, T70),
4559 MKT(UNI_BLLI_L3_TR9577, TR9577),
4560 MKT(UNI_BLLI_L3_USER, user),
4561 MKT(UNI_BLLI_L3_H310, H310),
4562 MKT(UNI_BLLI_L3_H321, H321),
4563 EOT()
4564 };
4565 static const struct uni_print_tbl l3mode_tbl[] = {
4566 MKT(UNI_BLLI_L3NSEQ, normal-seq),
4567 MKT(UNI_BLLI_L3ESEQ, extended-seq),
4568 EOT()
4569 };
4570 static const struct uni_print_tbl l3psiz_tbl[] = {
4571 MKT(UNI_BLLI_L3_16, 16),
4572 MKT(UNI_BLLI_L3_32, 32),
4573 MKT(UNI_BLLI_L3_64, 64),
4574 MKT(UNI_BLLI_L3_128, 128),
4575 MKT(UNI_BLLI_L3_256, 256),
4576 MKT(UNI_BLLI_L3_512, 512),
4577 MKT(UNI_BLLI_L3_1024, 1024),
4578 MKT(UNI_BLLI_L3_2048, 2048),
4579 MKT(UNI_BLLI_L3_4096, 4096),
4580 EOT()
4581 };
4582 static const struct uni_print_tbl l3ttype_tbl[] = {
4583 MKT(UNI_BLLI_L3_TTYPE_RECV, receive_only),
4584 MKT(UNI_BLLI_L3_TTYPE_SEND, send_only),
4585 MKT(UNI_BLLI_L3_TTYPE_BOTH, both),
4586 EOT()
4587 };
4588 static const struct uni_print_tbl l3mux_tbl[] = {
4589 MKT(UNI_BLLI_L3_MUX_NOMUX, NOMUX),
4590 MKT(UNI_BLLI_L3_MUX_TS, TS),
4591 MKT(UNI_BLLI_L3_MUX_TSFEC, TSFEC),
4592 MKT(UNI_BLLI_L3_MUX_PS, PS),
4593 MKT(UNI_BLLI_L3_MUX_PSFEC, PSFEC),
4594 MKT(UNI_BLLI_L3_MUX_H221, H221),
4595 EOT()
4596 };
4597 static const struct uni_print_tbl l3tcap_tbl[] = {
4598 MKT(UNI_BLLI_L3_TCAP_NOIND, noind),
4599 MKT(UNI_BLLI_L3_TCAP_AAL1, aal1),
4600 MKT(UNI_BLLI_L3_TCAP_AAL5, aal5),
4601 MKT(UNI_BLLI_L3_TCAP_AAL15, aal1&5),
4602 EOT()
4603 };
4604
4605 if(uni_print_iehdr("blli", &ie->h, cx))
4606 return;
4607
4608 if(ie->h.present & UNI_BLLI_L1_P) {
4609 uni_print_entry(cx, "l1", "%u", ie->l1);
4610 uni_print_eol(cx);
4611 }
4612 if(ie->h.present & UNI_BLLI_L2_P) {
4613 uni_print_tbl("l2", ie->l2, l2_tbl, cx);
4614 uni_print_push_prefix("l2", cx);
4615 cx->indent++;
4616 if(ie->h.present & UNI_BLLI_L2_USER_P)
4617 uni_print_entry(cx, "proto", "%u", ie->l2_user);
4618 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4619 uni_print_entry(cx, "q933", "%u", ie->l2_q933);
4620 uni_print_tbl("mode", ie->l2_mode, l2mode_tbl, cx);
4621 }
4622 if(ie->h.present & UNI_BLLI_L2_WSIZ_P)
4623 uni_print_entry(cx, "wsize", "%u", ie->l2_wsiz);
4624 uni_print_pop_prefix(cx);
4625 cx->indent--;
4626 uni_print_eol(cx);
4627
4628 }
4629 if(ie->h.present & UNI_BLLI_L3_P) {
4630 uni_print_tbl("l3", ie->l3, l3_tbl, cx);
4631 uni_print_push_prefix("l3", cx);
4632 cx->indent++;
4633 if(ie->h.present & UNI_BLLI_L3_USER_P)
4634 uni_print_entry(cx, "proto", "%u", ie->l3_user);
4635 if(ie->h.present & UNI_BLLI_L3_MODE_P)
4636 uni_print_tbl("mode", ie->l3_mode, l3mode_tbl, cx);
4637 if(ie->h.present & UNI_BLLI_L3_PSIZ_P)
4638 uni_print_tbl("packet-size", ie->l3_psiz, l3psiz_tbl, cx);
4639 if(ie->h.present & UNI_BLLI_L3_WSIZ_P)
4640 uni_print_entry(cx, "window-size", "%u", ie->l3_wsiz);
4641 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4642 uni_print_tbl("ttype", ie->l3_ttype, l3ttype_tbl, cx);
4643 uni_print_tbl("tcap", ie->l3_tcap, l3tcap_tbl, cx);
4644 }
4645 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4646 uni_print_tbl("fmux", ie->l3_fmux, l3mux_tbl, cx);
4647 uni_print_tbl("bmux", ie->l3_bmux, l3mux_tbl, cx);
4648 }
4649 if(ie->h.present & UNI_BLLI_L3_IPI_P)
4650 uni_print_entry(cx, "ipi", "0x%02x", ie->l3_ipi);
4651 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4652 uni_print_entry(cx, "snap", "%06x.%04x", ie->oui, ie->pid);
4653 uni_print_pop_prefix(cx);
4654 cx->indent--;
4655 uni_print_eol(cx);
4656 }
4657
4658 uni_print_ieend(cx);
4659 }
4660
4661 DEF_IE_CHECK(itu, blli)
4662 {
4663 UNUSED(cx);
4664 /*
4665 if(ie->h.present & UNI_BLLI_L1_P)
4666 ;
4667 */
4668
4669 if(ie->h.present & UNI_BLLI_L2_P) {
4670 static u_int mask =
4671 UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P |
4672 UNI_BLLI_L2_USER_P;
4673
4674 switch(ie->l2) {
4675 default:
4676 return -1;
4677
4678 case UNI_BLLI_L2_BASIC:
4679 case UNI_BLLI_L2_Q921:
4680 case UNI_BLLI_L2_LABP:
4681 case UNI_BLLI_L2_LAN:
4682 case UNI_BLLI_L2_X75:
4683 if(ie->h.present & mask)
4684 return -1;
4685 break;
4686
4687 case UNI_BLLI_L2_X25LL:
4688 case UNI_BLLI_L2_X25ML:
4689 case UNI_BLLI_L2_HDLC_ARM:
4690 case UNI_BLLI_L2_HDLC_NRM:
4691 case UNI_BLLI_L2_HDLC_ABM:
4692 case UNI_BLLI_L2_Q922:
4693 case UNI_BLLI_L2_ISO7776:
4694 switch(ie->h.present & mask) {
4695 default:
4696 return -1;
4697
4698 case 0:
4699 case UNI_BLLI_L2_Q933_P:
4700 case UNI_BLLI_L2_Q933_P | UNI_BLLI_L2_WSIZ_P:
4701 break;
4702 }
4703 break;
4704
4705 case UNI_BLLI_L2_USER:
4706 switch(ie->h.present & mask) {
4707 default:
4708 return -1;
4709
4710 case 0: /* XXX ? */
4711 case UNI_BLLI_L2_USER_P:
4712 break;
4713 }
4714 break;
4715 }
4716 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4717 if(ie->l2_q933 != 0)
4718 return -1;
4719
4720 switch(ie->l2_mode) {
4721 default:
4722 return -1;
4723
4724 case UNI_BLLI_L2NORM:
4725 case UNI_BLLI_L2EXT:
4726 break;
4727 }
4728 }
4729 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4730 if(ie->l2_wsiz == 0 || ie->l2_wsiz > 127)
4731 return -1;
4732 }
4733 if(ie->h.present & UNI_BLLI_L2_USER_P) {
4734 if(ie->l2_user > 127)
4735 return -1;
4736 }
4737 }
4738 if(ie->h.present & UNI_BLLI_L3_P) {
4739 static u_int mask =
4740 UNI_BLLI_L3_MODE_P | UNI_BLLI_L3_PSIZ_P |
4741 UNI_BLLI_L3_WSIZ_P | UNI_BLLI_L3_USER_P |
4742 UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P |
4743 UNI_BLLI_L3_TTYPE_P | UNI_BLLI_L3_MUX_P;
4744
4745 switch(ie->l3) {
4746 default:
4747 return -1;
4748
4749 case UNI_BLLI_L3_X25:
4750 case UNI_BLLI_L3_ISO8208:
4751 case UNI_BLLI_L3_X223:
4752 switch(ie->h.present & mask) {
4753 default:
4754 return -1;
4755
4756 case 0:
4757 case UNI_BLLI_L3_MODE_P:
4758 case UNI_BLLI_L3_MODE_P |
4759 UNI_BLLI_L3_PSIZ_P:
4760 case UNI_BLLI_L3_MODE_P |
4761 UNI_BLLI_L3_PSIZ_P |
4762 UNI_BLLI_L3_WSIZ_P:
4763 break;
4764 }
4765 break;
4766
4767 case UNI_BLLI_L3_CLMP:
4768 case UNI_BLLI_L3_T70:
4769 if(ie->h.present & mask)
4770 return -1;
4771 break;
4772
4773 case UNI_BLLI_L3_TR9577:
4774 switch(ie->h.present & mask) {
4775 default:
4776 return -1;
4777
4778 case 0:
4779 case UNI_BLLI_L3_IPI_P:
4780 case UNI_BLLI_L3_IPI_P | UNI_BLLI_L3_SNAP_P:
4781 break;
4782 }
4783 break;
4784
4785 case UNI_BLLI_L3_H310:
4786 switch(ie->h.present & mask) {
4787 default:
4788 return -1;
4789
4790 case 0:
4791 case UNI_BLLI_L3_TTYPE_P:
4792 case UNI_BLLI_L3_TTYPE_P|UNI_BLLI_L3_MUX_P:
4793 break;
4794 }
4795 break;
4796
4797 case UNI_BLLI_L3_USER:
4798 switch(ie->h.present & mask) {
4799 default:
4800 return -1;
4801
4802 case 0: /* XXX ? */
4803 case UNI_BLLI_L3_USER_P:
4804 break;
4805 }
4806 break;
4807 }
4808 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4809 switch(ie->l3_mode) {
4810 default:
4811 return -1;
4812
4813 case UNI_BLLI_L3NSEQ:
4814 case UNI_BLLI_L3ESEQ:
4815 break;
4816 }
4817 }
4818 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4819 switch(ie->l3_psiz) {
4820 default:
4821 return -1;
4822
4823 case UNI_BLLI_L3_16:
4824 case UNI_BLLI_L3_32:
4825 case UNI_BLLI_L3_64:
4826 case UNI_BLLI_L3_128:
4827 case UNI_BLLI_L3_256:
4828 case UNI_BLLI_L3_512:
4829 case UNI_BLLI_L3_1024:
4830 case UNI_BLLI_L3_2048:
4831 case UNI_BLLI_L3_4096:
4832 break;
4833 }
4834 }
4835 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4836 if(ie->l3_wsiz == 0 || ie->l3_wsiz > 127)
4837 return -1;
4838 }
4839 if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4840 if(ie->l3_ipi == UNI_BLLI_L3_SNAP) {
4841 if(!(ie->h.present & UNI_BLLI_L3_SNAP_P))
4842 return -1;
4843 } else {
4844 if(ie->h.present & UNI_BLLI_L3_SNAP_P)
4845 return -1;
4846 }
4847 }
4848 if(ie->h.present & UNI_BLLI_L3_USER_P) {
4849 if(ie->l3_user > 127)
4850 return -1;
4851 }
4852 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4853 if(ie->oui >= (1<<24))
4854 return -1;
4855 if(ie->pid >= (1<<16))
4856 return -1;
4857 }
4858 if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4859 switch(ie->l3_ttype) {
4860 default:
4861 return -1;
4862
4863 case UNI_BLLI_L3_TTYPE_RECV:
4864 case UNI_BLLI_L3_TTYPE_SEND:
4865 case UNI_BLLI_L3_TTYPE_BOTH:
4866 break;
4867 }
4868 switch(ie->l3_tcap) {
4869 default:
4870 return -1;
4871
4872 case UNI_BLLI_L3_TCAP_NOIND:
4873 case UNI_BLLI_L3_TCAP_AAL1:
4874 case UNI_BLLI_L3_TCAP_AAL5:
4875 case UNI_BLLI_L3_TCAP_AAL15:
4876 break;
4877 }
4878 }
4879 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4880 switch(ie->l3_fmux) {
4881 default:
4882 return -1;
4883
4884 case UNI_BLLI_L3_MUX_NOMUX:
4885 case UNI_BLLI_L3_MUX_TS:
4886 case UNI_BLLI_L3_MUX_TSFEC:
4887 case UNI_BLLI_L3_MUX_PS:
4888 case UNI_BLLI_L3_MUX_PSFEC:
4889 case UNI_BLLI_L3_MUX_H221:
4890 break;
4891 }
4892 switch(ie->l3_bmux) {
4893 default:
4894 return -1;
4895
4896 case UNI_BLLI_L3_MUX_NOMUX:
4897 case UNI_BLLI_L3_MUX_TS:
4898 case UNI_BLLI_L3_MUX_TSFEC:
4899 case UNI_BLLI_L3_MUX_PS:
4900 case UNI_BLLI_L3_MUX_PSFEC:
4901 case UNI_BLLI_L3_MUX_H221:
4902 break;
4903 }
4904 }
4905 }
4906
4907 return 0;
4908 }
4909
4910 DEF_IE_ENCODE(itu, blli)
4911 {
4912 START_IE(blli, UNI_IE_BLLI, 13);
4913
4914 if (IE_ISERROR(*ie)) {
4915 APP_BYTE(msg, 0xff);
4916 APP_BYTE(msg, 0xff);
4917 goto out;
4918 }
4919
4920 if(ie->h.present & UNI_BLLI_L1_P)
4921 APP_BYTE(msg, (UNI_BLLI_L1_ID<<5)|ie->l1|0x80);
4922
4923 if(ie->h.present & UNI_BLLI_L2_P) {
4924 if(ie->h.present & UNI_BLLI_L2_Q933_P) {
4925 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4926 if(ie->h.present & UNI_BLLI_L2_WSIZ_P) {
4927 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933);
4928 APP_BYTE(msg, ie->l2_wsiz | 0x80);
4929 } else {
4930 APP_BYTE(msg, (ie->l2_mode<<5)|ie->l2_q933|0x80);
4931 }
4932 } else if(ie->h.present & UNI_BLLI_L2_USER_P) {
4933 APP_BYTE(msg, (UNI_BLLI_L2_ID<<5)|ie->l2);
4934 APP_BYTE(msg, ie->l2_user | 0x80);
4935 } else {
4936 APP_BYTE(msg, (UNI_BLLI_L2_ID << 5) | ie->l2 | 0x80);
4937 }
4938 }
4939
4940 if(ie->h.present & UNI_BLLI_L3_P) {
4941 if(ie->h.present & UNI_BLLI_L3_MODE_P) {
4942 if(ie->h.present & UNI_BLLI_L3_PSIZ_P) {
4943 if(ie->h.present & UNI_BLLI_L3_WSIZ_P) {
4944 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4945 APP_BYTE(msg,(ie->l3_mode<<5));
4946 APP_BYTE(msg,ie->l3_psiz);
4947 APP_BYTE(msg,ie->l3_wsiz|0x80);
4948 } else {
4949 APP_BYTE(msg,(UNI_BLLI_L3_ID<<5)|ie->l3);
4950 APP_BYTE(msg,(ie->l3_mode<<5));
4951 APP_BYTE(msg,(ie->l3_psiz|0x80));
4952 }
4953 } else {
4954 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4955 APP_BYTE(msg, (ie->l3_mode<<5)|0x80);
4956 }
4957 } else if(ie->h.present & UNI_BLLI_L3_USER_P) {
4958 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4959 APP_BYTE(msg,(ie->l3_user|0x80));
4960 } else if(ie->h.present & UNI_BLLI_L3_IPI_P) {
4961 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3);
4962 APP_BYTE(msg,((ie->l3_ipi>>1) & 0x7f));
4963 APP_BYTE(msg,(((ie->l3_ipi&1)<<6)|0x80));
4964 if(ie->h.present & UNI_BLLI_L3_SNAP_P) {
4965 APP_BYTE(msg, 0x80);
4966 APP_BYTE(msg, (ie->oui >> 16));
4967 APP_BYTE(msg, (ie->oui >> 8));
4968 APP_BYTE(msg, (ie->oui >> 0));
4969 APP_BYTE(msg, (ie->pid >> 8));
4970 APP_BYTE(msg, (ie->pid >> 0));
4971 }
4972 } else if(ie->h.present & UNI_BLLI_L3_TTYPE_P) {
4973 if(ie->h.present & UNI_BLLI_L3_MUX_P) {
4974 APP_BYTE(msg, ie->l3_ttype | (ie->l3_tcap << 4));
4975 APP_BYTE(msg, 0x80 | (ie->l3_fmux << 3) | ie->l3_bmux);
4976 } else {
4977 APP_BYTE(msg, 0x80 | ie->l3_ttype | (ie->l3_tcap << 4));
4978 }
4979 } else {
4980 APP_BYTE(msg, (UNI_BLLI_L3_ID<<5)|ie->l3|0x80);
4981 }
4982 }
4983
4984 out:
4985 SET_IE_LEN(msg);
4986 return 0;
4987 }
4988
4989 DEF_IE_DECODE(itu, blli)
4990 {
4991 u_char c;
4992
4993 IE_START(;);
4994
4995 if(ielen > 17)
4996 goto rej;
4997
4998 while(ielen--) {
4999 switch(((c = *msg->b_rptr++) >> 5) & 0x3) {
5000 default:
5001 goto rej;
5002
5003 case UNI_BLLI_L1_ID:
5004 ie->h.present |= UNI_BLLI_L1_P;
5005 ie->l1 = c & 0x1f;
5006 if(!(c & 0x80))
5007 goto rej;
5008 break;
5009
5010 case UNI_BLLI_L2_ID:
5011 ie->h.present |= UNI_BLLI_L2_P;
5012 ie->l2 = c & 0x1f;
5013 if(!(c & 0x80)) {
5014 if(ielen == 0)
5015 goto rej;
5016 ielen--;
5017 c = *msg->b_rptr++;
5018 if(ie->l2 == UNI_BLLI_L2_USER) {
5019 ie->h.present |= UNI_BLLI_L2_USER_P;
5020 ie->l2_user = c & 0x7f;
5021 if(!(c & 0x80))
5022 goto rej;
5023 } else {
5024 ie->h.present |= UNI_BLLI_L2_Q933_P;
5025 ie->l2_q933 = c & 0x3;
5026 ie->l2_mode = (c >> 5) & 0x3;
5027 if(!(c & 0x80)) {
5028 if(ielen == 0)
5029 goto rej;
5030 ielen--;
5031 c = *msg->b_rptr++;
5032 ie->h.present |= UNI_BLLI_L2_WSIZ_P;
5033 ie->l2_wsiz = c & 0x7f;
5034 if(!(c & 0x80))
5035 goto rej;
5036 }
5037 }
5038 }
5039 break;
5040
5041 case UNI_BLLI_L3_ID:
5042 ie->h.present |= UNI_BLLI_L3_P;
5043 ie->l3 = c & 0x1f;
5044 if(!(c & 0x80)) {
5045 switch(ie->l3) {
5046 default:
5047 case UNI_BLLI_L3_CLMP:
5048 case UNI_BLLI_L3_T70:
5049 goto rej;
5050
5051 case UNI_BLLI_L3_X25:
5052 case UNI_BLLI_L3_ISO8208:
5053 case UNI_BLLI_L3_X223:
5054 if(ielen == 0)
5055 goto rej;
5056 ielen--;
5057 c = *msg->b_rptr++;
5058 ie->l3_mode = (c >> 5) & 0x3;
5059 ie->h.present |= UNI_BLLI_L3_MODE_P;
5060
5061 if(c & 0x80)
5062 break;
5063
5064 if(ielen == 0)
5065 goto rej;
5066 ielen--;
5067 c = *msg->b_rptr++;
5068 ie->l3_psiz = c & 0xf;
5069 ie->h.present |= UNI_BLLI_L3_PSIZ_P;
5070
5071 if(c & 0x80)
5072 break;
5073
5074 if(ielen == 0)
5075 goto rej;
5076 ielen--;
5077 c = *msg->b_rptr++;
5078 ie->l3_wsiz = c & 0x7f;
5079 ie->h.present |= UNI_BLLI_L3_WSIZ_P;
5080
5081 if(!(c & 0x80))
5082 goto rej;
5083 break;
5084
5085 case UNI_BLLI_L3_TR9577:
5086 if(ielen < 2)
5087 goto rej;
5088 ielen -= 2;
5089 c = *msg->b_rptr++;
5090 ie->l3_ipi = (c << 1) & 0xfe;
5091 if(c & 0x80)
5092 goto rej;
5093 c = *msg->b_rptr++;
5094 ie->l3_ipi |= c & 1;
5095 if(!(c & 0x80))
5096 goto rej;
5097 ie->h.present |= UNI_BLLI_L3_IPI_P;
5098
5099 if(ie->l3_ipi != UNI_BLLI_L3_SNAP)
5100 break;
5101 if(ielen < 6)
5102 goto rej;
5103 ielen -= 6;
5104 if(*msg->b_rptr++ != 0x80)
5105 goto rej;
5106 ie->h.present |= UNI_BLLI_L3_SNAP_P;
5107 ie->oui = *msg->b_rptr++ << 16;
5108 ie->oui |= *msg->b_rptr++ << 8;
5109 ie->oui |= *msg->b_rptr++;
5110 ie->pid = *msg->b_rptr++ << 8;
5111 ie->pid |= *msg->b_rptr++;
5112 break;
5113
5114 case UNI_BLLI_L3_H310:
5115 if(ielen == 0)
5116 goto rej;
5117 ielen--;
5118 c = *msg->b_rptr++;
5119 ie->l3_ttype = c & 0xf;
5120 ie->l3_tcap = (c >> 4) & 0x7;
5121 ie->h.present |= UNI_BLLI_L3_TTYPE_P;
5122 if(c & 0x80)
5123 break;
5124 if(ielen == 0)
5125 goto rej;
5126 ielen--;
5127 c = *msg->b_rptr++;
5128 ie->l3_fmux = (c >> 3) & 7;
5129 ie->l3_bmux = c & 7;
5130 ie->h.present |= UNI_BLLI_L3_MUX_P;
5131 if(!(c & 0x80))
5132 goto rej;
5133 break;
5134
5135 case UNI_BLLI_L3_USER:
5136 if(ielen == 0)
5137 goto rej;
5138 ielen--;
5139 c = *msg->b_rptr++;
5140 ie->l3_user = c & 0x7f;
5141 ie->h.present |= UNI_BLLI_L3_USER_P;
5142 if(!(c & 0x80))
5143 goto rej;
5144 break;
5145 }
5146 }
5147 break;
5148 }
5149 }
5150
5151 IE_END(BLLI);
5152 }
5153
5154 /*********************************************************************
5155 *
5156 * Broadband locking shift
5157 * Broadband non-locking shift.
5158 *
5159 * References for this IE are:
5160 *
5161 * Q.2931 pp. 41...42
5162 * UNI4.0 pp. 9
5163 *
5164 * Procedure not supported in UNI4.0, but IE's must be recognized.
5165 *
5166 * Only ITU-T coding allowed.
5167 */
5168
5169 DEF_IE_PRINT(itu, lshift)
5170 {
5171 if(uni_print_iehdr("locking_shift", &ie->h, cx))
5172 return;
5173 uni_print_ieend(cx);
5174 }
5175
5176 DEF_IE_CHECK(itu, lshift)
5177 {
5178 UNUSED(cx); UNUSED(ie);
5179 return -1;
5180 }
5181
5182 DEF_IE_ENCODE(itu, lshift)
5183 {
5184 START_IE(lshift, UNI_IE_LSHIFT, 1);
5185 APP_BYTE(msg, 0x80 | ie->set);
5186 SET_IE_LEN(msg);
5187 return 0;
5188 }
5189
5190 DEF_IE_DECODE(itu, lshift)
5191 {
5192 u_char c;
5193
5194 IE_START(;);
5195
5196 if(ielen != 1)
5197 goto rej;
5198
5199 c = *msg->b_rptr++;
5200
5201 if(!(c & 0x80))
5202 goto rej;
5203 ie->set = c & 7;
5204
5205 IE_END(LSHIFT);
5206 }
5207
5208 /***********************************************************************/
5209
5210 DEF_IE_PRINT(itu, nlshift)
5211 {
5212 if(uni_print_iehdr("nonlocking_shift", &ie->h, cx))
5213 return;
5214 uni_print_ieend(cx);
5215 }
5216
5217 DEF_IE_CHECK(itu, nlshift)
5218 {
5219 UNUSED(cx); UNUSED(ie);
5220 return -1;
5221 }
5222
5223 DEF_IE_ENCODE(itu, nlshift)
5224 {
5225 START_IE(nlshift, UNI_IE_NLSHIFT, 1);
5226 APP_BYTE(msg, 0x80 | ie->set);
5227 SET_IE_LEN(msg);
5228 return 0;
5229 }
5230
5231 DEF_IE_DECODE(itu, nlshift)
5232 {
5233 u_char c;
5234
5235 IE_START(;);
5236
5237 if(ielen != 1)
5238 goto rej;
5239
5240 c = *msg->b_rptr++;
5241
5242 if(!(c & 0x80))
5243 goto rej;
5244 ie->set = c & 7;
5245
5246 IE_END(NLSHIFT);
5247 }
5248
5249 /*********************************************************************
5250 *
5251 * Broadband Sending Complete Indicator
5252 *
5253 * References for this IE are:
5254 *
5255 * Q.2931 pp. 74-75
5256 *
5257 * Only ITU-T coding allowed.
5258 */
5259 DEF_IE_PRINT(itu, scompl)
5260 {
5261 if(uni_print_iehdr("sending_complete", &ie->h, cx))
5262 return;
5263 uni_print_ieend(cx);
5264 }
5265
5266 DEF_IE_CHECK(itu, scompl)
5267 {
5268 UNUSED(ie); UNUSED(cx);
5269 return 0;
5270 }
5271
5272 DEF_IE_ENCODE(itu, scompl)
5273 {
5274 START_IE(scompl, UNI_IE_SCOMPL, 1);
5275
5276 APP_BYTE(msg, 0x80 | 0x21);
5277
5278 SET_IE_LEN(msg);
5279 return 0;
5280 }
5281
5282 DEF_IE_DECODE(itu, scompl)
5283 {
5284 IE_START(;);
5285
5286 if(ielen != 1)
5287 goto rej;
5288
5289 if(*msg->b_rptr++ != (0x80 | 0x21))
5290 goto rej;
5291
5292 IE_END(SCOMPL);
5293 }
5294
5295 /*********************************************************************
5296 *
5297 * Broadband Repeat Indicator
5298 *
5299 * References for this IE are:
5300 *
5301 * Q.2931 p. 73
5302 * PNNI1.0 p. 196
5303 *
5304 * Q.2931 has table 4-19. Only codepoints 0x2 and 0xa (for PNNI) supported.
5305 *
5306 * Only ITU-T coding allowed.
5307 */
5308 DEF_IE_PRINT(itu, repeat)
5309 {
5310 static const struct uni_print_tbl tbl[] = {
5311 MKT(UNI_REPEAT_PRIDESC, desc),
5312 MKT(UNI_REPEAT_STACK, stack),
5313 EOT()
5314 };
5315
5316 if(uni_print_iehdr("repeat", &ie->h, cx))
5317 return;
5318 uni_print_tbl("type", ie->type, tbl, cx);
5319 uni_print_ieend(cx);
5320 }
5321
5322 DEF_IE_CHECK(itu, repeat)
5323 {
5324 switch(ie->type) {
5325
5326 case UNI_REPEAT_PRIDESC:
5327 break;
5328
5329 case UNI_REPEAT_STACK:
5330 if(!cx->pnni)
5331 return -1;
5332 break;
5333
5334 default:
5335 return -1;
5336 }
5337 return 0;
5338 }
5339
5340 DEF_IE_ENCODE(itu, repeat)
5341 {
5342 START_IE(repeat, UNI_IE_REPEAT, 1);
5343
5344 APP_BYTE(msg, 0x80 | ie->type);
5345
5346 SET_IE_LEN(msg);
5347 return 0;
5348 }
5349
5350 DEF_IE_DECODE(itu, repeat)
5351 {
5352 u_char c;
5353
5354 IE_START(;);
5355
5356 if(ielen != 1)
5357 goto rej;
5358
5359 c = *msg->b_rptr++;
5360 if(!(c & 0x80))
5361 goto rej;
5362 ie->type = c & 0xf;
5363
5364 IE_END(REPEAT);
5365 }
5366
5367 /*********************************************************************
5368 *
5369 * Transit Network Selection
5370 *
5371 * References for this IE are:
5372 *
5373 * Q.2931 pp. 75...76
5374 * UNI4.0 pp. 17
5375 *
5376 * According to UNI4.0 this is always National Network Id/Carried Id.
5377 *
5378 * ITU-T/Net coding allowed.
5379 */
5380
5381 DEF_IE_PRINT(itu, tns)
5382 {
5383 u_int i;
5384
5385 if(uni_print_iehdr("tns", &ie->h, cx))
5386 return;
5387 uni_print_entry(cx, "net", "%u,\"", ie->len);
5388 uni_putc('"', cx);
5389 for(i = 0; i < ie->len; i++) {
5390 if(ie->net[i] < ' ')
5391 uni_printf(cx, "^%c", ie->net[i] + '@');
5392 else if(ie->net[i] < '~')
5393 uni_putc(ie->net[i], cx);
5394 else
5395 uni_printf(cx, "\\%03o", ie->net[i]);
5396 }
5397 uni_putc('"', cx);
5398 uni_print_ieend(cx);
5399 }
5400
5401 DEF_IE_CHECK(itu, tns)
5402 {
5403 u_int i;
5404
5405 UNUSED(cx);
5406
5407 if(ie->len == 0 || ie->len > UNI_TNS_MAXLEN)
5408 return -1;
5409 for(i = 0; i < ie->len; i++)
5410 if(ie->net[i] < ' ' || ie->net[i] > '~')
5411 return -1;
5412 return 0;
5413 }
5414
5415 DEF_IE_ENCODE(itu, tns)
5416 {
5417 START_IE(tns, UNI_IE_TNS, ie->len + 1);
5418
5419 APP_BYTE(msg, 0x80 | (0x2 << 4) | 0x1);
5420 APP_BUF(msg, ie->net, ie->len);
5421
5422 SET_IE_LEN(msg);
5423 return 0;
5424 }
5425
5426 DEF_IE_DECODE(itu, tns)
5427 {
5428 IE_START(;);
5429
5430 if(ielen < 2 || ielen > 5)
5431 goto rej;
5432
5433 if(*msg->b_rptr++ != (0x80 | (0x2 << 4) | 0x1))
5434 goto rej;
5435 ielen--;
5436
5437 ie->len = 0;
5438 while(ielen--)
5439 ie->net[ie->len++] = *msg->b_rptr++;
5440
5441 IE_END(TNS);
5442 }
5443
5444 /*********************************************************************
5445 *
5446 * Restart indicator
5447 *
5448 * References for this IE are:
5449 *
5450 * Q.2931 pp. 73...74
5451 * UNI4.0 p. 17
5452 *
5453 * Only ITU-T coding allowed.
5454 */
5455
5456 DEF_IE_PRINT(itu, restart)
5457 {
5458 static const struct uni_print_tbl tbl[] = {
5459 MKT(UNI_RESTART_CHANNEL, channel),
5460 MKT(UNI_RESTART_PATH, path),
5461 MKT(UNI_RESTART_ALL, all),
5462 EOT()
5463 };
5464
5465 if(uni_print_iehdr("restart", &ie->h, cx))
5466 return;
5467 uni_print_tbl("class", ie->rclass, tbl, cx);
5468 uni_print_ieend(cx);
5469 }
5470
5471 DEF_IE_CHECK(itu, restart)
5472 {
5473 UNUSED(cx);
5474
5475 switch(ie->rclass) {
5476 default:
5477 return -1;
5478
5479 case UNI_RESTART_CHANNEL:
5480 case UNI_RESTART_PATH:
5481 case UNI_RESTART_ALL:
5482 break;
5483 }
5484
5485 return 0;
5486 }
5487
5488 DEF_IE_ENCODE(itu, restart)
5489 {
5490 START_IE(restart, UNI_IE_RESTART, 1);
5491
5492 APP_BYTE(msg, 0x80 | ie->rclass);
5493
5494 SET_IE_LEN(msg);
5495 return 0;
5496 }
5497
5498 DEF_IE_DECODE(itu, restart)
5499 {
5500 u_char c;
5501
5502 IE_START(;);
5503
5504 if(ielen != 1)
5505 goto rej;
5506
5507 ie->rclass = (c = *msg->b_rptr++) & 0x7;
5508
5509 if(!(c & 0x80))
5510 goto rej;
5511
5512 IE_END(RESTART);
5513 }
5514
5515 /*********************************************************************
5516 *
5517 * User-to-user info.
5518 *
5519 * References for this IE are:
5520 *
5521 * Q.2957
5522 *
5523 * Only ITU-T coding allowed.
5524 */
5525
5526 DEF_IE_PRINT(itu, uu)
5527 {
5528 u_int i;
5529
5530 if(uni_print_iehdr("uu", &ie->h, cx))
5531 return;
5532 uni_print_entry(cx, "len", "%u", ie->len);
5533 uni_print_entry(cx, "info", "(");
5534 for(i = 0; i < ie->len; i++)
5535 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->uu[i]);
5536 uni_printf(cx, ")");
5537 uni_print_ieend(cx);
5538 }
5539
5540 DEF_IE_CHECK(itu, uu)
5541 {
5542 UNUSED(cx);
5543
5544 if(ie->len > UNI_UU_MAXLEN)
5545 return -1;
5546
5547 return 0;
5548 }
5549
5550 DEF_IE_ENCODE(itu, uu)
5551 {
5552 START_IE(uu, UNI_IE_UU, ie->len);
5553
5554 APP_BUF(msg, ie->uu, ie->len);
5555
5556 SET_IE_LEN(msg);
5557 return 0;
5558 }
5559
5560 DEF_IE_DECODE(itu, uu)
5561 {
5562 IE_START(;);
5563
5564 if(ielen > UNI_UU_MAXLEN || ielen < 1)
5565 goto rej;
5566
5567 ie->len = ielen;
5568 ielen = 0;
5569 (void)memcpy(ie->uu, msg->b_rptr, ie->len);
5570 msg->b_rptr += ie->len;
5571
5572 IE_END(UU);
5573 }
5574
5575 /*********************************************************************
5576 *
5577 * Generic Identifier Transport
5578 *
5579 * References for this IE are:
5580 *
5581 * UNI4.0 pp. 26...28
5582 *
5583 * UNI4.0 prescribes a fixed format for this IE. We have a flag in the
5584 * context structur, which tells us whether the check of this IE should be
5585 * hard or soft. Probably it should be hard for end systems and soft for
5586 * network nodes.
5587 *
5588 * Only Net Coding allowed. (XXX)
5589 */
5590
5591 DEF_IE_PRINT(net, git)
5592 {
5593 static const struct uni_print_tbl std_tbl[] = {
5594 MKT(UNI_GIT_STD_DSMCC, dsmcc),
5595 MKT(UNI_GIT_STD_H245, H.245),
5596 EOT()
5597 };
5598 static const struct uni_print_tbl type_tbl[] = {
5599 MKT(UNI_GIT_TYPE_SESS, sess),
5600 MKT(UNI_GIT_TYPE_RES, res),
5601 EOT()
5602 };
5603 u_int i, j;
5604 char buf[20];
5605
5606 if(uni_print_iehdr("git", &ie->h, cx))
5607 return;
5608
5609 uni_print_tbl("std", ie->std, std_tbl, cx);
5610
5611 uni_print_eol(cx);
5612 uni_print_push_prefix("id", cx);
5613 cx->indent++;
5614 for(i = 0; i < ie->numsub; i++) {
5615 sprintf(buf, "%u", i);
5616 uni_print_entry(cx, buf, "(");
5617 uni_print_tbl(NULL, ie->sub[i].type, type_tbl, cx);
5618 for(j = 0; j < ie->sub[i].len; j++)
5619 uni_printf(cx, ",0x%02x", ie->sub[i].val[j]);
5620 uni_printf(cx, ")");
5621 uni_print_eol(cx);
5622 }
5623 cx->indent--;
5624 uni_print_pop_prefix(cx);
5625
5626 uni_print_ieend(cx);
5627 }
5628
5629 DEF_IE_CHECK(net, git)
5630 {
5631 u_int i;
5632
5633 if(cx->git_hard) {
5634 switch(ie->std) {
5635 case UNI_GIT_STD_DSMCC:
5636 case UNI_GIT_STD_H245:
5637 break;
5638 default:
5639 return -1;
5640 }
5641 if(ie->numsub != 2)
5642 return -1;
5643 if(ie->sub[0].type != UNI_GIT_TYPE_SESS)
5644 return -1;
5645 if(ie->sub[0].len > UNI_GIT_MAXSESS)
5646 return -1;
5647 if(ie->sub[1].type != UNI_GIT_TYPE_RES)
5648 return -1;
5649 if(ie->sub[1].len > UNI_GIT_MAXRES)
5650 return -1;
5651 } else {
5652 if(ie->numsub > UNI_GIT_MAXSUB)
5653 return -1;
5654 for(i = 0; i < ie->numsub; i++)
5655 if(ie->sub[i].len > UNI_GIT_MAXVAL)
5656 return -1;
5657 }
5658 return 0;
5659 }
5660
5661 DEF_IE_ENCODE(net, git)
5662 {
5663 u_int i;
5664
5665 START_IE(git, UNI_IE_GIT, 1 + ie->numsub * (1 + UNI_GIT_MAXVAL));
5666
5667 APP_BYTE(msg, ie->std);
5668 for(i = 0; i < ie->numsub; i++) {
5669 APP_BYTE(msg, ie->sub[i].type);
5670 APP_BYTE(msg, ie->sub[i].len);
5671 APP_BUF(msg, ie->sub[i].val, ie->sub[i].len);
5672 }
5673
5674 SET_IE_LEN(msg);
5675 return 0;
5676 }
5677
5678 DEF_IE_DECODE(net, git)
5679 {
5680 IE_START(;);
5681
5682 if(ielen > 1 + UNI_GIT_MAXSUB * (1 + UNI_GIT_MAXVAL) || ielen < 1)
5683 goto rej;
5684
5685 ie->std = *msg->b_rptr++;
5686 ielen--;
5687
5688 ie->numsub = 0;
5689 while(ielen > 0) {
5690 if(ie->numsub >= UNI_GIT_MAXSUB)
5691 goto rej;
5692
5693 ie->sub[ie->numsub].type = *msg->b_rptr++;
5694 ielen--;
5695
5696 if(ielen == 0)
5697 goto rej;
5698 ie->sub[ie->numsub].len = *msg->b_rptr++;
5699 ielen--;
5700
5701 if(ie->sub[ie->numsub].len > UNI_GIT_MAXVAL)
5702 goto rej;
5703 if(ie->sub[ie->numsub].len > (u_int)ielen)
5704 goto rej;
5705
5706 (void)memcpy(ie->sub[ie->numsub].val, msg->b_rptr, ie->sub[ie->numsub].len);
5707 ielen -= ie->sub[ie->numsub].len;
5708 msg->b_rptr += ie->sub[ie->numsub].len;
5709
5710 ie->numsub++;
5711 }
5712
5713 IE_END(GIT);
5714 }
5715
5716 /*********************************************************************
5717 *
5718 * Additional ABR Parameters
5719 * ABR Setup parameters
5720 *
5721 * References for this IE are:
5722 *
5723 * UNI4.0 pp. 78...82
5724 * PNNI1.0 p. 195
5725 *
5726 * Notes:
5727 * Only NET coding.
5728 */
5729
5730 static void
5731 print_abr_rec(struct unicx *cx, struct uni_abr_rec *rec)
5732 {
5733 if(rec->present & UNI_ABR_REC_NRM_P)
5734 uni_print_entry(cx, "nrm", "%d", rec->nrm);
5735 if(rec->present & UNI_ABR_REC_TRM_P)
5736 uni_print_entry(cx, "trm", "%d", rec->trm);
5737 if(rec->present & UNI_ABR_REC_CDF_P)
5738 uni_print_entry(cx, "cdf", "%d", rec->cdf);
5739 if(rec->present & UNI_ABR_REC_ADTF_P)
5740 uni_print_entry(cx, "adtf", "%d", rec->adtf);
5741 }
5742
5743 DEF_IE_PRINT(net, abradd)
5744 {
5745 if(uni_print_iehdr("abradd", &ie->h, cx))
5746 return;
5747
5748 uni_print_push_prefix("fwd", cx);
5749 print_abr_rec(cx, &ie->fwd);
5750 uni_print_pop_prefix(cx);
5751
5752 uni_print_push_prefix("bwd", cx);
5753 print_abr_rec(cx, &ie->bwd);
5754 uni_print_pop_prefix(cx);
5755
5756 uni_print_ieend(cx);
5757 }
5758
5759 DEF_IE_CHECK(net, abradd)
5760 {
5761 UNUSED(cx);
5762 UNUSED(ie);
5763
5764 return 0;
5765 }
5766
5767 static u_int
5768 encode_abr_rec(struct uni_abr_rec *rec)
5769 {
5770 u_int ret = rec->present & 0xf000;
5771
5772 if(ret & UNI_ABR_REC_NRM_P)
5773 ret |= (rec->nrm & 0x7) << 25;
5774 if(ret & UNI_ABR_REC_TRM_P)
5775 ret |= (rec->trm & 0x7) << 22;
5776 if(ret & UNI_ABR_REC_CDF_P)
5777 ret |= (rec->cdf & 0x7) << 19;
5778 if(ret & UNI_ABR_REC_ADTF_P)
5779 ret |= (rec->adtf & 0x3ff) << 9;
5780
5781 return ret;
5782 }
5783
5784 DEF_IE_ENCODE(net, abradd)
5785 {
5786 START_IE(abradd, UNI_IE_ABRADD, 10);
5787
5788 APP_SUB_32BIT(msg, UNI_ABRADD_FADD_ID, encode_abr_rec(&ie->fwd));
5789 APP_SUB_32BIT(msg, UNI_ABRADD_BADD_ID, encode_abr_rec(&ie->bwd));
5790
5791 SET_IE_LEN(msg);
5792 return 0;
5793 }
5794
5795 static int
5796 decode_abr_rec(struct uni_msg *msg, struct uni_abr_rec *rec)
5797 {
5798 u_int val;
5799
5800 val = *msg->b_rptr++ << 24;
5801 val |= *msg->b_rptr++ << 16;
5802 val |= *msg->b_rptr++ << 8;
5803 val |= *msg->b_rptr++ << 0;
5804
5805 rec->present = val & 0xf000;
5806
5807 rec->nrm = (val & UNI_ABR_REC_NRM_P) ? ((val >> 25) & 0x7) : 0;
5808 rec->trm = (val & UNI_ABR_REC_TRM_P) ? ((val >> 22) & 0x7) : 0;
5809 rec->cdf = (val & UNI_ABR_REC_CDF_P) ? ((val >> 19) & 0x7) : 0;
5810 rec->adtf = (val & UNI_ABR_REC_ADTF_P)? ((val >> 9) & 0x3ff) : 0;
5811
5812 return 0;
5813 }
5814
5815 DEF_IE_DECODE(net, abradd)
5816 {
5817 IE_START(;);
5818
5819 if(ielen != 10)
5820 goto rej;
5821
5822
5823 while(ielen--) {
5824 switch(*msg->b_rptr++) {
5825
5826 default:
5827 goto rej;
5828
5829 case UNI_ABRADD_FADD_ID:
5830 if(decode_abr_rec(msg, &ie->fwd))
5831 goto rej;
5832 ielen -= 4;
5833 break;
5834
5835 case UNI_ABRADD_BADD_ID:
5836 if(decode_abr_rec(msg, &ie->bwd))
5837 goto rej;
5838 ielen -= 4;
5839 break;
5840 }
5841 }
5842 IE_END(ABRADD);
5843 }
5844
5845 /*********************************************************************/
5846
5847 DEF_IE_PRINT(net, abrsetup)
5848 {
5849 if(uni_print_iehdr("abrsetup", &ie->h, cx))
5850 return;
5851
5852 uni_print_entry(cx, "rm_frt", "%d", ie->rmfrt);
5853
5854 uni_print_push_prefix("fwd", cx);
5855 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5856 uni_print_entry(cx, "icr", "%d", ie->ficr);
5857 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5858 uni_print_entry(cx, "tbe", "%d", ie->ftbe);
5859 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5860 uni_print_entry(cx, "rif", "%d", ie->frif);
5861 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5862 uni_print_entry(cx, "rdf", "%d", ie->frdf);
5863 uni_print_pop_prefix(cx);
5864
5865 uni_print_push_prefix("bwd", cx);
5866 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5867 uni_print_entry(cx, "icr", "%d", ie->bicr);
5868 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5869 uni_print_entry(cx, "tbe", "%d", ie->btbe);
5870 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5871 uni_print_entry(cx, "rif", "%d", ie->brif);
5872 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5873 uni_print_entry(cx, "rdf", "%d", ie->brdf);
5874 uni_print_pop_prefix(cx);
5875
5876 uni_print_ieend(cx);
5877 }
5878
5879 DEF_IE_CHECK(net, abrsetup)
5880 {
5881 if(cx->pnni) {
5882 if(!(ie->h.present & UNI_ABRSETUP_FICR_P))
5883 return -1;
5884 if(!(ie->h.present & UNI_ABRSETUP_BICR_P))
5885 return -1;
5886 if(!(ie->h.present & UNI_ABRSETUP_FTBE_P))
5887 return -1;
5888 if(!(ie->h.present & UNI_ABRSETUP_BTBE_P))
5889 return -1;
5890 if(!(ie->h.present & UNI_ABRSETUP_FRIF_P))
5891 return -1;
5892 if(!(ie->h.present & UNI_ABRSETUP_BRIF_P))
5893 return -1;
5894 if(!(ie->h.present & UNI_ABRSETUP_FRDF_P))
5895 return -1;
5896 if(!(ie->h.present & UNI_ABRSETUP_BRDF_P))
5897 return -1;
5898 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5899 return -1;
5900 }
5901
5902 if(!(ie->h.present & UNI_ABRSETUP_RMFRT_P))
5903 return -1;
5904
5905 if(ie->h.present & UNI_ABRSETUP_FICR_P)
5906 if(ie->ficr >= 1 << 24)
5907 return -1;
5908 if(ie->h.present & UNI_ABRSETUP_BICR_P)
5909 if(ie->bicr >= 1 << 24)
5910 return -1;
5911
5912 if(ie->h.present & UNI_ABRSETUP_FTBE_P)
5913 if(ie->ftbe >= 1 << 24 || ie->ftbe == 0)
5914 return -1;
5915 if(ie->h.present & UNI_ABRSETUP_BTBE_P)
5916 if(ie->btbe >= 1 << 24 || ie->btbe == 0)
5917 return -1;
5918
5919 if(ie->rmfrt >= 1 << 24)
5920 return -1;
5921
5922 if(ie->h.present & UNI_ABRSETUP_FRIF_P)
5923 if(ie->frif > 15)
5924 return -1;
5925 if(ie->h.present & UNI_ABRSETUP_FRDF_P)
5926 if(ie->frdf > 15)
5927 return -1;
5928 if(ie->h.present & UNI_ABRSETUP_BRIF_P)
5929 if(ie->brif > 15)
5930 return -1;
5931 if(ie->h.present & UNI_ABRSETUP_BRDF_P)
5932 if(ie->brdf > 15)
5933 return -1;
5934 return 0;
5935 }
5936
5937 DEF_IE_ENCODE(net, abrsetup)
5938 {
5939 START_IE(abrsetup, UNI_IE_ABRSETUP, 32);
5940
5941 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FICR_P,
5942 UNI_ABRSETUP_FICR_ID, ie->ficr);
5943 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BICR_P,
5944 UNI_ABRSETUP_BICR_ID, ie->bicr);
5945 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_FTBE_P,
5946 UNI_ABRSETUP_FTBE_ID, ie->ftbe);
5947 APP_OPT_24BIT(msg, ie->h.present, UNI_ABRSETUP_BTBE_P,
5948 UNI_ABRSETUP_BTBE_ID, ie->btbe);
5949 APP_SUB_24BIT(msg, UNI_ABRSETUP_RMFRT_ID, ie->rmfrt);
5950 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRIF_P,
5951 UNI_ABRSETUP_FRIF_ID, ie->frif);
5952 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRIF_P,
5953 UNI_ABRSETUP_BRIF_ID, ie->brif);
5954 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_FRDF_P,
5955 UNI_ABRSETUP_FRDF_ID, ie->frdf);
5956 APP_OPT_BYTE(msg, ie->h.present, UNI_ABRSETUP_BRDF_P,
5957 UNI_ABRSETUP_BRDF_ID, ie->brdf);
5958
5959 SET_IE_LEN(msg);
5960 return 0;
5961 }
5962
5963 DEF_IE_DECODE(net, abrsetup)
5964 {
5965 IE_START(;);
5966
5967 if(ielen < 4 || ielen > 32)
5968 goto rej;
5969
5970
5971 while(ielen--) {
5972 switch(*msg->b_rptr++) {
5973
5974 default:
5975 goto rej;
5976
5977
5978 DEC_GETF3(ABRSETUP_FICR, ficr, ie->h.present);
5979 DEC_GETF3(ABRSETUP_BICR, bicr, ie->h.present);
5980 DEC_GETF3(ABRSETUP_FTBE, ftbe, ie->h.present);
5981 DEC_GETF3(ABRSETUP_BTBE, btbe, ie->h.present);
5982 DEC_GETF1(ABRSETUP_FRIF, frif, ie->h.present);
5983 DEC_GETF1(ABRSETUP_BRIF, brif, ie->h.present);
5984 DEC_GETF1(ABRSETUP_FRDF, frdf, ie->h.present);
5985 DEC_GETF1(ABRSETUP_BRDF, brdf, ie->h.present);
5986 DEC_GETF3(ABRSETUP_RMFRT, frif, ie->h.present);
5987 }
5988 }
5989 IE_END(ABRSETUP);
5990 }
5991
5992 /*********************************************************************
5993 *
5994 * Broadband report type
5995 *
5996 * References for this IE are:
5997 *
5998 * Q.2963.1 pp. 7...8
5999 *
6000 * Only ITU-T coding allowed.
6001 */
6002
6003 DEF_IE_PRINT(itu, report)
6004 {
6005 static const struct uni_print_tbl tbl[] = {
6006 MKT(UNI_REPORT_MODCONF, modconf),
6007 MKT(UNI_REPORT_CLOCK, clock),
6008 MKT(UNI_REPORT_EEAVAIL, eeavail),
6009 MKT(UNI_REPORT_EEREQ, eereq),
6010 MKT(UNI_REPORT_EECOMPL, eecompl),
6011 EOT()
6012 };
6013
6014 if(uni_print_iehdr("report", &ie->h, cx))
6015 return;
6016 uni_print_tbl("type", ie->report, tbl, cx);
6017 uni_print_ieend(cx);
6018 }
6019
6020 DEF_IE_CHECK(itu, report)
6021 {
6022 UNUSED(cx);
6023
6024 switch(ie->report) {
6025
6026 default:
6027 return -1;
6028
6029 case UNI_REPORT_MODCONF:
6030 case UNI_REPORT_CLOCK:
6031 case UNI_REPORT_EEAVAIL:
6032 case UNI_REPORT_EEREQ:
6033 case UNI_REPORT_EECOMPL:
6034 break;
6035 }
6036 return 0;
6037 }
6038
6039 DEF_IE_ENCODE(itu, report)
6040 {
6041 START_IE(report, UNI_IE_REPORT, 1);
6042
6043 APP_BYTE(msg, ie->report);
6044
6045 SET_IE_LEN(msg);
6046 return 0;
6047 }
6048
6049 DEF_IE_DECODE(itu, report)
6050 {
6051 IE_START(;);
6052 if(ielen != 1)
6053 goto rej;
6054
6055 ie->report = *msg->b_rptr++;
6056
6057 IE_END(REPORT);
6058 }
6059
6060 /*********************************************************************
6061 *
6062 * Soft PVPC/PVCC
6063 *
6064 * References for this IE are:
6065 *
6066 * PNNI1.0 pp. 201...203
6067 *
6068 * Only NET coding allowed.
6069 */
6070 DEF_IE_PRINT(net, calling_soft)
6071 {
6072 if(uni_print_iehdr("calling_soft", &ie->h, cx))
6073 return;
6074
6075 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6076 if(ie->h.present & UNI_CALLING_SOFT_VCI_P)
6077 uni_print_entry(cx, "vci", "%d", ie->vci);
6078
6079 uni_print_ieend(cx);
6080 }
6081
6082 DEF_IE_PRINT(net, called_soft)
6083 {
6084 static const struct uni_print_tbl tab[] = {
6085 MKT(UNI_SOFT_SEL_ANY, any),
6086 MKT(UNI_SOFT_SEL_REQ, required),
6087 MKT(UNI_SOFT_SEL_ASS, assigned),
6088 EOT()
6089 };
6090
6091 if(uni_print_iehdr("called_soft", &ie->h, cx))
6092 return;
6093
6094 uni_print_tbl("selection", ie->sel, tab, cx);
6095 if(ie->h.present & UNI_CALLED_SOFT_VPI_P)
6096 uni_print_entry(cx, "vpi", "%d", ie->vpi);
6097 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6098 uni_print_entry(cx, "vci", "%d", ie->vci);
6099
6100 uni_print_ieend(cx);
6101 }
6102
6103 DEF_IE_CHECK(net, calling_soft)
6104 {
6105 UNUSED(cx);
6106
6107 if(ie->vpi >= 1 << 12)
6108 return -1;
6109 return 0;
6110 }
6111
6112 DEF_IE_CHECK(net, called_soft)
6113 {
6114 UNUSED(cx);
6115
6116 switch(ie->sel) {
6117
6118 case UNI_SOFT_SEL_ANY:
6119 case UNI_SOFT_SEL_REQ:
6120 case UNI_SOFT_SEL_ASS:
6121 break;
6122
6123 default:
6124 return -1;
6125 }
6126 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6127 if(ie->vpi >= 1 << 12)
6128 return -1;
6129 } else {
6130 if(ie->sel != UNI_SOFT_SEL_ANY)
6131 return -1;
6132 }
6133
6134 if(ie->h.present & UNI_CALLED_SOFT_VCI_P)
6135 if(!(ie->h.present & UNI_CALLED_SOFT_VPI_P))
6136 return -1;
6137
6138
6139 return 0;
6140 }
6141
6142 DEF_IE_ENCODE(net, calling_soft)
6143 {
6144 START_IE(calling_soft, UNI_IE_CALLING_SOFT, 6);
6145
6146 APP_BYTE(msg, 0x81);
6147 APP_16BIT(msg, ie->vpi);
6148
6149 if(ie->h.present & UNI_CALLING_SOFT_VCI_P) {
6150 APP_BYTE(msg, 0x82);
6151 APP_16BIT(msg, ie->vci);
6152 }
6153
6154 SET_IE_LEN(msg);
6155 return 0;
6156 }
6157
6158 DEF_IE_ENCODE(net, called_soft)
6159 {
6160 START_IE(called_soft, UNI_IE_CALLED_SOFT, 7);
6161
6162 APP_BYTE(msg, ie->sel);
6163
6164 if(ie->h.present & UNI_CALLED_SOFT_VPI_P) {
6165 APP_BYTE(msg, 0x81);
6166 APP_16BIT(msg, ie->vpi);
6167 }
6168
6169 if(ie->h.present & UNI_CALLED_SOFT_VCI_P) {
6170 APP_BYTE(msg, 0x82);
6171 APP_16BIT(msg, ie->vci);
6172 }
6173
6174 SET_IE_LEN(msg);
6175 return 0;
6176 }
6177
6178 DEF_IE_DECODE(net, calling_soft)
6179 {
6180 int vci_seen, vpi_seen;
6181
6182 IE_START(;);
6183 if(ielen < 3)
6184 goto rej;
6185
6186 vci_seen = 0;
6187 vpi_seen = 0;
6188
6189 while(ielen) {
6190 switch(*msg->b_rptr++) {
6191
6192 case 0x81:
6193 if(!vpi_seen) {
6194 ie->vpi = *msg->b_rptr++ << 8;
6195 ie->vpi |= *msg->b_rptr++;
6196 } else {
6197 msg->b_rptr += 2;
6198 }
6199 ielen -= 3;
6200 break;
6201
6202 case 0x82:
6203 if(!vci_seen) {
6204 ie->vci = *msg->b_rptr++ << 8;
6205 ie->vci |= *msg->b_rptr++;
6206 } else {
6207 msg->b_rptr += 2;
6208 }
6209 ie->h.present |= UNI_CALLING_SOFT_VCI_P;
6210 ielen -= 3;
6211 break;
6212
6213 default:
6214 goto rej;
6215 }
6216 }
6217
6218 if(!vpi_seen)
6219 goto rej;
6220
6221 IE_END(CALLING_SOFT);
6222 }
6223
6224 DEF_IE_DECODE(net, called_soft)
6225 {
6226 int vci_seen, vpi_seen;
6227
6228 IE_START(;);
6229 if(ielen < 3)
6230 goto rej;
6231
6232 vci_seen = 0;
6233 vpi_seen = 0;
6234
6235 while(ielen) {
6236 switch(*msg->b_rptr++) {
6237
6238 case 0x81:
6239 if(!vpi_seen) {
6240 ie->vpi = *msg->b_rptr++ << 8;
6241 ie->vpi |= *msg->b_rptr++;
6242 vpi_seen = 1;
6243 } else {
6244 msg->b_rptr += 2;
6245 }
6246 ielen -= 3;
6247 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6248 break;
6249
6250 case 0x82:
6251 if(!vci_seen) {
6252 ie->vci = *msg->b_rptr++ << 8;
6253 ie->vci |= *msg->b_rptr++;
6254 vci_seen = 1;
6255 } else {
6256 msg->b_rptr += 2;
6257 }
6258 ie->h.present |= UNI_CALLED_SOFT_VCI_P;
6259 ielen -= 3;
6260 break;
6261
6262 default:
6263 goto rej;
6264 }
6265 }
6266
6267 IE_END(CALLED_SOFT);
6268 }
6269
6270 /*********************************************************************
6271 *
6272 * Crankback
6273 *
6274 * References for this IE are:
6275 *
6276 * PNNI1.0 pp. 203...206
6277 *
6278 * Only NET coding allowed.
6279 */
6280
6281 DEF_IE_PRINT(net, crankback)
6282 {
6283 u_int j;
6284
6285 if(uni_print_iehdr("crankback", &ie->h, cx))
6286 return;
6287
6288 uni_print_entry(cx, "level", "%d", ie->level);
6289
6290 switch(ie->type) {
6291
6292 case UNI_CRANKBACK_IF:
6293 uni_print_entry(cx, "type", "interface");
6294 break;
6295
6296 case UNI_CRANKBACK_NODE:
6297 uni_print_entry(cx, "type", "node");
6298 uni_print_entry(cx, "node", "{%d/", ie->id.node.level);
6299 for(j = 0; j < 21; j++)
6300 uni_printf(cx, "%02x", ie->id.node.id[j]);
6301 uni_printf(cx, "}");
6302 uni_print_eol(cx);
6303 break;
6304
6305 case UNI_CRANKBACK_LINK:
6306 uni_print_entry(cx, "type", "link");
6307 uni_print_push_prefix("link", cx);
6308 cx->indent++;
6309
6310 uni_print_entry(cx, "prec", "{%d/", ie->id.link.plevel);
6311 for(j = 0; j < 21; j++)
6312 uni_printf(cx, "%02x", ie->id.link.pid[j]);
6313 uni_printf(cx, "}");
6314 uni_print_eol(cx);
6315
6316 uni_print_entry(cx, "port", "0x%04x", ie->id.link.port);
6317 uni_print_eol(cx);
6318
6319 uni_print_entry(cx, "succ", "{%d/", ie->id.link.slevel);
6320 for(j = 0; j < 21; j++)
6321 uni_printf(cx, "%02x", ie->id.link.sid[j]);
6322 uni_printf(cx, "}");
6323 uni_print_eol(cx);
6324
6325 cx->indent--;
6326 uni_print_pop_prefix(cx);
6327 break;
6328
6329 default:
6330 uni_print_entry(cx, "type", "0x%02x", ie->type);
6331 break;
6332 }
6333
6334 uni_print_entry(cx, "cause", "0x%02x", ie->cause);
6335
6336 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6337 uni_print_push_prefix("topol", cx);
6338 uni_print_entry(cx, "dir", "%d", ie->diag.top.dir);
6339 uni_print_entry(cx, "port", "0x%04x", ie->diag.top.port);
6340 uni_print_entry(cx, "avcr", "%u", ie->diag.top.avcr);
6341 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6342 uni_print_entry(cx, "crm", "%u", ie->diag.top.crm);
6343 uni_print_entry(cx, "vf", "%u", ie->diag.top.vf);
6344 }
6345 uni_print_pop_prefix(cx);
6346 uni_print_eol(cx);
6347 }
6348 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6349 uni_print_push_prefix("qos", cx);
6350 uni_print_entry(cx, "ctd", "%savail", ie->diag.qos.ctd ? "" : "un");
6351 uni_print_entry(cx, "cdv", "%savail", ie->diag.qos.cdv ? "" : "un");
6352 uni_print_entry(cx, "clr", "%savail", ie->diag.qos.clr ? "" : "un");
6353 uni_print_entry(cx, "other", "%savail", ie->diag.qos.other ? "" : "un");
6354 uni_print_pop_prefix(cx);
6355 uni_print_eol(cx);
6356 }
6357
6358 uni_print_eol(cx);
6359 uni_print_ieend(cx);
6360 }
6361
6362 DEF_IE_CHECK(net, crankback)
6363 {
6364 UNUSED(cx);
6365
6366 if(ie->level > 104)
6367 return -1;
6368 switch(ie->type) {
6369 case UNI_CRANKBACK_IF:
6370 break;
6371 case UNI_CRANKBACK_NODE:
6372 if(ie->id.node.level > 104)
6373 return -1;
6374 break;
6375
6376 case UNI_CRANKBACK_LINK:
6377 if(ie->id.link.plevel > 104)
6378 return -1;
6379 if(ie->id.link.slevel > 104)
6380 return -1;
6381 break;
6382
6383 default:
6384 return -1;
6385 }
6386
6387 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6388 if(ie->h.present & UNI_CRANKBACK_QOS_P)
6389 return -1;
6390
6391 if(ie->cause != UNI_CAUSE_CRATE_NAVL)
6392 return -1;
6393 switch(ie->diag.top.dir) {
6394
6395 case 0x00:
6396 case 0x01:
6397 break;
6398
6399 default:
6400 return -1;
6401 }
6402 }
6403 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6404 if(ie->cause != UNI_CAUSE_QOS_NAVL)
6405 return -1;
6406 }
6407 return 0;
6408 }
6409
6410 DEF_IE_ENCODE(net, crankback)
6411 {
6412 START_IE(crankback, UNI_IE_CRANKBACK, 72);
6413
6414 APP_BYTE(msg, ie->level);
6415 APP_BYTE(msg, ie->type);
6416
6417 switch(ie->type) {
6418
6419 case UNI_CRANKBACK_IF:
6420 break;
6421
6422 case UNI_CRANKBACK_NODE:
6423 APP_BYTE(msg, ie->id.node.level);
6424 APP_BUF(msg, ie->id.node.id, 21);
6425 break;
6426
6427 case UNI_CRANKBACK_LINK:
6428 APP_BYTE(msg, ie->id.link.plevel);
6429 APP_BUF(msg, ie->id.link.pid, 21);
6430 APP_32BIT(msg, ie->id.link.port);
6431 APP_BYTE(msg, ie->id.link.slevel);
6432 APP_BUF(msg, ie->id.link.sid, 21);
6433 break;
6434 }
6435
6436 APP_BYTE(msg, ie->cause);
6437
6438 if(ie->h.present & UNI_CRANKBACK_TOP_P) {
6439 APP_BYTE(msg, ie->diag.top.dir);
6440 APP_32BIT(msg, ie->diag.top.port);
6441 APP_32BIT(msg, ie->diag.top.avcr);
6442 if(ie->h.present & UNI_CRANKBACK_TOPX_P) {
6443 APP_32BIT(msg, ie->diag.top.crm);
6444 APP_32BIT(msg, ie->diag.top.vf);
6445 }
6446 }
6447
6448 if(ie->h.present & UNI_CRANKBACK_QOS_P) {
6449 APP_BYTE(msg, (ie->diag.qos.ctd << 3)
6450 |(ie->diag.qos.cdv << 2)
6451 |(ie->diag.qos.clr << 1)
6452 |(ie->diag.qos.other));
6453 }
6454 SET_IE_LEN(msg);
6455 return 0;
6456 }
6457
6458
6459 DEF_IE_DECODE(net, crankback)
6460 {
6461 IE_START(;);
6462
6463 if(ielen < 3)
6464 goto rej;
6465
6466 ie->level = *msg->b_rptr++;
6467 ielen--;
6468
6469 ie->type = *msg->b_rptr++;
6470 ielen--;
6471
6472 switch(ie->type) {
6473
6474 default:
6475 goto rej;
6476
6477 case UNI_CRANKBACK_IF:
6478 break;
6479
6480 case UNI_CRANKBACK_NODE:
6481 if(ielen < 22)
6482 goto rej;
6483 ie->id.node.level = *msg->b_rptr++;
6484 (void)memcpy(ie->id.node.id, msg->b_rptr, 21);
6485 msg->b_rptr += 21;
6486 ielen -= 22;
6487 break;
6488
6489 case UNI_CRANKBACK_LINK:
6490 if(ielen < 48)
6491 goto rej;
6492 ie->id.link.plevel = *msg->b_rptr++;
6493 (void)memcpy(ie->id.link.pid, msg->b_rptr, 21);
6494 msg->b_rptr += 21;
6495 ielen -= 22;
6496
6497 ie->id.link.port = *msg->b_rptr++ << 24;
6498 ie->id.link.port |= *msg->b_rptr++ << 16;
6499 ie->id.link.port |= *msg->b_rptr++ << 8;
6500 ie->id.link.port |= *msg->b_rptr++ << 0;
6501 ielen -= 4;
6502
6503 ie->id.link.slevel = *msg->b_rptr++;
6504 (void)memcpy(ie->id.link.sid, msg->b_rptr, 21);
6505 msg->b_rptr += 21;
6506 ielen -= 22;
6507
6508 break;
6509 }
6510
6511 if(ielen < 1)
6512 goto rej;
6513 ie->cause = *msg->b_rptr++;
6514 ielen--;
6515
6516 if(ie->cause == UNI_CAUSE_CRATE_NAVL) {
6517 if(ielen > 0) {
6518 if(ielen != 9 && ielen != 17)
6519 goto rej;
6520 ie->diag.top.dir = *msg->b_rptr++;
6521 ie->diag.top.port = *msg->b_rptr++ << 24;
6522 ie->diag.top.port |= *msg->b_rptr++ << 16;
6523 ie->diag.top.port |= *msg->b_rptr++ << 8;
6524 ie->diag.top.port |= *msg->b_rptr++ << 0;
6525 ie->diag.top.avcr = *msg->b_rptr++ << 24;
6526 ie->diag.top.avcr |= *msg->b_rptr++ << 16;
6527 ie->diag.top.avcr |= *msg->b_rptr++ << 8;
6528 ie->diag.top.avcr |= *msg->b_rptr++ << 0;
6529 ielen -= 9;
6530 ie->h.present |= UNI_CRANKBACK_TOP_P;
6531 if(ielen > 0) {
6532 ie->diag.top.crm = *msg->b_rptr++ << 24;
6533 ie->diag.top.crm |= *msg->b_rptr++ << 16;
6534 ie->diag.top.crm |= *msg->b_rptr++ << 8;
6535 ie->diag.top.crm |= *msg->b_rptr++ << 0;
6536 ie->diag.top.vf = *msg->b_rptr++ << 24;
6537 ie->diag.top.vf |= *msg->b_rptr++ << 16;
6538 ie->diag.top.vf |= *msg->b_rptr++ << 8;
6539 ie->diag.top.vf |= *msg->b_rptr++ << 0;
6540 ie->h.present |= UNI_CRANKBACK_TOPX_P;
6541 ielen -= 8;
6542 }
6543 }
6544 } else if(ie->cause == UNI_CAUSE_QOS_NAVL) {
6545 if(ielen > 0) {
6546 if(ielen != 1)
6547 goto rej;
6548 ie->diag.qos.ctd = *msg->b_rptr >> 3;
6549 ie->diag.qos.cdv = *msg->b_rptr >> 2;
6550 ie->diag.qos.clr = *msg->b_rptr >> 1;
6551 ie->diag.qos.other = *msg->b_rptr >> 0;
6552 ie->h.present |= UNI_CRANKBACK_QOS_P;
6553 ielen -= 1;
6554 }
6555 } else {
6556 if(ielen > 0)
6557 goto rej;
6558 }
6559
6560 IE_END(CRANKBACK);
6561 }
6562
6563 /*********************************************************************
6564 *
6565 * Designated transit list
6566 *
6567 * References for this IE are:
6568 *
6569 * PNNI1.0 pp. 206...208
6570 *
6571 * Only NET coding allowed.
6572 */
6573 DEF_IE_PRINT(net, dtl)
6574 {
6575 u_int i, j;
6576 char buf[10];
6577
6578 if(uni_print_iehdr("dtl", &ie->h, cx))
6579 return;
6580
6581 uni_print_entry(cx, "ptr", "%d(%d)", ie->ptr, ie->ptr / UNI_DTL_LOGNP_SIZE);
6582 uni_print_push_prefix("dtl", cx);
6583 cx->indent++;
6584 uni_printf(cx, "{");
6585 for(i = 0; i < ie->num; i++) {
6586 sprintf(buf, "%d", i);
6587 uni_print_entry(cx, buf, "{%d/", ie->dtl[i].node_level);
6588 for(j = 0; j < 21; j++)
6589 uni_printf(cx, "%02x", ie->dtl[i].node_id[j]);
6590 uni_printf(cx, ",%04x}", ie->dtl[i].port_id);
6591 uni_print_eol(cx);
6592 }
6593 cx->indent--;
6594 uni_print_pop_prefix(cx);
6595 uni_print_ieend(cx);
6596 }
6597
6598 DEF_IE_CHECK(net, dtl)
6599 {
6600 u_int i;
6601
6602 UNUSED(cx);
6603
6604 if(ie->ptr % UNI_DTL_LOGNP_SIZE != 0)
6605 return -1;
6606 if(ie->ptr / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6607 return -1;
6608 if(ie->num > UNI_DTL_MAXNUM)
6609 return -1;
6610 for(i = 0; i < ie->num; i++)
6611 if(ie->dtl[i].node_level > 104)
6612 return -1;
6613 return 0;
6614 }
6615
6616 DEF_IE_ENCODE(net, dtl)
6617 {
6618 u_int i;
6619
6620 START_IE(dtl, UNI_IE_DTL, 2 + UNI_DTL_LOGNP_SIZE * ie->num);
6621
6622 APP_16BIT(msg, ie->ptr);
6623
6624 for(i = 0; i < ie->num; i++) {
6625 APP_BYTE(msg, UNI_DTL_LOGNP);
6626 APP_BYTE(msg, ie->dtl[i].node_level);
6627 APP_BUF(msg, ie->dtl[i].node_id, 21);
6628 APP_32BIT(msg, ie->dtl[i].port_id);
6629 }
6630
6631 SET_IE_LEN(msg);
6632 return 0;
6633 }
6634
6635
6636 DEF_IE_DECODE(net, dtl)
6637 {
6638 IE_START(;);
6639
6640 if(ielen < 2)
6641 goto rej;
6642
6643 ie->ptr = *msg->b_rptr++ << 8;
6644 ie->ptr |= *msg->b_rptr++;
6645 ielen -= 2;
6646
6647 if(ielen % UNI_DTL_LOGNP_SIZE != 0)
6648 goto rej;
6649 if(ielen / UNI_DTL_LOGNP_SIZE > UNI_DTL_MAXNUM)
6650 goto rej;
6651
6652 ie->num = 0;
6653 while(ielen) {
6654 if(*msg->b_rptr++ != UNI_DTL_LOGNP)
6655 goto rej;
6656 ielen--;
6657
6658 ie->dtl[ie->num].node_level = *msg->b_rptr++;
6659 ielen--;
6660
6661 (void)memcpy(ie->dtl[ie->num].node_id, msg->b_rptr, 21);
6662 msg->b_rptr += 21;
6663 ielen -= 21;
6664
6665 ie->dtl[ie->num].port_id = *msg->b_rptr++ << 24;
6666 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 16;
6667 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 8;
6668 ie->dtl[ie->num].port_id |= *msg->b_rptr++ << 0;
6669 ielen -= 4;
6670
6671 ie->num++;
6672 }
6673
6674 IE_END(DTL);
6675 }
6676
6677 /*********************************************************************
6678 *
6679 * Leaf initiated join call identifier.
6680 * Leaf initiated join parameters.
6681 * Leaf initiated join sequence number.
6682 *
6683 * References for this IE are:
6684 *
6685 * UNI4.0 pp. 46...48
6686 *
6687 * Only NET coding allowed.
6688 */
6689
6690 /**********************************************************************/
6691
6692 DEF_IE_PRINT(net, lij_callid)
6693 {
6694 static const struct uni_print_tbl type_tbl[] = {
6695 MKT(UNI_LIJ_IDTYPE_ROOT, root),
6696 EOT()
6697 };
6698
6699 if(uni_print_iehdr("lij_callid", &ie->h, cx))
6700 return;
6701
6702 uni_print_tbl("type", ie->type, type_tbl, cx);
6703 uni_print_entry(cx, "id", "0x%x", ie->callid);
6704
6705 uni_print_ieend(cx);
6706 }
6707
6708 DEF_IE_CHECK(net, lij_callid)
6709 {
6710 UNUSED(cx);
6711
6712 switch(ie->type) {
6713
6714 case UNI_LIJ_IDTYPE_ROOT:
6715 break;
6716
6717 default:
6718 return -1;
6719 }
6720
6721 return 0;
6722 }
6723
6724 DEF_IE_ENCODE(net, lij_callid)
6725 {
6726 START_IE(lij_callid, UNI_IE_LIJ_CALLID, 5);
6727
6728 APP_BYTE(msg, 0x80 | ie->type);
6729 APP_32BIT(msg, ie->callid);
6730
6731 SET_IE_LEN(msg);
6732 return 0;
6733 }
6734
6735 DEF_IE_DECODE(net, lij_callid)
6736 {
6737 IE_START(;);
6738
6739 if(ielen != 5)
6740 goto rej;
6741
6742 ie->type = *msg->b_rptr++ & 0xf;
6743 ie->callid = *msg->b_rptr++ << 24;
6744 ie->callid |= *msg->b_rptr++ << 16;
6745 ie->callid |= *msg->b_rptr++ << 8;
6746 ie->callid |= *msg->b_rptr++ << 0;
6747
6748 IE_END(LIJ_CALLID);
6749 }
6750
6751 /**********************************************************************/
6752
6753 DEF_IE_PRINT(net, lij_param)
6754 {
6755 static const struct uni_print_tbl lscreen_tbl[] = {
6756 MKT(UNI_LIJ_SCREEN_NETJOIN, netjoin),
6757 EOT()
6758 };
6759
6760 if(uni_print_iehdr("lij_param", &ie->h, cx))
6761 return;
6762 uni_print_tbl("screen", ie->screen, lscreen_tbl, cx);
6763 uni_print_ieend(cx);
6764 }
6765
6766 DEF_IE_CHECK(net, lij_param)
6767 {
6768 UNUSED(cx);
6769
6770 switch(ie->screen) {
6771
6772 case UNI_LIJ_SCREEN_NETJOIN:
6773 break;
6774
6775 default:
6776 return -1;
6777 }
6778
6779 return 0;
6780 }
6781
6782 DEF_IE_ENCODE(net, lij_param)
6783 {
6784 START_IE(lij_param, UNI_IE_LIJ_PARAM, 1);
6785
6786 APP_BYTE(msg, 0x80 | ie->screen);
6787
6788 SET_IE_LEN(msg);
6789 return 0;
6790 }
6791
6792 DEF_IE_DECODE(net, lij_param)
6793 {
6794 IE_START(;);
6795
6796 if(ielen != 1)
6797 goto rej;
6798
6799 ie->screen = *msg->b_rptr++ & 0xf;
6800
6801 IE_END(LIJ_PARAM);
6802 }
6803
6804 /**********************************************************************/
6805
6806 DEF_IE_PRINT(net, lij_seqno)
6807 {
6808 if(uni_print_iehdr("lij_seqno", &ie->h, cx))
6809 return;
6810 uni_print_entry(cx, "seqno", "0x%x", ie->seqno);
6811 uni_print_ieend(cx);
6812 }
6813
6814 DEF_IE_CHECK(net, lij_seqno)
6815 {
6816 UNUSED(cx); UNUSED(ie);
6817
6818 return 0;
6819 }
6820
6821 DEF_IE_ENCODE(net, lij_seqno)
6822 {
6823 START_IE(lij_seqno, UNI_IE_LIJ_SEQNO, 4);
6824
6825 APP_32BIT(msg, ie->seqno);
6826
6827 SET_IE_LEN(msg);
6828 return 0;
6829 }
6830
6831 DEF_IE_DECODE(net, lij_seqno)
6832 {
6833 IE_START(;);
6834
6835 if(ielen != 4)
6836 goto rej;
6837
6838 ie->seqno = *msg->b_rptr++ << 24;
6839 ie->seqno |= *msg->b_rptr++ << 16;
6840 ie->seqno |= *msg->b_rptr++ << 8;
6841 ie->seqno |= *msg->b_rptr++ << 0;
6842
6843 IE_END(LIJ_SEQNO);
6844 }
6845
6846 /*********************************************************************
6847 *
6848 * Connection scope
6849 *
6850 * References for this IE are:
6851 *
6852 * UNI4.0 pp. 57...58
6853 *
6854 * Only NET coding allowed.
6855 */
6856 DEF_IE_PRINT(net, cscope)
6857 {
6858 static const struct uni_print_tbl type_tbl[] = {
6859 MKT(UNI_CSCOPE_ORG, org),
6860 EOT()
6861 };
6862 static const struct uni_print_tbl scope_tbl[] = {
6863 MKT(UNI_CSCOPE_ORG_LOC, local_network),
6864 MKT(UNI_CSCOPE_ORG_LOC_P1, local_network_plus_one),
6865 MKT(UNI_CSCOPE_ORG_LOC_P2, local_network_plus_two),
6866 MKT(UNI_CSCOPE_ORG_SITE_M1, site_minus_one),
6867 MKT(UNI_CSCOPE_ORG_SITE, intra_site),
6868 MKT(UNI_CSCOPE_ORG_SITE_P1, site_plus_one),
6869 MKT(UNI_CSCOPE_ORG_ORG_M1, organisation_minus_one),
6870 MKT(UNI_CSCOPE_ORG_ORG, intra_organisation),
6871 MKT(UNI_CSCOPE_ORG_ORG_P1, organisation_plus_one),
6872 MKT(UNI_CSCOPE_ORG_COMM_M1, community_minus_one),
6873 MKT(UNI_CSCOPE_ORG_COMM, intra_community),
6874 MKT(UNI_CSCOPE_ORG_COMM_P1, community_plus_one),
6875 MKT(UNI_CSCOPE_ORG_REG, regional),
6876 MKT(UNI_CSCOPE_ORG_INTER, inter_regional),
6877 MKT(UNI_CSCOPE_ORG_GLOBAL, global),
6878 EOT()
6879 };
6880
6881 if(uni_print_iehdr("cscope", &ie->h, cx))
6882 return;
6883
6884 uni_print_tbl("type", ie->type, type_tbl, cx);
6885 if(ie->type == UNI_CSCOPE_ORG)
6886 uni_print_tbl("scope", (u_int)ie->scope, scope_tbl, cx);
6887 else
6888 uni_print_entry(cx, "scope", "0x%02x", ie->scope);
6889
6890 uni_print_ieend(cx);
6891 }
6892
6893 DEF_IE_CHECK(net, cscope)
6894 {
6895 UNUSED(cx);
6896
6897 switch(ie->type) {
6898
6899 default:
6900 return -1;
6901
6902 case UNI_CSCOPE_ORG:
6903 switch(ie->scope) {
6904
6905 default:
6906 return -1;
6907
6908 case UNI_CSCOPE_ORG_LOC:
6909 case UNI_CSCOPE_ORG_LOC_P1:
6910 case UNI_CSCOPE_ORG_LOC_P2:
6911 case UNI_CSCOPE_ORG_SITE_M1:
6912 case UNI_CSCOPE_ORG_SITE:
6913 case UNI_CSCOPE_ORG_SITE_P1:
6914 case UNI_CSCOPE_ORG_ORG_M1:
6915 case UNI_CSCOPE_ORG_ORG:
6916 case UNI_CSCOPE_ORG_ORG_P1:
6917 case UNI_CSCOPE_ORG_COMM_M1:
6918 case UNI_CSCOPE_ORG_COMM:
6919 case UNI_CSCOPE_ORG_COMM_P1:
6920 case UNI_CSCOPE_ORG_REG:
6921 case UNI_CSCOPE_ORG_INTER:
6922 case UNI_CSCOPE_ORG_GLOBAL:
6923 break;
6924 }
6925 break;
6926 }
6927 return 0;
6928 }
6929
6930 DEF_IE_ENCODE(net, cscope)
6931 {
6932 START_IE(cscope, UNI_IE_CSCOPE, 2);
6933
6934 APP_BYTE(msg, ie->type | 0x80);
6935 APP_BYTE(msg, ie->scope);
6936
6937 SET_IE_LEN(msg);
6938 return 0;
6939 }
6940
6941 DEF_IE_DECODE(net, cscope)
6942 {
6943 IE_START(;);
6944 if(ielen != 2)
6945 goto rej;
6946
6947 if((*msg->b_rptr & 0xf0) != 0x80)
6948 goto rej;
6949
6950 ie->type = *msg->b_rptr++ & 0xf;
6951 ie->scope = *msg->b_rptr++;
6952
6953 IE_END(CSCOPE);
6954 }
6955
6956 /*********************************************************************
6957 *
6958 * Extended Quality of Service
6959 *
6960 * References for this IE are:
6961 *
6962 * UNI4.0 pp. 70...72
6963 *
6964 * Notes:
6965 * Only NET coding.
6966 */
6967 DEF_IE_PRINT(net, exqos)
6968 {
6969 static const struct uni_print_tbl tab[] = {
6970 MKT(UNI_EXQOS_USER, user),
6971 MKT(UNI_EXQOS_NET, net),
6972 EOT()
6973 };
6974
6975 if(uni_print_iehdr("exqos", &ie->h, cx))
6976 return;
6977
6978 uni_print_tbl("origin", ie->origin, tab, cx);
6979
6980 uni_print_entry(cx, "acceptable", "(");
6981 if(ie->h.present & UNI_EXQOS_FACC_P) {
6982 if(ie->facc == UNI_EXQOS_ANY_CDV)
6983 uni_printf(cx, "ANY");
6984 else
6985 uni_printf(cx, "%d", ie->facc);
6986 }
6987 uni_putc(',', cx);
6988 if(ie->h.present & UNI_EXQOS_BACC_P) {
6989 if(ie->bacc == UNI_EXQOS_ANY_CDV)
6990 uni_printf(cx, "ANY");
6991 else
6992 uni_printf(cx, "%d", ie->bacc);
6993 }
6994 uni_putc(')', cx);
6995
6996 uni_print_entry(cx, "cumulative", "(");
6997 if(ie->h.present & UNI_EXQOS_FCUM_P)
6998 uni_printf(cx, "%d", ie->fcum);
6999 uni_putc(',', cx);
7000 if(ie->h.present & UNI_EXQOS_BCUM_P)
7001 uni_printf(cx, "%d", ie->bcum);
7002 uni_putc(')', cx);
7003
7004 uni_print_entry(cx, "clrid", "(");
7005 if(ie->h.present & UNI_EXQOS_FCLR_P) {
7006 if(ie->fclr == UNI_EXQOS_ANY_CLR)
7007 uni_printf(cx, "ANY");
7008 else
7009 uni_printf(cx, "%d", ie->fclr);
7010 }
7011 uni_putc(',', cx);
7012 if(ie->h.present & UNI_EXQOS_BCLR_P) {
7013 if(ie->bclr == UNI_EXQOS_ANY_CLR)
7014 uni_printf(cx, "ANY");
7015 else
7016 uni_printf(cx, "%d", ie->bclr);
7017 }
7018 uni_putc(')', cx);
7019
7020 uni_print_ieend(cx);
7021 }
7022
7023 DEF_IE_CHECK(net, exqos)
7024 {
7025 UNUSED(cx);
7026
7027 switch(ie->origin) {
7028 case UNI_EXQOS_USER:
7029 case UNI_EXQOS_NET:
7030 break;
7031
7032 default:
7033 return -1;
7034 }
7035 if(ie->h.present & UNI_EXQOS_FACC_P)
7036 if(!(ie->h.present & UNI_EXQOS_FCUM_P))
7037 return -1;
7038 if(ie->h.present & UNI_EXQOS_BACC_P)
7039 if(!(ie->h.present & UNI_EXQOS_BCUM_P))
7040 return -1;
7041
7042 if(ie->h.present & UNI_EXQOS_FACC_P)
7043 if(ie->facc >= 1 << 24)
7044 return -1;
7045 if(ie->h.present & UNI_EXQOS_BACC_P)
7046 if(ie->bacc >= 1 << 24)
7047 return -1;
7048 if(ie->h.present & UNI_EXQOS_FCUM_P)
7049 if(ie->fcum >= 1 << 24)
7050 return -1;
7051 if(ie->h.present & UNI_EXQOS_BCUM_P)
7052 if(ie->bcum >= 1 << 24)
7053 return -1;
7054
7055 if(ie->h.present & UNI_EXQOS_FCLR_P)
7056 if(ie->fclr==0 || (ie->fclr>15 && ie->fclr!=UNI_EXQOS_ANY_CLR))
7057 return -1;
7058 if(ie->h.present & UNI_EXQOS_BCLR_P)
7059 if(ie->bclr==0 || (ie->bclr>15 && ie->bclr!=UNI_EXQOS_ANY_CLR))
7060 return -1;
7061 return 0;
7062 }
7063
7064 DEF_IE_ENCODE(net, exqos)
7065 {
7066 START_IE(exqos, UNI_IE_EXQOS, 21);
7067
7068 APP_BYTE(msg, ie->origin);
7069
7070 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FACC_P,
7071 UNI_EXQOS_FACC_ID, ie->facc);
7072 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BACC_P,
7073 UNI_EXQOS_BACC_ID, ie->bacc);
7074 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_FCUM_P,
7075 UNI_EXQOS_FCUM_ID, ie->fcum);
7076 APP_OPT_24BIT(msg, ie->h.present, UNI_EXQOS_BCUM_P,
7077 UNI_EXQOS_BCUM_ID, ie->bcum);
7078
7079 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_FCLR_P,
7080 UNI_EXQOS_FCLR_ID, ie->fclr);
7081 APP_OPT_BYTE(msg, ie->h.present, UNI_EXQOS_BCLR_P,
7082 UNI_EXQOS_BCLR_ID, ie->bclr);
7083
7084 SET_IE_LEN(msg);
7085 return 0;
7086 }
7087
7088 DEF_IE_DECODE(net, exqos)
7089 {
7090 IE_START(;);
7091
7092 if(ielen < 1 || ielen > 21)
7093 goto rej;
7094
7095 ie->origin = *msg->b_rptr++;
7096 ielen--;
7097
7098 while(ielen--) {
7099 switch(*msg->b_rptr++) {
7100
7101 default:
7102 goto rej;
7103
7104 DEC_GETF3(EXQOS_FACC, facc, ie->h.present);
7105 DEC_GETF3(EXQOS_BACC, bacc, ie->h.present);
7106 DEC_GETF3(EXQOS_FCUM, fcum, ie->h.present);
7107 DEC_GETF3(EXQOS_BCUM, bcum, ie->h.present);
7108
7109 DEC_GETF1(EXQOS_FCLR, fclr, ie->h.present);
7110 DEC_GETF1(EXQOS_BCLR, bclr, ie->h.present);
7111
7112 }
7113 }
7114 IE_END(EXQOS);
7115 }
7116
7117 /**************************************************************
7118 *
7119 * Free form IE (for testing mainly)
7120 */
7121 DEF_IE_PRINT(itu, unrec)
7122 {
7123 u_int i;
7124
7125 if (uni_print_iehdr("unrec", &ie->h, cx))
7126 return;
7127 uni_print_entry(cx, "len", "%u", ie->len);
7128 uni_print_entry(cx, "data", "(");
7129 for (i = 0; i < ie->len; i++)
7130 uni_printf(cx, "%s0x%02x", i == 0 ? "" : " ", ie->data[i]);
7131 uni_printf(cx, ")");
7132 uni_print_ieend(cx);
7133 }
7134
7135 DEF_IE_CHECK(itu, unrec)
7136 {
7137 UNUSED(cx);
7138
7139 if (ie->len > sizeof(ie->data))
7140 return (-1);
7141
7142 return (0);
7143 }
7144
7145 DEF_IE_ENCODE(itu, unrec)
7146 {
7147 START_IE2(unrec, UNI_IE_UNREC, ie->len, ie->id);
7148
7149 APP_BUF(msg, ie->data, ie->len);
7150
7151 SET_IE_LEN(msg);
7152 return (0);
7153 }
7154
7155 DEF_IE_DECODE(itu, unrec)
7156 {
7157 IE_START(;);
7158
7159 if (ielen > sizeof(ie->data) / sizeof(ie->data[0]) || ielen < 1)
7160 goto rej;
7161
7162 ie->len = ielen;
7163 ielen = 0;
7164 (void)memcpy(ie->data, msg->b_rptr, ie->len);
7165 msg->b_rptr += ie->len;
7166
7167 IE_END(UNREC);
7168 }
Cache object: cacf3bb7a036d3bb886aeecef36d6925
|