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 <[email protected]>
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
unisve_check_addr(const struct unisve_addr * sve)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
unisve_check_selector(const struct unisve_selector * sve)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
unisve_check_blli_id2(const struct unisve_blli_id2 * sve)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
unisve_check_blli_id3(const struct unisve_blli_id3 * sve)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
unisve_check_bhli(const struct unisve_bhli * sve)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
unisve_check_sap(const struct uni_sap * sap)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
unisve_overlap_addr(const struct unisve_addr * s1,const struct unisve_addr * s2)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
unisve_overlap_selector(const struct unisve_selector * s1,const struct unisve_selector * s2)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
unisve_overlap_blli_id2(const struct unisve_blli_id2 * s1,const struct unisve_blli_id2 * s2)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
unisve_overlap_blli_id3(const struct unisve_blli_id3 * s1,const struct unisve_blli_id3 * s2)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
unisve_overlap_bhli(const struct unisve_bhli * s1,const struct unisve_bhli * s2)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
unisve_overlap_sap(const struct uni_sap * s1,const struct uni_sap * s2)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
unisve_is_catchall(const struct uni_sap * sap)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
unisve_match(const struct uni_sap * sap,const struct uni_ie_called * called,const struct uni_ie_blli * blli,const struct uni_ie_bhli * bhli)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 }
416