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 *
|
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 */ 43int 44uni_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 111static int 112uni_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 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 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 UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC); 211 else 212 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 */ 230int 231uni_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 */ 245int 246uni_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 256int 257uni_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 */ 270void 271uni_initcx(struct unicx *cx) 272{ 273 memset(cx, 0, sizeof(struct unicx)); 274 cx->tabsiz = 4; 275}
|