1121934Sharti/*
2121934Sharti * Copyright (c) 2001-2003
3121934Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121934Sharti * 	All rights reserved.
5121934Sharti *
6121934Sharti * Redistribution and use in source and binary forms, with or without
7121934Sharti * modification, are permitted provided that the following conditions
8121934Sharti * are met:
9121934Sharti * 1. Redistributions of source code must retain the above copyright
10121934Sharti *    notice, this list of conditions and the following disclaimer.
11121934Sharti * 2. Redistributions in binary form must reproduce the above copyright
12121934Sharti *    notice, this list of conditions and the following disclaimer in the
13121934Sharti *    documentation and/or other materials provided with the distribution.
14121934Sharti *
15121934Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121934Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121934Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121934Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121934Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121934Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121934Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121934Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121934Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121934Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121934Sharti * SUCH DAMAGE.
26121934Sharti *
27121934Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28121934Sharti *
29131826Sharti * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $
30121934Sharti *
31121934Sharti * Private definitions for the MSG code file.
32121934Sharti *
33121934Sharti * This file is included at the begin of the automatically generated
34121934Sharti * uni_msg.c.
35121934Sharti */
36121934Sharti
37121934Sharti/*
38121934Sharti * Decode a UNI message header.
39121934Sharti * Return values:
40121934Sharti *   0 - ok
41121934Sharti *  -1 - ignore message (proto, length, CR error)
42121934Sharti */
43121934Shartiint
44121934Shartiuni_decode_head(struct uni_msg *msg, struct uni_all *out,
45121934Sharti    struct unicx *cx __unused)
46121934Sharti{
47121934Sharti	u_int mlen;
48121934Sharti
49121934Sharti	cx->errcnt = 0;
50121934Sharti	(void)memset(out, 0, sizeof(struct uni_all));
51121934Sharti
52121934Sharti	if(uni_msg_len(msg) < 9)
53121934Sharti		return -1;			/* Q.2931 5.6.2 */
54121934Sharti	if(cx->pnni) {
55121934Sharti		if(*msg->b_rptr++ != PNNI_PROTO)
56121934Sharti			return -1;			/* Q.2931 5.6.1 */
57121934Sharti	} else {
58121934Sharti		if(*msg->b_rptr++ != UNI_PROTO)
59121934Sharti			return -1;			/* Q.2931 5.6.1 */
60121934Sharti	}
61121934Sharti	if(*msg->b_rptr++ != 3)
62121934Sharti		return -1;			/* Q.2931 5.6.3.1 */
63121934Sharti
64121934Sharti	out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0;
65121934Sharti	out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16;
66121934Sharti	out->u.hdr.cref.cref |= *msg->b_rptr++ << 8;
67121934Sharti	out->u.hdr.cref.cref |= *msg->b_rptr++;
68121934Sharti
69121934Sharti	out->mtype = *msg->b_rptr++;
70121934Sharti
71121934Sharti	/*
72121934Sharti	 * Be not too piggy about this byte
73121934Sharti	 */
74121934Sharti	switch(*msg->b_rptr & 0x13) {
75121934Sharti
76121934Sharti	  case 0x00: case 0x01: case 0x02: case 0x03:
77121934Sharti		out->u.hdr.act = UNI_MSGACT_DEFAULT;
78121934Sharti		break;
79121934Sharti
80121934Sharti	  case 0x10: case 0x11: case 0x12:
81121934Sharti		out->u.hdr.act = *msg->b_rptr & 0x3;
82121934Sharti		break;
83121934Sharti
84121934Sharti	  case 0x13:			/* Q.2931 5.7.1 */
85121934Sharti		out->u.hdr.act = UNI_MSGACT_REPORT;
86121934Sharti		break;
87121934Sharti	}
88121934Sharti	if(cx->pnni && (*msg->b_rptr & 0x08))
89121934Sharti		out->u.hdr.pass = 1;
90121934Sharti	else
91121934Sharti		out->u.hdr.pass = 0;
92121934Sharti
93121934Sharti	msg->b_rptr++;
94121934Sharti
95121934Sharti	mlen = *msg->b_rptr++ << 8;
96121934Sharti	mlen |= *msg->b_rptr++;
97121934Sharti
98121934Sharti	/*
99121934Sharti	 * If the message is longer than the indicated length
100121934Sharti	 * shorten it. If it is shorter, probably one of the IE
101121934Sharti	 * decoders will break, but we should proceed. 5.5.6.5
102121934Sharti	 */
103121934Sharti#if 0
104121934Sharti	if(uni_msg_len(msg) > mlen)
105121934Sharti		msg->b_wptr = msg->b_rptr + mlen;
106121934Sharti#endif
107121934Sharti
108121934Sharti	return 0;
109121934Sharti}
110121934Sharti
111121934Shartistatic int
112121934Shartiuni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg,
113121934Sharti    union uni_msgall *out, struct unicx *cx)
114121934Sharti{
115121934Sharti	enum uni_ietype ietype;
116121934Sharti	struct uni_iehdr hdr;
117121934Sharti	u_int ielen;
118121934Sharti	const struct iedecl *iedecl;
119121934Sharti	int err = 0, ret;
120121934Sharti	u_char *end;
121121934Sharti
122121934Sharti	cx->ielast = (enum uni_ietype)0;
123121934Sharti	cx->repeat.h.present = 0;
124121934Sharti
125121934Sharti	while (uni_msg_len(msg) != 0) {
126121934Sharti		if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) {
127121934Sharti			/*
128121934Sharti			 * Short header. Set the ielen to an impossible size.
129121934Sharti			 * Then we should bump out in the error handling below.
130121934Sharti			 * We should have at least an IE type here.
131121934Sharti			 */
132121934Sharti			ielen = 0xffffffff;
133121934Sharti		}
134121934Sharti#ifdef DTRACE
135121934Sharti		printf("IE %x\n", ietype);
136121934Sharti#endif
137121934Sharti
138121934Sharti		if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL ||
139121934Sharti		    ietype == UNI_IE_UNREC) {
140121934Sharti			/*
141121934Sharti			 * entirly unknown IE. Check the length and skip it.
142121934Sharti			 * Q.2931 5.6.8.1
143121934Sharti			 */
144121934Sharti			if (ielen > uni_msg_len(msg))
145121934Sharti				msg->b_rptr = msg->b_wptr;
146121934Sharti			else
147121934Sharti				msg->b_rptr += ielen;
148213789Srpaulo			(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
149121934Sharti			err = -1;
150121934Sharti			continue;
151121934Sharti		}
152121934Sharti#ifdef DTRACE
153121934Sharti		printf("IE %x known\n", ietype);
154121934Sharti#endif
155121934Sharti		if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) {
156121934Sharti			/*
157121934Sharti			 * Information element too long -> content error.
158121934Sharti			 * Let the decoding routine set the error flag and
159121934Sharti			 * return DEC_ERR.
160121934Sharti			 * Q.2931 5.6.8.2
161121934Sharti			 */
162121934Sharti#if 0
163121934Sharti			/*
164121934Sharti			 * It is not clear how to best handle this error.
165121934Sharti			 */
166121934Sharti			if (ielen > iedecl->maxlen - 4)
167121934Sharti				ielen = iedecl->maxlen - 4;
168121934Sharti#endif
169121934Sharti
170121934Sharti			if (ielen > uni_msg_len(msg))
171121934Sharti				ielen = uni_msg_len(msg);
172121934Sharti
173121934Sharti			hdr.present |= UNI_IE_ERROR;
174121934Sharti
175121934Sharti#ifdef DTRACE
176121934Sharti			printf("IE %x length too large\n", ietype);
177121934Sharti#endif
178121934Sharti		}
179121934Sharti
180121934Sharti#ifdef DTRACE
181121934Sharti		else
182121934Sharti			printf("IE %x length ok\n", ietype);
183121934Sharti#endif
184121934Sharti		end = msg->b_rptr + ielen;
185121934Sharti		ret = uni_msgtable[mtype]->decode(out, msg, ietype,
186121934Sharti		    &hdr, ielen, cx);
187121934Sharti		msg->b_rptr = end;
188121934Sharti
189121934Sharti#ifdef DTRACE
190121934Sharti		printf("IE %x ret %d\n", ietype, ret);
191121934Sharti#endif
192121934Sharti
193121934Sharti		switch (ret) {
194121934Sharti
195121934Sharti		  case DEC_OK:	/* ok */
196121934Sharti			break;
197121934Sharti
198121934Sharti		  case DEC_ILL:	/* illegal IE */
199121934Sharti			/*
200121934Sharti			 * Unexpected but recognized.
201121934Sharti			 * Q.2931 5.6.8.3
202121934Sharti			 */
203213789Srpaulo			(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
204121934Sharti			err = -1;
205121934Sharti			break;
206121934Sharti
207121934Sharti		  case DEC_ERR:	/* bad IE */
208121934Sharti			if (iedecl->flags & UNIFL_ACCESS)
209121934Sharti				/* this may be wrong: 5.6.8.2 */
210213789Srpaulo				(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC);
211121934Sharti			else
212213789Srpaulo				(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD);
213121934Sharti			err = -1;
214121934Sharti			break;
215121934Sharti
216121934Sharti		  default:
217121934Sharti			PANIC(("bad decode return"));
218121934Sharti		}
219121934Sharti	    	cx->ielast = ietype;
220121934Sharti	    	if (ietype != UNI_IE_REPEAT)
221121934Sharti			cx->repeat.h.present = 0;
222121934Sharti	}
223121934Sharti	return err;
224121934Sharti}
225121934Sharti
226121934Sharti/*
227121934Sharti * Decode the body of a message. The header is assumed to be decoded
228121934Sharti * already and out->hdr is filled in. Only information elements remain.
229121934Sharti */
230121934Shartiint
231121934Shartiuni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
232121934Sharti{
233121934Sharti	cx->errcnt = 0;
234121934Sharti	if (out->mtype >= 256)
235121934Sharti		return (-1);
236121934Sharti	if (uni_msgtable[out->mtype] == NULL)
237121934Sharti		return (-1);
238121934Sharti	return (uni_decode_body_internal(out->mtype, msg, &out->u, cx));
239121934Sharti}
240121934Sharti
241121934Sharti
242121934Sharti/*
243121934Sharti * Decode a uni message
244121934Sharti */
245121934Shartiint
246121934Shartiuni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
247121934Sharti{
248121934Sharti	cx->errcnt = 0;
249121934Sharti	if (uni_decode_head(msg, out, cx))
250121934Sharti		return (-1);
251121934Sharti	if (uni_decode_body(msg, out, cx))
252121934Sharti		return (-2);
253121934Sharti	return (0);
254121934Sharti}
255121934Sharti
256121934Shartiint
257121934Shartiuni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx)
258121934Sharti{
259121934Sharti	if (in->mtype >= 256)
260121934Sharti		return (-1);
261121934Sharti	if (uni_msgtable[in->mtype] == NULL)
262121934Sharti		return (-3);
263121934Sharti
264121934Sharti	return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx));
265121934Sharti}
266121934Sharti
267121934Sharti/*
268121934Sharti * Doesn't belong here
269121934Sharti */
270121934Shartivoid
271121934Shartiuni_initcx(struct unicx *cx)
272121934Sharti{
273121934Sharti	memset(cx, 0, sizeof(struct unicx));
274121934Sharti	cx->tabsiz = 4;
275121934Sharti}
276