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