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