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 43void 44uni_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 */ 63void 64uni_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 */ 144enum verify 145uni_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 */ 324void 325uni_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 365void 366uni_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 */ 393void 394uni_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 */ 427void 428uni_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