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