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