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