]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/ngatm/netnatm/api/unisap.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / ngatm / netnatm / api / unisap.c
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
45 int
46 unisve_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
72 int
73 unisve_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  */
85 int
86 unisve_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  */
98 int
99 unisve_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
108 int
109 unisve_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
130 int
131 unisve_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
160 int
161 unisve_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
169 int
170 unisve_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
178 int
179 unisve_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
188 int
189 unisve_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
214 int
215 unisve_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
223 int
224 unisve_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
247 int
248 unisve_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
257 int
258 unisve_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 }