1 /*
2  * Copyright (c) 2001-2003
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  * 	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <[email protected]>
28  *
29  * $Begemot: libunimsg/netnatm/sig/sig_verify.c,v 1.19 2004/07/08 08:22:23 brandt Exp $
30  *
31  * Message verification with explicit action indicators.
32  */
33 
34 #include <netnatm/unimsg.h>
35 #include <netnatm/saal/sscfudef.h>
36 #include <netnatm/msg/unistruct.h>
37 #include <netnatm/msg/unimsglib.h>
38 #include <netnatm/sig/uni.h>
39 
40 #include <netnatm/sig/unipriv.h>
41 #include <netnatm/sig/unimkmsg.h>
42 
43 void
uni_mandate_ie(struct uni * uni,enum uni_ietype ie)44 uni_mandate_ie(struct uni *uni, enum uni_ietype ie)
45 {
46 	struct uni_ierr *e;
47 
48 	FOREACH_ERR(e, uni)
49 		if (e->ie == ie) {
50 			e->man = 1;
51 			return;
52 		}
53 	if (UNI_SAVE_IERR(&uni->cx, ie, UNI_IEACT_DEFAULT, UNI_IERR_MIS))
54 		uni->cx.err[uni->cx.errcnt - 1].man = 1;
55 }
56 
57 /*
58  * This special handling is required for ADD PARTY, PARTY ALERTING and
59  * ADD PARTY ACKNOWLEDGE by Q.2971 9.5.3.2.1.
60  * It means, that the EPREF should be handled as mandatory only if
61  * no other IEs have explicit action indicators.
62  */
63 void
uni_mandate_epref(struct uni * uni,struct uni_ie_epref * epref)64 uni_mandate_epref(struct uni *uni, struct uni_ie_epref *epref)
65 {
66 	struct uni_ierr *e;
67 	int maxact;
68 
69 	if (!IE_ISPRESENT(*epref)) {
70 		/*
71 		 * 9.5.3.2.1 -- missing endpoint reference
72 		 */
73 
74 		/*
75 		 * a) if any unrecognized or IE with error has a CLEAR
76 		 *    action indicator, this takes precedence.
77 		 * b) if any unrecognized or IE with error has a
78 		 *    discard message and report action indicator, this takes
79 		 *    precedence.
80 		 * c) if any unrecognized or IE with error has a
81 		 *    discard message action indicator, this takes
82 		 *    precedence.
83 		 *
84 		 * In any of these cases we must remove the EPREF IE
85 		 * if it has CLEAR, otherwise the CLEAR would take over.
86 		 */
87 		maxact = -1;
88 		FOREACH_ERR(e, uni) {
89 			if (e->ie == UNI_IE_EPREF)
90 				continue;
91 			if (e->act == UNI_IEACT_CLEAR)
92 				maxact = UNI_IEACT_CLEAR;
93 			else if (e->act == UNI_IEACT_MSG_REPORT) {
94 				if (maxact == -1 && maxact != UNI_IEACT_CLEAR)
95 					maxact = UNI_IEACT_MSG_REPORT;
96 			} else if (e->act == UNI_IEACT_MSG_IGNORE) {
97 				if (maxact == -1)
98 					maxact = UNI_IEACT_MSG_IGNORE;
99 			}
100 		}
101 
102 		if (maxact != -1) {
103 			/* ok, second pass to remove UNI_IE_EPREF */
104 			FOREACH_ERR(e, uni)
105 				if (e->ie == UNI_IE_EPREF) {
106 					memmove(e, e + 1,
107 					    (uni->cx.errcnt - (e - uni->cx.err)
108 					    - 1) * sizeof(uni->cx.err[0]));
109 					uni->cx.errcnt--;
110 					break;
111 				}
112 			return;
113 
114 		}
115 
116 		/*
117 		 * d) if nothing of the above, the IE is mandatory
118 		 */
119 		uni_mandate_ie(uni, UNI_IE_EPREF);
120 		return;
121 
122 	}
123 	if (IE_ISGOOD(*epref))
124 		return;
125 
126 	/*
127 	 * It has an error obviously
128 	 * 9.5.3.2.2
129 	 *
130 	 * It turns out, that Q.2931 handling just does the right thing
131 	 * if we don't mandate the IE.
132 	 */
133 	return;
134 }
135 
136 /*
137  * Look, what to do with this message. We assume, that the message itself is
138  * recognized.
139  *
140  * This is rather complicated. We must use the information provided in the
141  * fields of the context, because IEs with length errors may not be set
142  * altogether.
143  */
144 enum verify
uni_verify(struct uni * uni,enum uni_msgact msgact)145 uni_verify(struct uni *uni, enum uni_msgact msgact)
146 {
147 	struct uni_ierr *e1;
148 
149 	if (uni->debug[UNI_FAC_VERIFY] >= 2) {
150 		FOREACH_ERR(e1, uni) {
151 			VERBOSE(uni, UNI_FAC_VERIFY, 2, "ie=%02x err=%u man=%d"
152 			    " act=%u", e1->ie, e1->err, e1->man, e1->act);
153 		}
154 	}
155 
156 	/*
157 	 * Look for missing mandatory IEs. The action indicator is ignored
158 	 * according to 5.6.7.1. If IEs are missing the action is to
159 	 * ignore the message and report status for all messages except
160 	 * RELEASE, RELEASE_COMPLETE and SETUP. Because we must differentiate
161 	 * this RAI from other RAIs in this case, use another return code.
162 	 * Note, that mandatory IEs with errors are not handled here.
163 	 */
164 	FOREACH_ERR(e1, uni) {
165 		if (e1->err == UNI_IERR_MIS) {
166 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
167 			    UNI_CAUSE_MANDAT);
168 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAIM");
169 			return (VFY_RAIM);
170 		}
171 	}
172 
173 	/*
174 	 * When any IE with error specifies a CLR action indicator, this
175 	 * takes precedence obviously. There are two cases here:
176 	 * unrecognized IEs and IEs with error. So we look through the
177 	 * error array twice and send only one STATUS. Unrecognized will
178 	 * take precedence.
179 	 *
180 	 * 5.7.2a)
181 	 */
182 	FOREACH_ERR(e1, uni) {
183 		if (e1->act == UNI_IEACT_CLEAR && e1->err == UNI_IERR_UNK) {
184 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
185 			    UNI_CAUSE_IE_NIMPL);
186 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR1");
187 			return (VFY_CLR);
188 		}
189 	}
190 
191 	FOREACH_ERR(e1, uni) {
192 		if (e1->act == UNI_IEACT_CLEAR &&
193 		   (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
194 		    e1->err == UNI_IERR_ACC)) {
195 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
196 			    UNI_CAUSE_IE_INV);
197 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR2");
198 			return (VFY_CLR);
199 		}
200 	}
201 
202 	/*
203 	 * Now check, whether anybody wants to explicitly ignore the message
204 	 * and report status.
205 	 *
206 	 * 5.7.2a)
207 	 */
208 	FOREACH_ERR(e1, uni) {
209 		if (e1->act == UNI_IEACT_MSG_REPORT && e1->err == UNI_IERR_UNK) {
210 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
211 			    UNI_CAUSE_IE_NIMPL);
212 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
213 			return (VFY_RAI);
214 		}
215 	}
216 
217 	FOREACH_ERR(e1, uni) {
218 		if (e1->act == UNI_IEACT_MSG_REPORT &&
219 		   (e1->err == UNI_IERR_LEN || e1->err == UNI_IERR_BAD ||
220 		    e1->err == UNI_IERR_ACC)) {
221 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
222 			    UNI_CAUSE_IE_INV);
223 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
224 			return (VFY_RAI);
225 		}
226 	}
227 
228 	/*
229 	 * Now look whether some IE wants to explicitely ignore the message
230 	 * without any report.
231 	 */
232 	FOREACH_ERR(e1, uni) {
233 		if (e1->act == UNI_IEACT_MSG_IGNORE) {
234 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "I1");
235 			return (VFY_I);
236 		}
237 	}
238 
239 	/*
240 	 * At this point we have left only
241 	 *  mandatory and non-mandatory IEs with error that want the IE to be
242 	 *  ignored or ignored with report or defaulted.
243 	 * Because a mandatory IE with errors lead to
244 	 * the message beeing ignored, we make this of higher
245 	 * precedence, than the rest.
246 	 */
247 	FOREACH_ERR(e1, uni) {
248 		if (e1->man) {
249 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
250 			    UNI_CAUSE_MANDAT);
251 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
252 			return (VFY_RAI);
253 		}
254 	}
255 
256 	/*
257 	 * Now look for ignoring the IE and reporting. This takes precedence
258 	 * over simply ignoring it. We also collect defaulted (non-mandatory)
259 	 * IEs.
260 	 *
261 	 * 5.7.2d) and 5.6.8.1
262 	 */
263 	FOREACH_ERR(e1, uni) {
264 		if ((e1->act == UNI_IEACT_DEFAULT ||
265 		     e1->act == UNI_IEACT_REPORT)
266 		    && e1->err != UNI_IERR_UNK) {
267 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
268 			    UNI_CAUSE_IE_INV);
269 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAP");
270 			return (VFY_RAP);
271 		}
272 	}
273 
274 	FOREACH_ERR(e1, uni) {
275 		if ((e1->act == UNI_IEACT_DEFAULT ||
276 		     e1->act == UNI_IEACT_REPORT)
277 		    && e1->err == UNI_IERR_UNK) {
278 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
279 			    UNI_CAUSE_IE_NIMPL);
280 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAPU");
281 			return (VFY_RAPU);
282 		}
283 	}
284 
285 	/*
286 	 * This leaves us with IEs, that want to be ignored. Among these may
287 	 * be mandatory IEs. If we have an mandatory IEs here in the error
288 	 * array, then the message wil not contain enough information and
289 	 * must be handled according to 5.8 as either in 5.6.7.1 (this
290 	 * means, that mandatory IEs cannot really be ignored) or 5.7.1.
291 	 */
292 	FOREACH_ERR(e1, uni) {
293 		if (e1->man) {
294 			MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
295 			    UNI_CAUSE_MANDAT);
296 			if (msgact == UNI_MSGACT_CLEAR) {
297 				VERBOSE(uni, UNI_FAC_VERIFY, 1, "CLR3");
298 				return (VFY_CLR);
299 			}
300 			if (msgact == UNI_MSGACT_IGNORE) {
301 				VERBOSE(uni, UNI_FAC_VERIFY, 1, "I2");
302 				return (VFY_I);
303 			}
304 			VERBOSE(uni, UNI_FAC_VERIFY, 1, "RAI");
305 			return (VFY_RAI);
306 		}
307 	}
308 
309 	/*
310 	 * Now only non-mandatory IEs are left, that want to be explicitely
311 	 * ignored.
312 	 */
313 	if (uni->cx.errcnt != 0)
314 		MK_IE_CAUSE(uni->cause, UNI_CAUSE_LOC_USER,
315 		    UNI_CAUSE_IE_INV);
316 
317 	VERBOSE(uni, UNI_FAC_VERIFY, 1, "OK");
318 	return (VFY_OK);
319 }
320 
321 /*
322  * Collect the IE identifiers for some of the known cause codes.
323  */
324 void
uni_vfy_collect_ies(struct uni * uni)325 uni_vfy_collect_ies(struct uni *uni)
326 {
327 	struct uni_ierr *e;
328 
329 #define STUFF_IE(IE)						\
330 	uni->cause.u.ie.ie[uni->cause.u.ie.len++] = (IE);	\
331 	if (uni->cause.u.ie.len == UNI_CAUSE_IE_N)		\
332 		break;
333 
334 	uni->cause.u.ie.len = 0;
335 	if (uni->cause.cause == UNI_CAUSE_MANDAT) {
336 		FOREACH_ERR(e, uni) {
337 			if (e->err == UNI_IERR_MIS || e->man != 0) {
338 				STUFF_IE(e->ie);
339 			}
340 		}
341 
342 	} else if (uni->cause.cause == UNI_CAUSE_IE_NIMPL) {
343 		FOREACH_ERR(e, uni) {
344 			if (e->err == UNI_IERR_UNK) {
345 				STUFF_IE(e->ie);
346 			}
347 		}
348 
349 	} else if (uni->cause.cause == UNI_CAUSE_IE_INV) {
350 		FOREACH_ERR(e, uni) {
351 			if (e->err == UNI_IERR_LEN ||
352 			    e->err == UNI_IERR_BAD ||
353 			    e->err == UNI_IERR_ACC) {
354 				STUFF_IE(e->ie);
355 			}
356 		}
357 	} else
358 		return;
359 
360 	if (uni->cause.u.ie.len != 0)
361 		uni->cause.h.present |= UNI_CAUSE_IE_P;
362 }
363 
364 
365 void
uni_respond_status_verify(struct uni * uni,struct uni_cref * cref,enum uni_callstate cs,struct uni_ie_epref * epref,enum uni_epstate ps)366 uni_respond_status_verify(struct uni *uni, struct uni_cref *cref,
367     enum uni_callstate cs, struct uni_ie_epref *epref,
368     enum uni_epstate ps)
369 {
370 	struct uni_all *resp;
371 
372 	if ((resp = UNI_ALLOC()) == NULL)
373 		return;
374 
375 	uni_vfy_collect_ies(uni);
376 
377 	MK_MSG_RESP(resp, UNI_STATUS, cref);
378 	MK_IE_CALLSTATE(resp->u.status.callstate, cs);
379 	resp->u.status.cause = uni->cause;
380 	if (epref && IE_ISGOOD(*epref)) {
381 		MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag);
382 		MK_IE_EPSTATE(resp->u.status.epstate, ps);
383 	}
384 
385 	uni_send_output(resp, uni);
386 
387 	UNI_FREE(resp);
388 }
389 
390 /*
391  * Handling of Q.2971 9.5.8.1:
392  */
393 void
uni_vfy_remove_unknown(struct uni * uni)394 uni_vfy_remove_unknown(struct uni *uni)
395 {
396 	struct uni_ierr *e1, *e0;
397 	int flag = 0;
398 
399 	FOREACH_ERR(e1, uni) {
400 		if (e1->err == UNI_IERR_UNK) {
401 			if (e1->act == UNI_IEACT_CLEAR ||
402 			    e1->act == UNI_IEACT_MSG_IGNORE ||
403 			    e1->act == UNI_IEACT_MSG_REPORT)
404 				return;
405 			if (e1->act == UNI_IEACT_REPORT ||
406 			    e1->act == UNI_IEACT_DEFAULT)
407 				flag = 1;
408 		}
409 	}
410 	if (flag)
411 		return;
412 	e0 = e1 = uni->cx.err;
413 	while (e1 < uni->cx.err + uni->cx.errcnt) {
414 		if (e1->err != UNI_IERR_UNK) {
415 			if (e0 != e1)
416 				*e0 = *e1;
417 			e0++;
418 		}
419 		e1++;
420 	}
421 	uni->cx.errcnt = e0 - uni->cx.err;
422 }
423 
424 /*
425  * Handling for ADD_PARTY_REJ and DROP_PARTY_ACK with bad cause
426  */
427 void
uni_vfy_remove_cause(struct uni * uni)428 uni_vfy_remove_cause(struct uni *uni)
429 {
430 	struct uni_ierr *e1, *e0;
431 
432 	e0 = e1 = uni->cx.err;
433 	while (e1 < uni->cx.err + uni->cx.errcnt) {
434 		if (e1->ie != UNI_IE_CAUSE) {
435 			if (e0 != e1)
436 				*e0 = *e1;
437 			e0++;
438 		}
439 		e1++;
440 	}
441 	uni->cx.errcnt = e0 - uni->cx.err;
442 }
443