1122205Sharti/*
2122205Sharti * Copyright (c) 2001-2003
3122205Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4122205Sharti * 	All rights reserved.
5122205Sharti *
6122205Sharti * Redistribution and use in source and binary forms, with or without
7122205Sharti * modification, are permitted provided that the following conditions
8122205Sharti * are met:
9122205Sharti * 1. Redistributions of source code must retain the above copyright
10122205Sharti *    notice, this list of conditions and the following disclaimer.
11122205Sharti * 2. Redistributions in binary form must reproduce the above copyright
12122205Sharti *    notice, this list of conditions and the following disclaimer in the
13122205Sharti *    documentation and/or other materials provided with the distribution.
14122205Sharti *
15122205Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16122205Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17122205Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18122205Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19122205Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20122205Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21122205Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22122205Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23122205Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24122205Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25122205Sharti * SUCH DAMAGE.
26122205Sharti *
27122205Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28122205Sharti *
29131826Sharti * $Begemot: libunimsg/netnatm/sig/sig_verify.c,v 1.19 2004/07/08 08:22:23 brandt Exp $
30122205Sharti *
31122205Sharti * Message verification with explicit action indicators.
32122205Sharti */
33122205Sharti
34122205Sharti#include <netnatm/unimsg.h>
35122205Sharti#include <netnatm/saal/sscfudef.h>
36122205Sharti#include <netnatm/msg/unistruct.h>
37122205Sharti#include <netnatm/msg/unimsglib.h>
38122205Sharti#include <netnatm/sig/uni.h>
39122205Sharti
40122205Sharti#include <netnatm/sig/unipriv.h>
41122205Sharti#include <netnatm/sig/unimkmsg.h>
42122205Sharti
43122205Shartivoid
44122205Shartiuni_mandate_ie(struct uni *uni, enum uni_ietype ie)
45122205Sharti{
46122205Sharti	struct uni_ierr *e;
47122205Sharti
48122205Sharti	FOREACH_ERR(e, uni)
49122205Sharti		if (e->ie == ie) {
50122205Sharti			e->man = 1;
51122205Sharti			return;
52122205Sharti		}
53122205Sharti	if (UNI_SAVE_IERR(&uni->cx, ie, UNI_IEACT_DEFAULT, UNI_IERR_MIS))
54122205Sharti		uni->cx.err[uni->cx.errcnt - 1].man = 1;
55122205Sharti}
56122205Sharti
57122205Sharti/*
58122205Sharti * This special handling is required for ADD PARTY, PARTY ALERTING and
59122205Sharti * ADD PARTY ACKNOWLEDGE by Q.2971 9.5.3.2.1.
60122205Sharti * It means, that the EPREF should be handled as mandatory only if
61122205Sharti * no other IEs have explicit action indicators.
62122205Sharti */
63122205Shartivoid
64122205Shartiuni_mandate_epref(struct uni *uni, struct uni_ie_epref *epref)
65122205Sharti{
66122205Sharti	struct uni_ierr *e;
67122205Sharti	int maxact;
68122205Sharti
69122205Sharti	if (!IE_ISPRESENT(*epref)) {
70122205Sharti		/*
71122205Sharti		 * 9.5.3.2.1 -- missing endpoint reference
72122205Sharti		 */
73122205Sharti
74122205Sharti		/*
75122205Sharti		 * a) if any unrecognized or IE with error has a CLEAR
76122205Sharti		 *    action indicator, this takes precedence.
77122205Sharti		 * b) if any unrecognized or IE with error has a
78122205Sharti		 *    discard message and report action indicator, this takes
79122205Sharti		 *    precedence.
80122205Sharti		 * c) if any unrecognized or IE with error has a
81122205Sharti		 *    discard message action indicator, this takes
82122205Sharti		 *    precedence.
83122205Sharti		 *
84122205Sharti		 * In any of these cases we must remove the EPREF IE
85122205Sharti		 * if it has CLEAR, otherwise the CLEAR would take over.
86122205Sharti		 */
87122205Sharti		maxact = -1;
88122205Sharti		FOREACH_ERR(e, uni) {
89122205Sharti			if (e->ie == UNI_IE_EPREF)
90122205Sharti				continue;
91122205Sharti			if (e->act == UNI_IEACT_CLEAR)
92122205Sharti				maxact = UNI_IEACT_CLEAR;
93122205Sharti			else if (e->act == UNI_IEACT_MSG_REPORT) {
94122205Sharti				if (maxact == -1 && maxact != UNI_IEACT_CLEAR)
95122205Sharti					maxact = UNI_IEACT_MSG_REPORT;
96122205Sharti			} else if (e->act == UNI_IEACT_MSG_IGNORE) {
97122205Sharti				if (maxact == -1)
98122205Sharti					maxact = UNI_IEACT_MSG_IGNORE;
99122205Sharti			}
100122205Sharti		}
101122205Sharti
102122205Sharti		if (maxact != -1) {
103122205Sharti			/* ok, second pass to remove UNI_IE_EPREF */
104122205Sharti			FOREACH_ERR(e, uni)
105122205Sharti				if (e->ie == UNI_IE_EPREF) {
106122205Sharti					memmove(e, e + 1,
107122205Sharti					    (uni->cx.errcnt - (e - uni->cx.err)
108122205Sharti					    - 1) * sizeof(uni->cx.err[0]));
109122205Sharti					uni->cx.errcnt--;
110122205Sharti					break;
111122205Sharti				}
112122205Sharti			return;
113122205Sharti
114122205Sharti		}
115122205Sharti
116122205Sharti		/*
117122205Sharti		 * d) if nothing of the above, the IE is mandatory
118122205Sharti		 */
119122205Sharti		uni_mandate_ie(uni, UNI_IE_EPREF);
120122205Sharti		return;
121122205Sharti
122122205Sharti	}
123122205Sharti	if (IE_ISGOOD(*epref))
124122205Sharti		return;
125122205Sharti
126122205Sharti	/*
127122205Sharti	 * It has an error obviously
128122205Sharti	 * 9.5.3.2.2
129122205Sharti	 *
130122205Sharti	 * It turns out, that Q.2931 handling just does the right thing
131122205Sharti	 * if we don't mandate the IE.
132122205Sharti	 */
133122205Sharti	return;
134122205Sharti}
135122205Sharti
136122205Sharti/*
137122205Sharti * Look, what to do with this message. We assume, that the message itself is
138122205Sharti * recognized.
139122205Sharti *
140122205Sharti * This is rather complicated. We must use the information provided in the
141122205Sharti * fields of the context, because IEs with length errors may not be set
142122205Sharti * altogether.
143122205Sharti */
144122205Shartienum verify
145122205Shartiuni_verify(struct uni *uni, enum uni_msgact msgact)
146122205Sharti{
147122205Sharti	struct uni_ierr *e1;
148122205Sharti
149122205Sharti	if (uni->debug[UNI_FAC_VERIFY] >= 2) {
150122205Sharti		FOREACH_ERR(e1, uni) {
151122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 2, "ie=%02x err=%u man=%d"
152122205Sharti			    " act=%u", e1->ie, e1->err, e1->man, e1->act);
153122205Sharti		}
154122205Sharti	}
155122205Sharti
156122205Sharti	/*
157122205Sharti	 * Look for missing mandatory IEs. The action indicator is ignored
158122205Sharti	 * according to 5.6.7.1. If IEs are missing the action is to
159122205Sharti	 * ignore the message and report status for all messages except
160122205Sharti	 * RELEASE, RELEASE_COMPLETE and SETUP. Because we must differentiate
161122205Sharti	 * this RAI from other RAIs in this case, use another return code.
162122205Sharti	 * Note, that mandatory IEs with errors are not handled here.
163122205Sharti	 */
164122205Sharti	FOREACH_ERR(e1, uni) {
165122205Sharti		if (e1->err == UNI_IERR_MIS) {
166122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
167122205Sharti			    UNI_CAUSE_MANDAT);
168122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAIM");
169122205Sharti			return (VFY_RAIM);
170122205Sharti		}
171122205Sharti	}
172122205Sharti
173122205Sharti	/*
174122205Sharti	 * When any IE with error specifies a CLR action indicator, this
175122205Sharti	 * takes precedence obviously. There are two cases here:
176122205Sharti	 * unrecognized IEs and IEs with error. So we look through the
177122205Sharti	 * error array twice and send only one STATUS. Unrecognized will
178122205Sharti	 * take precedence.
179122205Sharti	 *
180122205Sharti	 * 5.7.2a)
181122205Sharti	 */
182122205Sharti	FOREACH_ERR(e1, uni) {
183122205Sharti		if (e1->act == UNI_IEACT_CLEAR && e1->err == UNI_IERR_UNK) {
184122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
185122205Sharti			    UNI_CAUSE_IE_NIMPL);
186122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR1");
187122205Sharti			return (VFY_CLR);
188122205Sharti		}
189122205Sharti	}
190122205Sharti
191122205Sharti	FOREACH_ERR(e1, uni) {
192122205Sharti		if (e1->act == UNI_IEACT_CLEAR &&
193122205Sharti		   (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
194122205Sharti		    e1->err == UNI_IERR_ACC)) {
195122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
196122205Sharti			    UNI_CAUSE_IE_INV);
197122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR2");
198122205Sharti			return (VFY_CLR);
199122205Sharti		}
200122205Sharti	}
201122205Sharti
202122205Sharti	/*
203122205Sharti	 * Now check, whether anybody wants to explicitly ignore the message
204122205Sharti	 * and report status.
205122205Sharti	 *
206122205Sharti	 * 5.7.2a)
207122205Sharti	 */
208122205Sharti	FOREACH_ERR(e1, uni) {
209122205Sharti		if (e1->act == UNI_IEACT_MSG_REPORT && e1->err == UNI_IERR_UNK) {
210122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
211122205Sharti			    UNI_CAUSE_IE_NIMPL);
212122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
213122205Sharti			return (VFY_RAI);
214122205Sharti		}
215122205Sharti	}
216122205Sharti
217122205Sharti	FOREACH_ERR(e1, uni) {
218122205Sharti		if (e1->act == UNI_IEACT_MSG_REPORT &&
219122205Sharti		   (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
220122205Sharti		    e1->err == UNI_IERR_ACC)) {
221122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
222122205Sharti			    UNI_CAUSE_IE_INV);
223122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
224122205Sharti			return (VFY_RAI);
225122205Sharti		}
226122205Sharti	}
227122205Sharti
228122205Sharti	/*
229122205Sharti	 * Now look whether some IE wants to explicitely ignore the message
230122205Sharti	 * without any report.
231122205Sharti	 */
232122205Sharti	FOREACH_ERR(e1, uni) {
233122205Sharti		if (e1->act == UNI_IEACT_MSG_IGNORE) {
234122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "I1");
235122205Sharti			return (VFY_I);
236122205Sharti		}
237122205Sharti	}
238122205Sharti
239122205Sharti	/*
240122205Sharti	 * At this point we have left only
241122205Sharti	 *  mandatory and non-mandatory IEs with error that want the IE to be
242122205Sharti	 *  ignored or ignored with report or defaulted.
243122205Sharti	 * Because a mandatory IE with errors lead to
244122205Sharti	 * the message beeing ignored, we make this of higher
245122205Sharti	 * precedence, than the rest.
246122205Sharti	 */
247122205Sharti	FOREACH_ERR(e1, uni) {
248122205Sharti		if (e1->man) {
249122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
250122205Sharti			    UNI_CAUSE_MANDAT);
251122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
252122205Sharti			return (VFY_RAI);
253122205Sharti		}
254122205Sharti	}
255122205Sharti
256122205Sharti	/*
257122205Sharti	 * Now look for ignoring the IE and reporting. This takes precedence
258122205Sharti	 * over simply ignoring it. We also collect defaulted (non-mandatory)
259122205Sharti	 * IEs.
260122205Sharti	 *
261122205Sharti	 * 5.7.2d) and 5.6.8.1
262122205Sharti	 */
263122205Sharti	FOREACH_ERR(e1, uni) {
264122205Sharti		if ((e1->act == UNI_IEACT_DEFAULT ||
265122205Sharti		     e1->act == UNI_IEACT_REPORT)
266122205Sharti		    && e1->err != UNI_IERR_UNK) {
267122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
268122205Sharti			    UNI_CAUSE_IE_INV);
269122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAP");
270122205Sharti			return (VFY_RAP);
271122205Sharti		}
272122205Sharti	}
273122205Sharti
274122205Sharti	FOREACH_ERR(e1, uni) {
275122205Sharti		if ((e1->act == UNI_IEACT_DEFAULT ||
276122205Sharti		     e1->act == UNI_IEACT_REPORT)
277122205Sharti		    && e1->err == UNI_IERR_UNK) {
278122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
279122205Sharti			    UNI_CAUSE_IE_NIMPL);
280122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAPU");
281122205Sharti			return (VFY_RAPU);
282122205Sharti		}
283122205Sharti	}
284122205Sharti
285122205Sharti	/*
286122205Sharti	 * This leaves us with IEs, that want to be ignored. Among these may
287122205Sharti	 * be mandatory IEs. If we have an mandatory IEs here in the error
288122205Sharti	 * array, then the message wil not contain enough information and
289122205Sharti	 * must be handled according to 5.8 as either in 5.6.7.1 (this
290122205Sharti	 * means, that mandatory IEs cannot really be ignored) or 5.7.1.
291122205Sharti	 */
292122205Sharti	FOREACH_ERR(e1, uni) {
293122205Sharti		if (e1->man) {
294122205Sharti			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
295122205Sharti			    UNI_CAUSE_MANDAT);
296122205Sharti			if (msgact == UNI_MSGACT_CLEAR) {
297122205Sharti				VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR3");
298122205Sharti				return (VFY_CLR);
299122205Sharti			}
300122205Sharti			if (msgact == UNI_MSGACT_IGNORE) {
301122205Sharti				VERBOSE(uni, UNI_FAC_VERIFY, 1, "I2");
302122205Sharti				return (VFY_I);
303122205Sharti			}
304122205Sharti			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
305122205Sharti			return (VFY_RAI);
306122205Sharti		}
307122205Sharti	}
308122205Sharti
309122205Sharti	/*
310122205Sharti	 * Now only non-mandatory IEs are left, that want to be explicitely
311122205Sharti	 * ignored.
312122205Sharti	 */
313122205Sharti	if (uni->cx.errcnt != 0)
314122205Sharti		MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
315122205Sharti		    UNI_CAUSE_IE_INV);
316122205Sharti
317122205Sharti	VERBOSE(uni, UNI_FAC_VERIFY, 1, "OK");
318122205Sharti	return (VFY_OK);
319122205Sharti}
320122205Sharti
321122205Sharti/*
322122205Sharti * Collect the IE identifiers for some of the known cause codes.
323122205Sharti */
324122205Shartivoid
325122205Shartiuni_vfy_collect_ies(struct uni *uni)
326122205Sharti{
327122205Sharti	struct uni_ierr *e;
328122205Sharti
329122205Sharti#define STUFF_IE(IE)						\
330122205Sharti	uni->cause.u.ie.ie[uni->cause.u.ie.len++] = (IE);	\
331122205Sharti	if (uni->cause.u.ie.len == UNI_CAUSE_IE_N)		\
332122205Sharti		break;
333122205Sharti
334122205Sharti	uni->cause.u.ie.len = 0;
335122205Sharti	if (uni->cause.cause == UNI_CAUSE_MANDAT) {
336122205Sharti		FOREACH_ERR(e, uni) {
337122205Sharti			if (e->err == UNI_IERR_MIS || e->man != 0) {
338122205Sharti				STUFF_IE(e->ie);
339122205Sharti			}
340122205Sharti		}
341122205Sharti
342122205Sharti	} else if (uni->cause.cause == UNI_CAUSE_IE_NIMPL) {
343122205Sharti		FOREACH_ERR(e, uni) {
344122205Sharti			if (e->err == UNI_IERR_UNK) {
345122205Sharti				STUFF_IE(e->ie);
346122205Sharti			}
347122205Sharti		}
348122205Sharti
349122205Sharti	} else if (uni->cause.cause == UNI_CAUSE_IE_INV) {
350122205Sharti		FOREACH_ERR(e, uni) {
351122205Sharti			if (e->err == UNI_IERR_LEN ||
352122205Sharti			    e->err == UNI_IERR_BAD ||
353122205Sharti			    e->err == UNI_IERR_ACC) {
354122205Sharti				STUFF_IE(e->ie);
355122205Sharti			}
356122205Sharti		}
357122205Sharti	} else
358122205Sharti		return;
359122205Sharti
360122205Sharti	if (uni->cause.u.ie.len != 0)
361122205Sharti		uni->cause.h.present |= UNI_CAUSE_IE_P;
362122205Sharti}
363122205Sharti
364122205Sharti
365122205Shartivoid
366122205Shartiuni_respond_status_verify(struct uni *uni, struct uni_cref *cref,
367122205Sharti    enum uni_callstate cs, struct uni_ie_epref *epref,
368122205Sharti    enum uni_epstate ps)
369122205Sharti{
370122205Sharti	struct uni_all *resp;
371122205Sharti
372122205Sharti	if ((resp = UNI_ALLOC()) == NULL)
373122205Sharti		return;
374122205Sharti
375122205Sharti	uni_vfy_collect_ies(uni);
376122205Sharti
377122205Sharti	MK_MSG_RESP(resp, UNI_STATUS, cref);
378122205Sharti	MK_IE_CALLSTATE(resp->u.status.callstate, cs);
379122205Sharti	resp->u.status.cause = uni->cause;
380122205Sharti	if (epref && IE_ISGOOD(*epref)) {
381122205Sharti		MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag);
382122205Sharti		MK_IE_EPSTATE(resp->u.status.epstate, ps);
383122205Sharti	}
384122205Sharti
385122205Sharti	uni_send_output(resp, uni);
386122205Sharti
387122205Sharti	UNI_FREE(resp);
388122205Sharti}
389122205Sharti
390122205Sharti/*
391122205Sharti * Handling of Q.2971 9.5.8.1:
392122205Sharti */
393122205Shartivoid
394122205Shartiuni_vfy_remove_unknown(struct uni *uni)
395122205Sharti{
396122205Sharti	struct uni_ierr *e1, *e0;
397122205Sharti	int flag = 0;
398122205Sharti
399122205Sharti	FOREACH_ERR(e1, uni) {
400122205Sharti		if (e1->err == UNI_IERR_UNK) {
401122205Sharti			if (e1->act == UNI_IEACT_CLEAR ||
402122205Sharti			    e1->act == UNI_IEACT_MSG_IGNORE ||
403122205Sharti			    e1->act == UNI_IEACT_MSG_REPORT)
404122205Sharti				return;
405122205Sharti			if (e1->act == UNI_IEACT_REPORT ||
406122205Sharti			    e1->act == UNI_IEACT_DEFAULT)
407122205Sharti				flag = 1;
408122205Sharti		}
409122205Sharti	}
410122205Sharti	if (flag)
411122205Sharti		return;
412122205Sharti	e0 = e1 = uni->cx.err;
413122205Sharti	while (e1 < uni->cx.err + uni->cx.errcnt) {
414122205Sharti		if (e1->err != UNI_IERR_UNK) {
415122205Sharti			if (e0 != e1)
416122205Sharti				*e0 = *e1;
417122205Sharti			e0++;
418122205Sharti		}
419122205Sharti		e1++;
420122205Sharti	}
421122205Sharti	uni->cx.errcnt = e0 - uni->cx.err;
422122205Sharti}
423122205Sharti
424122205Sharti/*
425122205Sharti * Handling for ADD_PARTY_REJ and DROP_PARTY_ACK with bad cause
426122205Sharti */
427122205Shartivoid
428122205Shartiuni_vfy_remove_cause(struct uni *uni)
429122205Sharti{
430122205Sharti	struct uni_ierr *e1, *e0;
431122205Sharti
432122205Sharti	e0 = e1 = uni->cx.err;
433122205Sharti	while (e1 < uni->cx.err + uni->cx.errcnt) {
434122205Sharti		if (e1->ie != UNI_IE_CAUSE) {
435122205Sharti			if (e0 != e1)
436122205Sharti				*e0 = *e1;
437122205Sharti			e0++;
438122205Sharti		}
439122205Sharti		e1++;
440122205Sharti	}
441122205Sharti	uni->cx.errcnt = e0 - uni->cx.err;
442122205Sharti}
443