privmsg.c revision 131827
182498Sroberto/* 282498Sroberto * Copyright (c) 2001-2003 382498Sroberto * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 482498Sroberto * All rights reserved. 582498Sroberto * 682498Sroberto * Redistribution and use in source and binary forms, with or without 782498Sroberto * modification, are permitted provided that the following conditions 8132451Sroberto * are met: 982498Sroberto * 1. Redistributions of source code must retain the above copyright 1082498Sroberto * notice, this list of conditions and the following disclaimer. 11132451Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1282498Sroberto * notice, this list of conditions and the following disclaimer in the 1382498Sroberto * documentation and/or other materials provided with the distribution. 1482498Sroberto * 1582498Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1682498Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17132451Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1882498Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19182007Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2082498Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21132451Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22132451Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23132451Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24132451Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25132451Sroberto * SUCH DAMAGE. 26132451Sroberto * 27132451Sroberto * Author: Hartmut Brandt <harti@freebsd.org> 28132451Sroberto * 2982498Sroberto * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $ 3082498Sroberto * 3182498Sroberto * Private definitions for the MSG code file. 3282498Sroberto * 3382498Sroberto * This file is included at the begin of the automatically generated 34132451Sroberto * uni_msg.c. 3582498Sroberto */ 36132451Sroberto 37132451Sroberto/* 38132451Sroberto * Decode a UNI message header. 3982498Sroberto * Return values: 40132451Sroberto * 0 - ok 41132451Sroberto * -1 - ignore message (proto, length, CR error) 42132451Sroberto */ 43132451Srobertoint 44132451Srobertouni_decode_head(struct uni_msg *msg, struct uni_all *out, 45132451Sroberto struct unicx *cx __unused) 46132451Sroberto{ 47132451Sroberto u_int mlen; 48132451Sroberto 49132451Sroberto cx->errcnt = 0; 50132451Sroberto (void)memset(out, 0, sizeof(struct uni_all)); 51132451Sroberto 52132451Sroberto if(uni_msg_len(msg) < 9) 53132451Sroberto return -1; /* Q.2931 5.6.2 */ 54132451Sroberto if(cx->pnni) { 55132451Sroberto if(*msg->b_rptr++ != PNNI_PROTO) 56132451Sroberto return -1; /* Q.2931 5.6.1 */ 57132451Sroberto } else { 58132451Sroberto if(*msg->b_rptr++ != UNI_PROTO) 59132451Sroberto return -1; /* Q.2931 5.6.1 */ 60132451Sroberto } 6182498Sroberto if(*msg->b_rptr++ != 3) 62132451Sroberto return -1; /* Q.2931 5.6.3.1 */ 63132451Sroberto 64132451Sroberto out->u.hdr.cref.flag = (*msg->b_rptr & 0x80) ? 1 : 0; 65132451Sroberto out->u.hdr.cref.cref = (*msg->b_rptr++ & 0x7f) << 16; 66132451Sroberto out->u.hdr.cref.cref |= *msg->b_rptr++ << 8; 67132451Sroberto out->u.hdr.cref.cref |= *msg->b_rptr++; 68132451Sroberto 69132451Sroberto out->mtype = *msg->b_rptr++; 70132451Sroberto 71132451Sroberto /* 72132451Sroberto * Be not too piggy about this byte 73132451Sroberto */ 74132451Sroberto switch(*msg->b_rptr & 0x13) { 75132451Sroberto 76132451Sroberto case 0x00: case 0x01: case 0x02: case 0x03: 77132451Sroberto out->u.hdr.act = UNI_MSGACT_DEFAULT; 78132451Sroberto break; 79132451Sroberto 80132451Sroberto case 0x10: case 0x11: case 0x12: 81132451Sroberto out->u.hdr.act = *msg->b_rptr & 0x3; 82132451Sroberto break; 83132451Sroberto 84132451Sroberto case 0x13: /* Q.2931 5.7.1 */ 85132451Sroberto out->u.hdr.act = UNI_MSGACT_REPORT; 86132451Sroberto break; 87132451Sroberto } 88132451Sroberto if(cx->pnni && (*msg->b_rptr & 0x08)) 8982498Sroberto out->u.hdr.pass = 1; 9082498Sroberto else 91132451Sroberto out->u.hdr.pass = 0; 9282498Sroberto 93132451Sroberto msg->b_rptr++; 94132451Sroberto 95132451Sroberto mlen = *msg->b_rptr++ << 8; 96132451Sroberto mlen |= *msg->b_rptr++; 9782498Sroberto 9882498Sroberto /* 99132451Sroberto * If the message is longer than the indicated length 10082498Sroberto * shorten it. If it is shorter, probably one of the IE 101132451Sroberto * decoders will break, but we should proceed. 5.5.6.5 10282498Sroberto */ 10382498Sroberto#if 0 104132451Sroberto if(uni_msg_len(msg) > mlen) 10582498Sroberto msg->b_wptr = msg->b_rptr + mlen; 106132451Sroberto#endif 107132451Sroberto 108132451Sroberto return 0; 109132451Sroberto} 110182007Sroberto 111182007Srobertostatic int 112182007Srobertouni_decode_body_internal(enum uni_msgtype mtype, struct uni_msg *msg, 113182007Sroberto union uni_msgall *out, struct unicx *cx) 114182007Sroberto{ 115182007Sroberto enum uni_ietype ietype; 11682498Sroberto struct uni_iehdr hdr; 11782498Sroberto u_int ielen; 118132451Sroberto const struct iedecl *iedecl; 11982498Sroberto int err = 0, ret; 120132451Sroberto u_char *end; 121132451Sroberto 122132451Sroberto cx->ielast = (enum uni_ietype)0; 123132451Sroberto cx->repeat.h.present = 0; 124132451Sroberto 125132451Sroberto while (uni_msg_len(msg) != 0) { 126132451Sroberto if (uni_decode_ie_hdr(&ietype, &hdr, msg, cx, &ielen)) { 127132451Sroberto /* 128132451Sroberto * Short header. Set the ielen to an impossible size. 129132451Sroberto * Then we should bump out in the error handling below. 130182007Sroberto * We should have at least an IE type here. 131132451Sroberto */ 132182007Sroberto ielen = 0xffffffff; 133182007Sroberto } 13482498Sroberto#ifdef DTRACE 13582498Sroberto printf("IE %x\n", ietype); 13682498Sroberto#endif 13782498Sroberto 138132451Sroberto if ((iedecl = GET_IEDECL(ietype, hdr.coding)) == NULL || 139132451Sroberto ietype == UNI_IE_UNREC) { 140132451Sroberto /* 141132451Sroberto * entirly unknown IE. Check the length and skip it. 142132451Sroberto * Q.2931 5.6.8.1 143132451Sroberto */ 144132451Sroberto if (ielen > uni_msg_len(msg)) 145132451Sroberto msg->b_rptr = msg->b_wptr; 146132451Sroberto else 147132451Sroberto msg->b_rptr += ielen; 148132451Sroberto UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK); 149132451Sroberto err = -1; 150132451Sroberto continue; 151132451Sroberto } 152132451Sroberto#ifdef DTRACE 153132451Sroberto printf("IE %x known\n", ietype); 154132451Sroberto#endif 155132451Sroberto if (ielen > iedecl->maxlen - 4 || ielen > uni_msg_len(msg)) { 156132451Sroberto /* 157132451Sroberto * Information element too long -> content error. 158132451Sroberto * Let the decoding routine set the error flag and 159132451Sroberto * return DEC_ERR. 160132451Sroberto * Q.2931 5.6.8.2 161132451Sroberto */ 16282498Sroberto#if 0 16382498Sroberto /* 164132451Sroberto * It is not clear how to best handle this error. 165132451Sroberto */ 166132451Sroberto if (ielen > iedecl->maxlen - 4) 167132451Sroberto ielen = iedecl->maxlen - 4; 168132451Sroberto#endif 169132451Sroberto 17082498Sroberto if (ielen > uni_msg_len(msg)) 17182498Sroberto ielen = uni_msg_len(msg); 17282498Sroberto 17382498Sroberto hdr.present |= UNI_IE_ERROR; 17482498Sroberto 17582498Sroberto#ifdef DTRACE 17682498Sroberto printf("IE %x length too large\n", ietype); 17782498Sroberto#endif 178132451Sroberto } 179132451Sroberto 18082498Sroberto#ifdef DTRACE 181132451Sroberto else 18282498Sroberto printf("IE %x length ok\n", ietype); 183132451Sroberto#endif 184132451Sroberto end = msg->b_rptr + ielen; 185132451Sroberto ret = uni_msgtable[mtype]->decode(out, msg, ietype, 186132451Sroberto &hdr, ielen, cx); 187132451Sroberto msg->b_rptr = end; 18882498Sroberto 18982498Sroberto#ifdef DTRACE 190132451Sroberto printf("IE %x ret %d\n", ietype, ret); 191132451Sroberto#endif 192132451Sroberto 193132451Sroberto switch (ret) { 194132451Sroberto 19582498Sroberto case DEC_OK: /* ok */ 196182007Sroberto break; 197182007Sroberto 198182007Sroberto case DEC_ILL: /* illegal IE */ 19982498Sroberto /* 20082498Sroberto * Unexpected but recognized. 20182498Sroberto * Q.2931 5.6.8.3 20282498Sroberto */ 203132451Sroberto UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_UNK); 204132451Sroberto err = -1; 205132451Sroberto break; 206132451Sroberto 207132451Sroberto case DEC_ERR: /* bad IE */ 208132451Sroberto if (iedecl->flags & UNIFL_ACCESS) 209132451Sroberto /* this may be wrong: 5.6.8.2 */ 210132451Sroberto UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_ACC); 211132451Sroberto else 212182007Sroberto UNI_SAVE_IERR(cx, ietype, hdr.act, UNI_IERR_BAD); 213132451Sroberto err = -1; 214132451Sroberto break; 215132451Sroberto 216132451Sroberto default: 217132451Sroberto PANIC(("bad decode return")); 218132451Sroberto } 219132451Sroberto cx->ielast = ietype; 220132451Sroberto if (ietype != UNI_IE_REPEAT) 221132451Sroberto cx->repeat.h.present = 0; 222132451Sroberto } 223132451Sroberto return err; 224132451Sroberto} 225132451Sroberto 226132451Sroberto/* 22782498Sroberto * Decode the body of a message. The header is assumed to be decoded 22882498Sroberto * already and out->hdr is filled in. Only information elements remain. 229132451Sroberto */ 23082498Srobertoint 23182498Srobertouni_decode_body(struct uni_msg *msg, struct uni_all *out, struct unicx *cx) 23282498Sroberto{ 23382498Sroberto cx->errcnt = 0; 23482498Sroberto if (out->mtype >= 256) 23582498Sroberto return (-1); 236132451Sroberto if (uni_msgtable[out->mtype] == NULL) 23782498Sroberto return (-1); 23882498Sroberto return (uni_decode_body_internal(out->mtype, msg, &out->u, cx)); 23982498Sroberto} 24082498Sroberto 24182498Sroberto 24282498Sroberto/* 24382498Sroberto * Decode a uni message 24482498Sroberto */ 24582498Srobertoint 246182007Srobertouni_decode(struct uni_msg *msg, struct uni_all *out, struct unicx *cx) 247182007Sroberto{ 248182007Sroberto cx->errcnt = 0; 249182007Sroberto if (uni_decode_head(msg, out, cx)) 25082498Sroberto return (-1); 25182498Sroberto if (uni_decode_body(msg, out, cx)) 25282498Sroberto return (-2); 25382498Sroberto return (0); 25482498Sroberto} 25582498Sroberto 256182007Srobertoint 25782498Srobertouni_encode(struct uni_msg *msg, struct uni_all *in, struct unicx *cx) 25882498Sroberto{ 25982498Sroberto if (in->mtype >= 256) 26082498Sroberto return (-1); 26182498Sroberto if (uni_msgtable[in->mtype] == NULL) 262132451Sroberto return (-3); 263132451Sroberto 26482498Sroberto return ((uni_msgtable[in->mtype]->encode)(msg, &in->u, cx)); 265132451Sroberto} 266132451Sroberto 267132451Sroberto/* 268132451Sroberto * Doesn't belong here 269182007Sroberto */ 270132451Srobertovoid 27182498Srobertouni_initcx(struct unicx *cx) 272182007Sroberto{ 273182007Sroberto memset(cx, 0, sizeof(struct unicx)); 274182007Sroberto cx->tabsiz = 4; 27582498Sroberto} 27682498Sroberto