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