unisap.c revision 131826
1131826Sharti/* 2131826Sharti * Copyright (c) 2001-2003 3131826Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4131826Sharti * All rights reserved. 5131826Sharti * Copyright (c) 2004 6131826Sharti * Hartmut Brandt 7131826Sharti * 8131826Sharti * Author: Hartmut Brandt <harti@freebsd.org> 9131826Sharti * 10131826Sharti * Redistribution and use in source and binary forms, with or without 11131826Sharti * modification, are permitted provided that the following conditions 12131826Sharti * are met: 13131826Sharti * 1. Redistributions of source code must retain the above copyright 14131826Sharti * notice, this list of conditions and the following disclaimer. 15131826Sharti * 2. Redistributions in binary form must reproduce the above copyright 16131826Sharti * notice, this list of conditions and the following disclaimer in the 17131826Sharti * documentation and/or other materials provided with the distribution. 18131826Sharti * 19131826Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20131826Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21131826Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22131826Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23131826Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24131826Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25131826Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26131826Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27131826Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28131826Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29131826Sharti * SUCH DAMAGE. 30131826Sharti * 31131826Sharti * $Begemot: libunimsg/netnatm/api/unisap.c,v 1.4 2004/07/08 08:22:01 brandt Exp $ 32131826Sharti */ 33131826Sharti 34131826Sharti#include <sys/types.h> 35131826Sharti#ifdef _KERNEL 36131826Sharti#include <sys/ctype.h> 37131826Sharti#include <sys/libkern.h> 38131826Sharti#else 39131826Sharti#include <ctype.h> 40131826Sharti#include <string.h> 41131826Sharti#endif 42131826Sharti#include <netnatm/msg/unistruct.h> 43131826Sharti#include <netnatm/api/unisap.h> 44131826Sharti 45131826Shartiint 46131826Shartiunisve_check_addr(const struct unisve_addr *sve) 47131826Sharti{ 48131826Sharti if (sve->tag == UNISVE_ABSENT) 49131826Sharti return (UNISVE_OK); 50131826Sharti if (sve->tag == UNISVE_ANY) 51131826Sharti return (UNISVE_OK); 52131826Sharti if (sve->tag != UNISVE_PRESENT) 53131826Sharti return (UNISVE_ERROR_BAD_TAG); 54131826Sharti 55131826Sharti if (sve->type == UNI_ADDR_INTERNATIONAL) { 56131826Sharti if (sve->plan != UNI_ADDR_E164) 57131826Sharti return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); 58131826Sharti if (sve->len == 0 || sve->len > 15) 59131826Sharti return (UNISVE_ERROR_ADDR_LEN); 60131826Sharti 61131826Sharti } else if (sve->type == UNI_ADDR_UNKNOWN) { 62131826Sharti if (sve->plan != UNI_ADDR_ATME) 63131826Sharti return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); 64131826Sharti if (sve->len != 19) 65131826Sharti return (UNISVE_ERROR_ADDR_LEN); 66131826Sharti } else 67131826Sharti return (UNISVE_ERROR_BAD_ADDR_TYPE); 68131826Sharti 69131826Sharti return (UNISVE_OK); 70131826Sharti} 71131826Sharti 72131826Shartiint 73131826Shartiunisve_check_selector(const struct unisve_selector *sve) 74131826Sharti{ 75131826Sharti if (sve->tag != UNISVE_PRESENT && 76131826Sharti sve->tag != UNISVE_ABSENT && 77131826Sharti sve->tag != UNISVE_ANY) 78131826Sharti return (UNISVE_ERROR_BAD_TAG); 79131826Sharti return (UNISVE_OK); 80131826Sharti} 81131826Sharti 82131826Sharti/* 83131826Sharti * We don't want to check the protocol values here. 84131826Sharti */ 85131826Shartiint 86131826Shartiunisve_check_blli_id2(const struct unisve_blli_id2 *sve) 87131826Sharti{ 88131826Sharti if (sve->tag != UNISVE_PRESENT && 89131826Sharti sve->tag != UNISVE_ABSENT && 90131826Sharti sve->tag != UNISVE_ANY) 91131826Sharti return (UNISVE_ERROR_BAD_TAG); 92131826Sharti return (UNISVE_OK); 93131826Sharti} 94131826Sharti 95131826Sharti/* 96131826Sharti * We don't want to check the protocol values here. 97131826Sharti */ 98131826Shartiint 99131826Shartiunisve_check_blli_id3(const struct unisve_blli_id3 *sve) 100131826Sharti{ 101131826Sharti if (sve->tag != UNISVE_PRESENT && 102131826Sharti sve->tag != UNISVE_ABSENT && 103131826Sharti sve->tag != UNISVE_ANY) 104131826Sharti return (UNISVE_ERROR_BAD_TAG); 105131826Sharti return (UNISVE_OK); 106131826Sharti} 107131826Sharti 108131826Shartiint 109131826Shartiunisve_check_bhli(const struct unisve_bhli *sve) 110131826Sharti{ 111131826Sharti if (sve->tag == UNISVE_ABSENT) 112131826Sharti return (UNISVE_OK); 113131826Sharti if (sve->tag == UNISVE_ANY) 114131826Sharti return (UNISVE_OK); 115131826Sharti 116131826Sharti if (sve->tag != UNISVE_PRESENT) 117131826Sharti return (UNISVE_ERROR_BAD_TAG); 118131826Sharti 119131826Sharti if (sve->type != UNI_BHLI_ISO && 120131826Sharti sve->type != UNI_BHLI_USER && 121131826Sharti sve->type != UNI_BHLI_VENDOR) 122131826Sharti return (UNISVE_ERROR_BAD_BHLI_TYPE); 123131826Sharti 124131826Sharti if (sve->len > sizeof(sve->info)) 125131826Sharti return (UNISVE_ERROR_BAD_BHLI_LEN); 126131826Sharti 127131826Sharti return (UNISVE_OK); 128131826Sharti} 129131826Sharti 130131826Shartiint 131131826Shartiunisve_check_sap(const struct uni_sap *sap) 132131826Sharti{ 133131826Sharti int err; 134131826Sharti 135131826Sharti if ((err = unisve_check_addr(&sap->addr)) != 0 || 136131826Sharti (err = unisve_check_selector(&sap->selector)) != 0 || 137131826Sharti (err = unisve_check_blli_id2(&sap->blli_id2)) != 0 || 138131826Sharti (err = unisve_check_blli_id3(&sap->blli_id3)) != 0 || 139131826Sharti (err = unisve_check_bhli(&sap->bhli)) != 0) 140131826Sharti return (err); 141131826Sharti 142131826Sharti if (sap->addr.plan == UNI_ADDR_E164) { 143131826Sharti if (sap->selector.tag == UNISVE_PRESENT) 144131826Sharti return (UNISVE_ERROR_ADDR_SEL_CONFLICT); 145131826Sharti } else if (sap->addr.plan == UNI_ADDR_ATME) { 146131826Sharti if (sap->selector.tag == UNISVE_ABSENT) 147131826Sharti return (UNISVE_ERROR_ADDR_SEL_CONFLICT); 148131826Sharti } 149131826Sharti return (0); 150131826Sharti} 151131826Sharti 152131826Sharti#define COMMON_OVERLAP(A1,A2) \ 153131826Sharti if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_ABSENT) || \ 154131826Sharti A1->tag == UNISVE_ANY || A2->tag == UNISVE_ANY) \ 155131826Sharti return (1); \ 156131826Sharti if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_PRESENT) || \ 157131826Sharti (A2->tag == UNISVE_ABSENT && A1->tag == UNISVE_PRESENT)) \ 158131826Sharti return (0); 159131826Sharti 160131826Shartiint 161131826Shartiunisve_overlap_addr(const struct unisve_addr *s1, const struct unisve_addr *s2) 162131826Sharti{ 163131826Sharti COMMON_OVERLAP(s1, s2); 164131826Sharti 165131826Sharti return (s1->type == s2->type && s1->plan == s2->plan && 166131826Sharti s1->len == s2->len && memcmp(s1->addr, s2->addr, s1->len) == 0); 167131826Sharti} 168131826Sharti 169131826Shartiint 170131826Shartiunisve_overlap_selector(const struct unisve_selector *s1, 171131826Sharti const struct unisve_selector *s2) 172131826Sharti{ 173131826Sharti COMMON_OVERLAP(s1, s2); 174131826Sharti 175131826Sharti return (s1->selector == s2->selector); 176131826Sharti} 177131826Sharti 178131826Shartiint 179131826Shartiunisve_overlap_blli_id2(const struct unisve_blli_id2 *s1, 180131826Sharti const struct unisve_blli_id2 *s2) 181131826Sharti{ 182131826Sharti COMMON_OVERLAP(s1, s2); 183131826Sharti 184131826Sharti return (s1->proto == s2->proto && 185131826Sharti (s1->proto != UNI_BLLI_L2_USER || s1->user == s2->user)); 186131826Sharti} 187131826Sharti 188131826Shartiint 189131826Shartiunisve_overlap_blli_id3(const struct unisve_blli_id3 *s1, 190131826Sharti const struct unisve_blli_id3 *s2) 191131826Sharti{ 192131826Sharti COMMON_OVERLAP(s1, s2); 193131826Sharti 194131826Sharti if (s1->proto != s2->proto) 195131826Sharti return (0); 196131826Sharti if (s1->proto == UNI_BLLI_L3_USER) 197131826Sharti return (s1->user == s2->user); 198131826Sharti if (s1->proto == UNI_BLLI_L3_TR9577) { 199131826Sharti if (s1->noipi && s2->noipi) 200131826Sharti return (1); 201131826Sharti if (!s1->noipi && !s2->noipi) { 202131826Sharti if (s1->ipi == s2->ipi) { 203131826Sharti if (s1->ipi != UNI_BLLI_L3_SNAP) 204131826Sharti return (1); 205131826Sharti if (s1->oui == s2->oui && s1->pid == s2->pid) 206131826Sharti return (1); 207131826Sharti } 208131826Sharti } 209131826Sharti return (0); 210131826Sharti } 211131826Sharti return (1); 212131826Sharti} 213131826Sharti 214131826Shartiint 215131826Shartiunisve_overlap_bhli(const struct unisve_bhli *s1, const struct unisve_bhli *s2) 216131826Sharti{ 217131826Sharti COMMON_OVERLAP(s1, s2); 218131826Sharti 219131826Sharti return (s1->type == s2->type && s1->len == s2->len && 220131826Sharti memcmp(s1->info, s2->info, s1->len) == 0); 221131826Sharti} 222131826Sharti 223131826Shartiint 224131826Shartiunisve_overlap_sap(const struct uni_sap *s1, const struct uni_sap *s2) 225131826Sharti{ 226131826Sharti int any1, any2; 227131826Sharti 228131826Sharti /* 229131826Sharti * Two catch-all's SAP's are not allowed. A catch-all does never 230131826Sharti * overlap with a non-catch all SAP. 231131826Sharti */ 232131826Sharti any1 = unisve_is_catchall(s1); 233131826Sharti any2 = unisve_is_catchall(s2); 234131826Sharti 235131826Sharti if (any1 && any2) 236131826Sharti return (1); 237131826Sharti if(any1 || any2) 238131826Sharti return (0); 239131826Sharti 240131826Sharti return (unisve_overlap_addr(&s1->addr, &s2->addr) && 241131826Sharti unisve_overlap_selector(&s1->selector, &s2->selector) && 242131826Sharti unisve_overlap_blli_id2(&s1->blli_id2, &s2->blli_id2) && 243131826Sharti unisve_overlap_blli_id3(&s1->blli_id3, &s2->blli_id3) && 244131826Sharti unisve_overlap_bhli(&s1->bhli, &s2->bhli)); 245131826Sharti} 246131826Sharti 247131826Shartiint 248131826Shartiunisve_is_catchall(const struct uni_sap *sap) 249131826Sharti{ 250131826Sharti return (sap->addr.tag == UNISVE_ANY && 251131826Sharti sap->selector.tag == UNISVE_ANY && 252131826Sharti sap->blli_id2.tag == UNISVE_ANY && 253131826Sharti sap->blli_id3.tag == UNISVE_ANY && 254131826Sharti sap->bhli.tag == UNISVE_ANY); 255131826Sharti} 256131826Sharti 257131826Shartiint 258131826Shartiunisve_match(const struct uni_sap *sap, const struct uni_ie_called *called, 259131826Sharti const struct uni_ie_blli *blli, const struct uni_ie_bhli *bhli) 260131826Sharti{ 261131826Sharti switch (sap->addr.tag) { 262131826Sharti case UNISVE_ABSENT: 263131826Sharti if (IE_ISGOOD(*called)) 264131826Sharti return (0); 265131826Sharti break; 266131826Sharti 267131826Sharti case UNISVE_ANY: 268131826Sharti break; 269131826Sharti 270131826Sharti case UNISVE_PRESENT: 271131826Sharti if (!IE_ISGOOD(*called)) 272131826Sharti return (0); 273131826Sharti if (called->addr.type != sap->addr.type || 274131826Sharti called->addr.plan != sap->addr.plan) 275131826Sharti return (0); 276131826Sharti if (called->addr.plan == UNI_ADDR_E164) { 277131826Sharti if (called->addr.len != sap->addr.len || 278131826Sharti memcmp(called->addr.addr, sap->addr.addr, 279131826Sharti called->addr.len) != 0) 280131826Sharti return (0); 281131826Sharti } else if (called->addr.plan == UNI_ADDR_ATME) { 282131826Sharti if (called->addr.len != 20 || 283131826Sharti memcmp(called->addr.addr, sap->addr.addr, 19) != 0) 284131826Sharti return (0); 285131826Sharti } 286131826Sharti break; 287131826Sharti 288131826Sharti default: 289131826Sharti return (0); 290131826Sharti } 291131826Sharti 292131826Sharti switch (sap->selector.tag) { 293131826Sharti 294131826Sharti case UNISVE_ABSENT: 295131826Sharti if (IE_ISGOOD(*called) && called->addr.plan == UNI_ADDR_ATME) 296131826Sharti return (0); 297131826Sharti break; 298131826Sharti 299131826Sharti case UNISVE_ANY: 300131826Sharti break; 301131826Sharti 302131826Sharti case UNISVE_PRESENT: 303131826Sharti if (!IE_ISGOOD(*called)) 304131826Sharti return (0); 305131826Sharti if (called->addr.plan != UNI_ADDR_ATME) 306131826Sharti return (0); 307131826Sharti if (called->addr.addr[19] != sap->selector.selector) 308131826Sharti return (0); 309131826Sharti break; 310131826Sharti 311131826Sharti default: 312131826Sharti return (0); 313131826Sharti } 314131826Sharti 315131826Sharti switch (sap->blli_id2.tag) { 316131826Sharti 317131826Sharti case UNISVE_ABSENT: 318131826Sharti if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L2_P)) 319131826Sharti return (0); 320131826Sharti break; 321131826Sharti 322131826Sharti case UNISVE_ANY: 323131826Sharti break; 324131826Sharti 325131826Sharti case UNISVE_PRESENT: 326131826Sharti if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L2_P) == 0) 327131826Sharti return (0); 328131826Sharti if (blli->l2 != sap->blli_id2.proto) 329131826Sharti return (0); 330131826Sharti if (blli->l2 == UNI_BLLI_L2_USER) { 331131826Sharti if ((blli->h.present & UNI_BLLI_L2_USER_P) == 0) 332131826Sharti return (0); 333131826Sharti if (blli->l2_user != sap->blli_id2.user) 334131826Sharti return (0); 335131826Sharti } 336131826Sharti break; 337131826Sharti 338131826Sharti default: 339131826Sharti return (0); 340131826Sharti } 341131826Sharti 342131826Sharti switch (sap->blli_id3.tag) { 343131826Sharti 344131826Sharti case UNISVE_ABSENT: 345131826Sharti if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L3_P)) 346131826Sharti return (0); 347131826Sharti break; 348131826Sharti 349131826Sharti case UNISVE_ANY: 350131826Sharti break; 351131826Sharti 352131826Sharti case UNISVE_PRESENT: 353131826Sharti if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L3_P) == 0) 354131826Sharti return (0); 355131826Sharti if (blli->l3 != sap->blli_id3.proto) 356131826Sharti return (0); 357131826Sharti if (blli->l3 == UNI_BLLI_L3_USER) { 358131826Sharti if ((blli->h.present & UNI_BLLI_L3_USER_P) == 0) 359131826Sharti return (0); 360131826Sharti if (blli->l3_user != sap->blli_id3.user) 361131826Sharti return (0); 362131826Sharti break; 363131826Sharti } 364131826Sharti if (blli->l3 == UNI_BLLI_L3_TR9577) { 365131826Sharti if (sap->blli_id3.noipi) { 366131826Sharti if (blli->h.present & UNI_BLLI_L3_IPI_P) 367131826Sharti return (0); 368131826Sharti } else { 369131826Sharti if (!(blli->h.present & UNI_BLLI_L3_IPI_P)) 370131826Sharti return (0); 371131826Sharti if (blli->l3_ipi != sap->blli_id3.ipi) 372131826Sharti return (0); 373131826Sharti if (blli->l3_ipi == UNI_BLLI_L3_SNAP) { 374131826Sharti if (!(blli->h.present & 375131826Sharti UNI_BLLI_L3_SNAP_P)) 376131826Sharti return (0); 377131826Sharti if (blli->oui != sap->blli_id3.oui || 378131826Sharti blli->pid != sap->blli_id3.pid) 379131826Sharti return (0); 380131826Sharti } 381131826Sharti } 382131826Sharti } 383131826Sharti break; 384131826Sharti 385131826Sharti default: 386131826Sharti return (0); 387131826Sharti } 388131826Sharti 389131826Sharti switch (sap->bhli.tag) { 390131826Sharti 391131826Sharti case UNISVE_ABSENT: 392131826Sharti if (IE_ISGOOD(*bhli)) 393131826Sharti return (0); 394131826Sharti break; 395131826Sharti 396131826Sharti case UNISVE_ANY: 397131826Sharti break; 398131826Sharti 399131826Sharti case UNISVE_PRESENT: 400131826Sharti if (!IE_ISGOOD(*bhli)) 401131826Sharti return (0); 402131826Sharti if (sap->bhli.type != bhli->type) 403131826Sharti return (0); 404131826Sharti if (sap->bhli.len != bhli->len) 405131826Sharti return (0); 406131826Sharti if (memcmp(sap->bhli.info, bhli->info, bhli->len) != 0) 407131826Sharti return (0); 408131826Sharti break; 409131826Sharti 410131826Sharti default: 411131826Sharti return (0); 412131826Sharti } 413131826Sharti /* Uff */ 414131826Sharti return (1); 415131826Sharti} 416