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