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