]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/msg/privmsg.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / msg / privmsg.c
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         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
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
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
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
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
271 uni_initcx(struct unicx *cx)
272 {
273         memset(cx, 0, sizeof(struct unicx));
274         cx->tabsiz = 4;
275 }