The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ngatm/netnatm/msg/uni_ie.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: cacf3bb7a036d3bb886aeecef36d6925


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.