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