1/* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * Copyright (c) 2004 6 * Hartmut Brandt 7 * 8 * Author: Hartmut Brandt <harti@freebsd.org> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Begemot: libunimsg/netnatm/api/unisap.c,v 1.4 2004/07/08 08:22:01 brandt Exp $ 32 */ 33 34#include <sys/types.h> 35#ifdef _KERNEL 36#include <sys/ctype.h> 37#include <sys/libkern.h> 38#else 39#include <ctype.h> 40#include <string.h> 41#endif 42#include <netnatm/msg/unistruct.h> 43#include <netnatm/api/unisap.h> 44 45int 46unisve_check_addr(const struct unisve_addr *sve) 47{ 48 if (sve->tag == UNISVE_ABSENT) 49 return (UNISVE_OK); 50 if (sve->tag == UNISVE_ANY) 51 return (UNISVE_OK); 52 if (sve->tag != UNISVE_PRESENT) 53 return (UNISVE_ERROR_BAD_TAG); 54 55 if (sve->type == UNI_ADDR_INTERNATIONAL) { 56 if (sve->plan != UNI_ADDR_E164) 57 return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); 58 if (sve->len == 0 || sve->len > 15) 59 return (UNISVE_ERROR_ADDR_LEN); 60 61 } else if (sve->type == UNI_ADDR_UNKNOWN) { 62 if (sve->plan != UNI_ADDR_ATME) 63 return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); 64 if (sve->len != 19) 65 return (UNISVE_ERROR_ADDR_LEN); 66 } else 67 return (UNISVE_ERROR_BAD_ADDR_TYPE); 68 69 return (UNISVE_OK); 70} 71 72int 73unisve_check_selector(const struct unisve_selector *sve) 74{ 75 if (sve->tag != UNISVE_PRESENT && 76 sve->tag != UNISVE_ABSENT && 77 sve->tag != UNISVE_ANY) 78 return (UNISVE_ERROR_BAD_TAG); 79 return (UNISVE_OK); 80} 81 82/* 83 * We don't want to check the protocol values here. 84 */ 85int 86unisve_check_blli_id2(const struct unisve_blli_id2 *sve) 87{ 88 if (sve->tag != UNISVE_PRESENT && 89 sve->tag != UNISVE_ABSENT && 90 sve->tag != UNISVE_ANY) 91 return (UNISVE_ERROR_BAD_TAG); 92 return (UNISVE_OK); 93} 94 95/* 96 * We don't want to check the protocol values here. 97 */ 98int 99unisve_check_blli_id3(const struct unisve_blli_id3 *sve) 100{ 101 if (sve->tag != UNISVE_PRESENT && 102 sve->tag != UNISVE_ABSENT && 103 sve->tag != UNISVE_ANY) 104 return (UNISVE_ERROR_BAD_TAG); 105 return (UNISVE_OK); 106} 107 108int 109unisve_check_bhli(const struct unisve_bhli *sve) 110{ 111 if (sve->tag == UNISVE_ABSENT) 112 return (UNISVE_OK); 113 if (sve->tag == UNISVE_ANY) 114 return (UNISVE_OK); 115 116 if (sve->tag != UNISVE_PRESENT) 117 return (UNISVE_ERROR_BAD_TAG); 118 119 if (sve->type != UNI_BHLI_ISO && 120 sve->type != UNI_BHLI_USER && 121 sve->type != UNI_BHLI_VENDOR) 122 return (UNISVE_ERROR_BAD_BHLI_TYPE); 123 124 if (sve->len > sizeof(sve->info)) 125 return (UNISVE_ERROR_BAD_BHLI_LEN); 126 127 return (UNISVE_OK); 128} 129 130int 131unisve_check_sap(const struct uni_sap *sap) 132{ 133 int err; 134 135 if ((err = unisve_check_addr(&sap->addr)) != 0 || 136 (err = unisve_check_selector(&sap->selector)) != 0 || 137 (err = unisve_check_blli_id2(&sap->blli_id2)) != 0 || 138 (err = unisve_check_blli_id3(&sap->blli_id3)) != 0 || 139 (err = unisve_check_bhli(&sap->bhli)) != 0) 140 return (err); 141 142 if (sap->addr.plan == UNI_ADDR_E164) { 143 if (sap->selector.tag == UNISVE_PRESENT) 144 return (UNISVE_ERROR_ADDR_SEL_CONFLICT); 145 } else if (sap->addr.plan == UNI_ADDR_ATME) { 146 if (sap->selector.tag == UNISVE_ABSENT) 147 return (UNISVE_ERROR_ADDR_SEL_CONFLICT); 148 } 149 return (0); 150} 151 152#define COMMON_OVERLAP(A1,A2) \ 153 if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_ABSENT) || \ 154 A1->tag == UNISVE_ANY || A2->tag == UNISVE_ANY) \ 155 return (1); \ 156 if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_PRESENT) || \ 157 (A2->tag == UNISVE_ABSENT && A1->tag == UNISVE_PRESENT)) \ 158 return (0); 159 160int 161unisve_overlap_addr(const struct unisve_addr *s1, const struct unisve_addr *s2) 162{ 163 COMMON_OVERLAP(s1, s2); 164 165 return (s1->type == s2->type && s1->plan == s2->plan && 166 s1->len == s2->len && memcmp(s1->addr, s2->addr, s1->len) == 0); 167} 168 169int 170unisve_overlap_selector(const struct unisve_selector *s1, 171 const struct unisve_selector *s2) 172{ 173 COMMON_OVERLAP(s1, s2); 174 175 return (s1->selector == s2->selector); 176} 177 178int 179unisve_overlap_blli_id2(const struct unisve_blli_id2 *s1, 180 const struct unisve_blli_id2 *s2) 181{ 182 COMMON_OVERLAP(s1, s2); 183 184 return (s1->proto == s2->proto && 185 (s1->proto != UNI_BLLI_L2_USER || s1->user == s2->user)); 186} 187 188int 189unisve_overlap_blli_id3(const struct unisve_blli_id3 *s1, 190 const struct unisve_blli_id3 *s2) 191{ 192 COMMON_OVERLAP(s1, s2); 193 194 if (s1->proto != s2->proto) 195 return (0); 196 if (s1->proto == UNI_BLLI_L3_USER) 197 return (s1->user == s2->user); 198 if (s1->proto == UNI_BLLI_L3_TR9577) { 199 if (s1->noipi && s2->noipi) 200 return (1); 201 if (!s1->noipi && !s2->noipi) { 202 if (s1->ipi == s2->ipi) { 203 if (s1->ipi != UNI_BLLI_L3_SNAP) 204 return (1); 205 if (s1->oui == s2->oui && s1->pid == s2->pid) 206 return (1); 207 } 208 } 209 return (0); 210 } 211 return (1); 212} 213 214int 215unisve_overlap_bhli(const struct unisve_bhli *s1, const struct unisve_bhli *s2) 216{ 217 COMMON_OVERLAP(s1, s2); 218 219 return (s1->type == s2->type && s1->len == s2->len && 220 memcmp(s1->info, s2->info, s1->len) == 0); 221} 222 223int 224unisve_overlap_sap(const struct uni_sap *s1, const struct uni_sap *s2) 225{ 226 int any1, any2; 227 228 /* 229 * Two catch-all's SAP's are not allowed. A catch-all does never 230 * overlap with a non-catch all SAP. 231 */ 232 any1 = unisve_is_catchall(s1); 233 any2 = unisve_is_catchall(s2); 234 235 if (any1 && any2) 236 return (1); 237 if(any1 || any2) 238 return (0); 239 240 return (unisve_overlap_addr(&s1->addr, &s2->addr) && 241 unisve_overlap_selector(&s1->selector, &s2->selector) && 242 unisve_overlap_blli_id2(&s1->blli_id2, &s2->blli_id2) && 243 unisve_overlap_blli_id3(&s1->blli_id3, &s2->blli_id3) && 244 unisve_overlap_bhli(&s1->bhli, &s2->bhli)); 245} 246 247int 248unisve_is_catchall(const struct uni_sap *sap) 249{ 250 return (sap->addr.tag == UNISVE_ANY && 251 sap->selector.tag == UNISVE_ANY && 252 sap->blli_id2.tag == UNISVE_ANY && 253 sap->blli_id3.tag == UNISVE_ANY && 254 sap->bhli.tag == UNISVE_ANY); 255} 256 257int 258unisve_match(const struct uni_sap *sap, const struct uni_ie_called *called, 259 const struct uni_ie_blli *blli, const struct uni_ie_bhli *bhli) 260{ 261 switch (sap->addr.tag) { 262 case UNISVE_ABSENT: 263 if (IE_ISGOOD(*called)) 264 return (0); 265 break; 266 267 case UNISVE_ANY: 268 break; 269 270 case UNISVE_PRESENT: 271 if (!IE_ISGOOD(*called)) 272 return (0); 273 if (called->addr.type != sap->addr.type || 274 called->addr.plan != sap->addr.plan) 275 return (0); 276 if (called->addr.plan == UNI_ADDR_E164) { 277 if (called->addr.len != sap->addr.len || 278 memcmp(called->addr.addr, sap->addr.addr, 279 called->addr.len) != 0) 280 return (0); 281 } else if (called->addr.plan == UNI_ADDR_ATME) { 282 if (called->addr.len != 20 || 283 memcmp(called->addr.addr, sap->addr.addr, 19) != 0) 284 return (0); 285 } 286 break; 287 288 default: 289 return (0); 290 } 291 292 switch (sap->selector.tag) { 293 294 case UNISVE_ABSENT: 295 if (IE_ISGOOD(*called) && called->addr.plan == UNI_ADDR_ATME) 296 return (0); 297 break; 298 299 case UNISVE_ANY: 300 break; 301 302 case UNISVE_PRESENT: 303 if (!IE_ISGOOD(*called)) 304 return (0); 305 if (called->addr.plan != UNI_ADDR_ATME) 306 return (0); 307 if (called->addr.addr[19] != sap->selector.selector) 308 return (0); 309 break; 310 311 default: 312 return (0); 313 } 314 315 switch (sap->blli_id2.tag) { 316 317 case UNISVE_ABSENT: 318 if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L2_P)) 319 return (0); 320 break; 321 322 case UNISVE_ANY: 323 break; 324 325 case UNISVE_PRESENT: 326 if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L2_P) == 0) 327 return (0); 328 if (blli->l2 != sap->blli_id2.proto) 329 return (0); 330 if (blli->l2 == UNI_BLLI_L2_USER) { 331 if ((blli->h.present & UNI_BLLI_L2_USER_P) == 0) 332 return (0); 333 if (blli->l2_user != sap->blli_id2.user) 334 return (0); 335 } 336 break; 337 338 default: 339 return (0); 340 } 341 342 switch (sap->blli_id3.tag) { 343 344 case UNISVE_ABSENT: 345 if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L3_P)) 346 return (0); 347 break; 348 349 case UNISVE_ANY: 350 break; 351 352 case UNISVE_PRESENT: 353 if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L3_P) == 0) 354 return (0); 355 if (blli->l3 != sap->blli_id3.proto) 356 return (0); 357 if (blli->l3 == UNI_BLLI_L3_USER) { 358 if ((blli->h.present & UNI_BLLI_L3_USER_P) == 0) 359 return (0); 360 if (blli->l3_user != sap->blli_id3.user) 361 return (0); 362 break; 363 } 364 if (blli->l3 == UNI_BLLI_L3_TR9577) { 365 if (sap->blli_id3.noipi) { 366 if (blli->h.present & UNI_BLLI_L3_IPI_P) 367 return (0); 368 } else { 369 if (!(blli->h.present & UNI_BLLI_L3_IPI_P)) 370 return (0); 371 if (blli->l3_ipi != sap->blli_id3.ipi) 372 return (0); 373 if (blli->l3_ipi == UNI_BLLI_L3_SNAP) { 374 if (!(blli->h.present & 375 UNI_BLLI_L3_SNAP_P)) 376 return (0); 377 if (blli->oui != sap->blli_id3.oui || 378 blli->pid != sap->blli_id3.pid) 379 return (0); 380 } 381 } 382 } 383 break; 384 385 default: 386 return (0); 387 } 388 389 switch (sap->bhli.tag) { 390 391 case UNISVE_ABSENT: 392 if (IE_ISGOOD(*bhli)) 393 return (0); 394 break; 395 396 case UNISVE_ANY: 397 break; 398 399 case UNISVE_PRESENT: 400 if (!IE_ISGOOD(*bhli)) 401 return (0); 402 if (sap->bhli.type != bhli->type) 403 return (0); 404 if (sap->bhli.len != bhli->len) 405 return (0); 406 if (memcmp(sap->bhli.info, bhli->info, bhli->len) != 0) 407 return (0); 408 break; 409 410 default: 411 return (0); 412 } 413 /* Uff */ 414 return (1); 415} 416