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