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 <harti@freebsd.org>
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
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
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
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
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
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
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
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 }
Cache object: 388ba2a9404f8863eca96b715055eeb5
|