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/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
44 uni_decode_head(struct uni_msg *msg, struct uni_all *out,
45 struct unicx *cx __unused)
46 {
47 #if 0
48 u_int mlen;
49 #endif
50
51 cx->errcnt = 0;
52 (void)memset(out, 0, sizeof(struct uni_all));
53
54 if(uni_msg_len(msg) < 9)
55 return -1; /* Q.2931 5.6.2 */
56 if(cx->pnni) {
57 if(*msg->b_rptr++ != PNNI_PROTO)
58 return -1; /* Q.2931 5.6.1 */
59 } else {
60 if(*msg->b_rptr++ != UNI_PROTO)
61 return -1; /* Q.2931 5.6.1 */
62 }
63 if(*msg->b_rptr++ != 3)
64 return -1; /* Q.2931 5.6.3.1 */
65
66 out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0;
67 out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16;
68 out->u.hdr.cref.cref |= *msg->b_rptr++ << 8;
69 out->u.hdr.cref.cref |= *msg->b_rptr++;
70
71 out->mtype = *msg->b_rptr++;
72
73 /*
74 * Be not too piggy about this byte
75 */
76 switch(*msg->b_rptr & 0x13) {
77
78 case 0x00: case 0x01: case 0x02: case 0x03:
79 out->u.hdr.act = UNI_MSGACT_DEFAULT;
80 break;
81
82 case 0x10: case 0x11: case 0x12:
83 out->u.hdr.act = *msg->b_rptr & 0x3;
84 break;
85
86 case 0x13: /* Q.2931 5.7.1 */
87 out->u.hdr.act = UNI_MSGACT_REPORT;
88 break;
89 }
90 if(cx->pnni && (*msg->b_rptr & 0x08))
91 out->u.hdr.pass = 1;
92 else
93 out->u.hdr.pass = 0;
94
95 msg->b_rptr++;
96
97 #if 0
98 mlen = *msg->b_rptr++ << 8;
99 mlen |= *msg->b_rptr++;
100
101 /*
102 * If the message is longer than the indicated length
103 * shorten it. If it is shorter, probably one of the IE
104 * decoders will break, but we should proceed. 5.5.6.5
105 */
106 if(uni_msg_len(msg) > mlen)
107 msg->b_wptr = msg->b_rptr + mlen;
108 #endif
109
110 return 0;
111 }
112
113 static int
114 uni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg,
115 union uni_msgall *out, struct unicx *cx)
116 {
117 enum uni_ietype ietype;
118 struct uni_iehdr hdr;
119 u_int ielen;
120 const struct iedecl *iedecl;
121 int err = 0, ret;
122 u_char *end;
123
124 cx->ielast = (enum uni_ietype)0;
125 cx->repeat.h.present = 0;
126
127 while (uni_msg_len(msg) != 0) {
128 if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) {
129 /*
130 * Short header. Set the ielen to an impossible size.
131 * Then we should bump out in the error handling below.
132 * We should have at least an IE type here.
133 */
134 ielen = 0xffffffff;
135 }
136 #ifdef DTRACE
137 printf("IE %x\n", ietype);
138 #endif
139
140 if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL ||
141 ietype == UNI_IE_UNREC) {
142 /*
143 * entirly unknown IE. Check the length and skip it.
144 * Q.2931 5.6.8.1
145 */
146 if (ielen > uni_msg_len(msg))
147 msg->b_rptr = msg->b_wptr;
148 else
149 msg->b_rptr += ielen;
150 (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
151 err = -1;
152 continue;
153 }
154 #ifdef DTRACE
155 printf("IE %x known\n", ietype);
156 #endif
157 if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) {
158 /*
159 * Information element too long -> content error.
160 * Let the decoding routine set the error flag and
161 * return DEC_ERR.
162 * Q.2931 5.6.8.2
163 */
164 #if 0
165 /*
166 * It is not clear how to best handle this error.
167 */
168 if (ielen > iedecl->maxlen - 4)
169 ielen = iedecl->maxlen - 4;
170 #endif
171
172 if (ielen > uni_msg_len(msg))
173 ielen = uni_msg_len(msg);
174
175 hdr.present |= UNI_IE_ERROR;
176
177 #ifdef DTRACE
178 printf("IE %x length too large\n", ietype);
179 #endif
180 }
181
182 #ifdef DTRACE
183 else
184 printf("IE %x length ok\n", ietype);
185 #endif
186 end = msg->b_rptr + ielen;
187 ret = uni_msgtable[mtype]->decode(out, msg, ietype,
188 &hdr, ielen, cx);
189 msg->b_rptr = end;
190
191 #ifdef DTRACE
192 printf("IE %x ret %d\n", ietype, ret);
193 #endif
194
195 switch (ret) {
196
197 case DEC_OK: /* ok */
198 break;
199
200 case DEC_ILL: /* illegal IE */
201 /*
202 * Unexpected but recognized.
203 * Q.2931 5.6.8.3
204 */
205 (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK);
206 err = -1;
207 break;
208
209 case DEC_ERR: /* bad IE */
210 if (iedecl->flags & UNIFL_ACCESS)
211 /* this may be wrong: 5.6.8.2 */
212 (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC);
213 else
214 (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD);
215 err = -1;
216 break;
217
218 default:
219 PANIC(("bad decode return"));
220 }
221 cx->ielast = ietype;
222 if (ietype != UNI_IE_REPEAT)
223 cx->repeat.h.present = 0;
224 }
225 return err;
226 }
227
228 /*
229 * Decode the body of a message. The header is assumed to be decoded
230 * already and out->hdr is filled in. Only information elements remain.
231 */
232 int
233 uni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
234 {
235 cx->errcnt = 0;
236 if (out->mtype >= 256)
237 return (-1);
238 if (uni_msgtable[out->mtype] == NULL)
239 return (-1);
240 return (uni_decode_body_internal(out->mtype, msg, &out->u, cx));
241 }
242
243
244 /*
245 * Decode a uni message
246 */
247 int
248 uni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx)
249 {
250 cx->errcnt = 0;
251 if (uni_decode_head(msg, out, cx))
252 return (-1);
253 if (uni_decode_body(msg, out, cx))
254 return (-2);
255 return (0);
256 }
257
258 int
259 uni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx)
260 {
261 if (in->mtype >= 256)
262 return (-1);
263 if (uni_msgtable[in->mtype] == NULL)
264 return (-3);
265
266 return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx));
267 }
268
269 /*
270 * Doesn't belong here
271 */
272 void
273 uni_initcx(struct unicx *cx)
274 {
275 memset(cx, 0, sizeof(struct unicx));
276 cx->tabsiz = 4;
277 }
Cache object: ff69a0b12faf44344668125e34be2098
|