]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/sig/sig_verify.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / sig / sig_verify.c
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 }