/* * Copyright (c) 2001-2003 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Author: Hartmut Brandt * * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $ * * Private definitions for the MSG code file. * * This file is included at the begin of the automatically generated * uni_msg.c. */ /* * Decode a UNI message header. * Return values: * 0 - ok * -1 - ignore message (proto, length, CR error) */ int uni_decode_head(struct uni_msg *msg, struct uni_all *out, struct unicx *cx __unused) { u_int mlen; cx->errcnt = 0; (void)memset(out, 0, sizeof(struct uni_all)); if(uni_msg_len(msg) < 9) return -1; /* Q.2931 5.6.2 */ if(cx->pnni) { if(*msg->b_rptr++ != PNNI_PROTO) return -1; /* Q.2931 5.6.1 */ } else { if(*msg->b_rptr++ != UNI_PROTO) return -1; /* Q.2931 5.6.1 */ } if(*msg->b_rptr++ != 3) return -1; /* Q.2931 5.6.3.1 */ out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0; out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16; out->u.hdr.cref.cref |= *msg->b_rptr++ << 8; out->u.hdr.cref.cref |= *msg->b_rptr++; out->mtype = *msg->b_rptr++; /* * Be not too piggy about this byte */ switch(*msg->b_rptr & 0x13) { case 0x00: case 0x01: case 0x02: case 0x03: out->u.hdr.act = UNI_MSGACT_DEFAULT; break; case 0x10: case 0x11: case 0x12: out->u.hdr.act = *msg->b_rptr & 0x3; break; case 0x13: /* Q.2931 5.7.1 */ out->u.hdr.act = UNI_MSGACT_REPORT; break; } if(cx->pnni && (*msg->b_rptr & 0x08)) out->u.hdr.pass = 1; else out->u.hdr.pass = 0; msg->b_rptr++; mlen = *msg->b_rptr++ << 8; mlen |= *msg->b_rptr++; /* * If the message is longer than the indicated length * shorten it. If it is shorter, probably one of the IE * decoders will break, but we should proceed. 5.5.6.5 */ #if 0 if(uni_msg_len(msg) > mlen) msg->b_wptr = msg->b_rptr + mlen; #endif return 0; } static int uni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg, union uni_msgall *out, struct unicx *cx) { enum uni_ietype ietype; struct uni_iehdr hdr; u_int ielen; const struct iedecl *iedecl; int err = 0, ret; u_char *end; cx->ielast = (enum uni_ietype)0; cx->repeat.h.present = 0; while (uni_msg_len(msg) != 0) { if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) { /* * Short header. Set the ielen to an impossible size. * Then we should bump out in the error handling below. * We should have at least an IE type here. */ ielen = 0xffffffff; } #ifdef DTRACE printf("IE %x\n", ietype); #endif if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL || ietype == UNI_IE_UNREC) { /* * entirly unknown IE. Check the length and skip it. * Q.2931 5.6.8.1 */ if (ielen > uni_msg_len(msg)) msg->b_rptr = msg->b_wptr; else msg->b_rptr += ielen; (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK); err = -1; continue; } #ifdef DTRACE printf("IE %x known\n", ietype); #endif if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) { /* * Information element too long -> content error. * Let the decoding routine set the error flag and * return DEC_ERR. * Q.2931 5.6.8.2 */ #if 0 /* * It is not clear how to best handle this error. */ if (ielen > iedecl->maxlen - 4) ielen = iedecl->maxlen - 4; #endif if (ielen > uni_msg_len(msg)) ielen = uni_msg_len(msg); hdr.present |= UNI_IE_ERROR; #ifdef DTRACE printf("IE %x length too large\n", ietype); #endif } #ifdef DTRACE else printf("IE %x length ok\n", ietype); #endif end = msg->b_rptr + ielen; ret = uni_msgtable[mtype]->decode(out, msg, ietype, &hdr, ielen, cx); msg->b_rptr = end; #ifdef DTRACE printf("IE %x ret %d\n", ietype, ret); #endif switch (ret) { case DEC_OK: /* ok */ break; case DEC_ILL: /* illegal IE */ /* * Unexpected but recognized. * Q.2931 5.6.8.3 */ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK); err = -1; break; case DEC_ERR: /* bad IE */ if (iedecl->flags & UNIFL_ACCESS) /* this may be wrong: 5.6.8.2 */ (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC); else (void)UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD); err = -1; break; default: PANIC(("bad decode return")); } cx->ielast = ietype; if (ietype != UNI_IE_REPEAT) cx->repeat.h.present = 0; } return err; } /* * Decode the body of a message. The header is assumed to be decoded * already and out->hdr is filled in. Only information elements remain. */ int uni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx) { cx->errcnt = 0; if (out->mtype >= 256) return (-1); if (uni_msgtable[out->mtype] == NULL) return (-1); return (uni_decode_body_internal(out->mtype, msg, &out->u, cx)); } /* * Decode a uni message */ int uni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx) { cx->errcnt = 0; if (uni_decode_head(msg, out, cx)) return (-1); if (uni_decode_body(msg, out, cx)) return (-2); return (0); } int uni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx) { if (in->mtype >= 256) return (-1); if (uni_msgtable[in->mtype] == NULL) return (-3); return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx)); } /* * Doesn't belong here */ void uni_initcx(struct unicx *cx) { memset(cx, 0, sizeof(struct unicx)); cx->tabsiz = 4; }