1 /*
2  * Copyright (c) 2001-2003
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  * 	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <[email protected]>
28  *
29  * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $
30  *
31  * Private definitions for the MSG code file.
32  *
33  * This file is included at the begin of the automatically generated
34  * uni_msg.c.
35  */
36 
37 /*
38  * Decode a UNI message header.
39  * Return values:
40  *   0 - ok
41  *  -1 - ignore message (proto, length, CR error)
42  */
43 int
uni_decode_head(struct uni_msg * msg,struct uni_all * out,struct unicx * cx __unused)44 uni_decode_head(struct uni_msg *msg, struct uni_all *out,
45     struct unicx *cx __unused)
46 {
47 	u_int mlen;
48 
49 	cx->errcnt = 0;
50 	(void)memset(out, 0, sizeof(struct uni_all));
51 
52 	if(uni_msg_len(msg) < 9)
53 		return -1;			/* Q.2931 5.6.2 */
54 	if(cx->pnni) {
55 		if(*msg->b_rptr++ != PNNI_PROTO)
56 			return -1;			/* Q.2931 5.6.1 */
57 	} else {
58 		if(*msg->b_rptr++ != UNI_PROTO)
59 			return -1;			/* Q.2931 5.6.1 */
60 	}
61 	if(*msg->b_rptr++ != 3)
62 		return -1;			/* Q.2931 5.6.3.1 */
63 
64 	out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0;
65 	out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16;
66 	out->u.hdr.cref.cref |= *msg->b_rptr++ << 8;
67 	out->u.hdr.cref.cref |= *msg->b_rptr++;
68 
69 	out->mtype = *msg->b_rptr++;
70 
71 	/*
72 	 * Be not too piggy about this byte
73 	 */
74 	switch(*msg->b_rptr & 0x13) {
75 
76 	  case 0x00: case 0x01: case 0x02: case 0x03:
77 		out->u.hdr.act = UNI_MSGACT_DEFAULT;
78 		break;
79 
80 	  case 0x10: case 0x11: case 0x12:
81 		out->u.hdr.act = *msg->b_rptr & 0x3;
82 		break;
83 
84 	  case 0x13:			/* Q.2931 5.7.1 */
85 		out->u.hdr.act = UNI_MSGACT_REPORT;
86 		break;
87 	}
88 	if(cx->pnni && (*msg->b_rptr & 0x08))
89 		out->u.hdr.pass = 1;
90 	else
91 		out->u.hdr.pass = 0;
92 
93 	msg->b_rptr++;
94 
95 	mlen = *msg->b_rptr++ << 8;
96 	mlen |= *msg->b_rptr++;
97 
98 	/*
99 	 * If the message is longer than the indicated length
100 	 * shorten it. If it is shorter, probably one of the IE
101 	 * decoders will break, but we should proceed. 5.5.6.5
102 	 */
103 #if 0
104 	if(uni_msg_len(msg) > mlen)
105 		msg->b_wptr = msg->b_rptr + mlen;
106 #endif
107 
108 	return 0;
109 }
110 
111 static int
uni_decode_body_internal(enum uni_msgtype mtype,struct uni_msg * msg,union uni_msgall * out,struct unicx * cx)112 uni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg,
113     union uni_msgall *out, struct unicx *cx)
114 {
115 	enum uni_ietype ietype;
116 	struct uni_iehdr hdr;
117 	u_int ielen;
118 	const struct iedecl *iedecl;
119 	int err = 0, ret;
120 	u_char *end;
121 
122 	cx->ielast = (enum uni_ietype)0;
123 	cx->repeat.h.present = 0;
124 
125 	while (uni_msg_len(msg) != 0) {
126 		if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) {
127 			/*
128 			 * Short header. Set the ielen to an impossible size.
129 			 * Then we should bump out in the error handling below.
130 			 * We should have at least an IE type here.
131 			 */
132 			ielen = 0xffffffff;
133 		}
134 #ifdef DTRACE
135 		printf("IE %x\n", ietype);
136 #endif
137 
138 		if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL ||
139 		    ietype == UNI_IE_UNREC) {
140 			/*
141 			 * entirly unknown IE. Check the length and skip it.
142 			 * Q.2931 5.6.8.1
143 			 */
144 			if (ielen > uni_msg_len(msg))
145 				msg->b_rptr = msg->b_wptr;
146 			else
147 				msg->b_rptr += ielen;
148 			(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
149 			err = -1;
150 			continue;
151 		}
152 #ifdef DTRACE
153 		printf("IE %x known\n", ietype);
154 #endif
155 		if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) {
156 			/*
157 			 * Information element too long -> content error.
158 			 * Let the decoding routine set the error flag and
159 			 * return DEC_ERR.
160 			 * Q.2931 5.6.8.2
161 			 */
162 #if 0
163 			/*
164 			 * It is not clear how to best handle this error.
165 			 */
166 			if (ielen > iedecl->maxlen - 4)
167 				ielen = iedecl->maxlen - 4;
168 #endif
169 
170 			if (ielen > uni_msg_len(msg))
171 				ielen = uni_msg_len(msg);
172 
173 			hdr.present |= UNI_IE_ERROR;
174 
175 #ifdef DTRACE
176 			printf("IE %x length too large\n", ietype);
177 #endif
178 		}
179 
180 #ifdef DTRACE
181 		else
182 			printf("IE %x length ok\n", ietype);
183 #endif
184 		end = msg->b_rptr + ielen;
185 		ret = uni_msgtable[mtype]->decode(out, msg, ietype,
186 		    &hdr, ielen, cx);
187 		msg->b_rptr = end;
188 
189 #ifdef DTRACE
190 		printf("IE %x ret %d\n", ietype, ret);
191 #endif
192 
193 		switch (ret) {
194 
195 		  case DEC_OK:	/* ok */
196 			break;
197 
198 		  case DEC_ILL:	/* illegal IE */
199 			/*
200 			 * Unexpected but recognized.
201 			 * Q.2931 5.6.8.3
202 			 */
203 			(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
204 			err = -1;
205 			break;
206 
207 		  case DEC_ERR:	/* bad IE */
208 			if (iedecl->flags & UNIFL_ACCESS)
209 				/* this may be wrong: 5.6.8.2 */
210 				(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC);
211 			else
212 				(void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD);
213 			err = -1;
214 			break;
215 
216 		  default:
217 			PANIC(("bad decode return"));
218 		}
219 	    	cx->ielast = ietype;
220 	    	if (ietype != UNI_IE_REPEAT)
221 			cx->repeat.h.present = 0;
222 	}
223 	return err;
224 }
225 
226 /*
227  * Decode the body of a message. The header is assumed to be decoded
228  * already and out->hdr is filled in. Only information elements remain.
229  */
230 int
uni_decode_body(struct uni_msg * msg,struct uni_all * out,struct unicx * cx)231 uni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
232 {
233 	cx->errcnt = 0;
234 	if (out->mtype >= 256)
235 		return (-1);
236 	if (uni_msgtable[out->mtype] == NULL)
237 		return (-1);
238 	return (uni_decode_body_internal(out->mtype, msg, &out->u, cx));
239 }
240 
241 
242 /*
243  * Decode a uni message
244  */
245 int
uni_decode(struct uni_msg * msg,struct uni_all * out,struct unicx * cx)246 uni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
247 {
248 	cx->errcnt = 0;
249 	if (uni_decode_head(msg, out, cx))
250 		return (-1);
251 	if (uni_decode_body(msg, out, cx))
252 		return (-2);
253 	return (0);
254 }
255 
256 int
uni_encode(struct uni_msg * msg,struct uni_all * in,struct unicx * cx)257 uni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx)
258 {
259 	if (in->mtype >= 256)
260 		return (-1);
261 	if (uni_msgtable[in->mtype] == NULL)
262 		return (-3);
263 
264 	return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx));
265 }
266 
267 /*
268  * Doesn't belong here
269  */
270 void
uni_initcx(struct unicx * cx)271 uni_initcx(struct unicx *cx)
272 {
273 	memset(cx, 0, sizeof(struct unicx));
274 	cx->tabsiz = 4;
275 }
276