diff options
Diffstat (limited to 'sys/contrib/ngatm/netnatm/msg/privmsg.c')
-rw-r--r-- | sys/contrib/ngatm/netnatm/msg/privmsg.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/msg/privmsg.c b/sys/contrib/ngatm/netnatm/msg/privmsg.c new file mode 100644 index 0000000..76a7f69 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/msg/privmsg.c @@ -0,0 +1,275 @@ +/* + * 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 <harti@freebsd.org> + * + * $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; +} |