xref: /freebsd/sys/netinet/libalias/alias_mod.c (revision 1019f603d557f059a34e128d45f58d519b802734)
1be4f3cd0SPaolo Pisati /*-
2be4f3cd0SPaolo Pisati  * Copyright (c) 2005 Paolo Pisati <piso@FreeBSD.org>
3be4f3cd0SPaolo Pisati  * All rights reserved.
4be4f3cd0SPaolo Pisati  *
5be4f3cd0SPaolo Pisati  * Redistribution and use in source and binary forms, with or without
6be4f3cd0SPaolo Pisati  * modification, are permitted provided that the following conditions
7be4f3cd0SPaolo Pisati  * are met:
8be4f3cd0SPaolo Pisati  * 1. Redistributions of source code must retain the above copyright
9be4f3cd0SPaolo Pisati  *    notice, this list of conditions and the following disclaimer.
10be4f3cd0SPaolo Pisati  * 2. Redistributions in binary form must reproduce the above copyright
11be4f3cd0SPaolo Pisati  *    notice, this list of conditions and the following disclaimer in the
12be4f3cd0SPaolo Pisati  *    documentation and/or other materials provided with the distribution.
13be4f3cd0SPaolo Pisati  *
14be4f3cd0SPaolo Pisati  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15be4f3cd0SPaolo Pisati  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16be4f3cd0SPaolo Pisati  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17be4f3cd0SPaolo Pisati  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18be4f3cd0SPaolo Pisati  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19be4f3cd0SPaolo Pisati  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20be4f3cd0SPaolo Pisati  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21be4f3cd0SPaolo Pisati  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22be4f3cd0SPaolo Pisati  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23be4f3cd0SPaolo Pisati  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24be4f3cd0SPaolo Pisati  * SUCH DAMAGE.
25be4f3cd0SPaolo Pisati  *
26be4f3cd0SPaolo Pisati  */
277c00cc76SPaolo Pisati #include <sys/cdefs.h>
28be4f3cd0SPaolo Pisati __FBSDID("$FreeBSD$");
29be4f3cd0SPaolo Pisati 
30be4f3cd0SPaolo Pisati #ifdef _KERNEL
31be4f3cd0SPaolo Pisati #include <sys/libkern.h>
32be4f3cd0SPaolo Pisati #include <sys/param.h>
33be4f3cd0SPaolo Pisati #include <sys/lock.h>
34be4f3cd0SPaolo Pisati #include <sys/rwlock.h>
35be4f3cd0SPaolo Pisati #else
36be4f3cd0SPaolo Pisati #include <stdio.h>
37be4f3cd0SPaolo Pisati #include <string.h>
38be4f3cd0SPaolo Pisati #include <sys/types.h>
39be4f3cd0SPaolo Pisati #include <errno.h>
40be4f3cd0SPaolo Pisati #endif
41be4f3cd0SPaolo Pisati 
42be4f3cd0SPaolo Pisati #include <netinet/in_systm.h>
43be4f3cd0SPaolo Pisati #include <netinet/in.h>
44be4f3cd0SPaolo Pisati #include <netinet/ip.h>
45be4f3cd0SPaolo Pisati 
46be4f3cd0SPaolo Pisati #ifdef _KERNEL
47be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_local.h>
48be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h>
49be4f3cd0SPaolo Pisati #else
50be4f3cd0SPaolo Pisati #include "alias_local.h"
51be4f3cd0SPaolo Pisati #include "alias_mod.h"
52be4f3cd0SPaolo Pisati #endif
53be4f3cd0SPaolo Pisati 
54be4f3cd0SPaolo Pisati /* Protocol and userland module handlers chains. */
5513e403fdSAntoine Brodin LIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(handler_chain);
56be4f3cd0SPaolo Pisati #ifdef _KERNEL
57be4f3cd0SPaolo Pisati struct rwlock   handler_rw;
58be4f3cd0SPaolo Pisati #endif
5913e403fdSAntoine Brodin SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(dll_chain);
60be4f3cd0SPaolo Pisati 
61be4f3cd0SPaolo Pisati #ifdef _KERNEL
62be4f3cd0SPaolo Pisati 
63ccd57eeaSPaolo Pisati #define	LIBALIAS_RWLOCK_INIT() \
64be4f3cd0SPaolo Pisati 	rw_init(&handler_rw, "Libalias_modules_rwlock")
65ccd57eeaSPaolo Pisati #define	LIBALIAS_RWLOCK_DESTROY()	rw_destroy(&handler_rw)
66be4f3cd0SPaolo Pisati #define	LIBALIAS_WLOCK_ASSERT() \
67be4f3cd0SPaolo Pisati 	rw_assert(&handler_rw, RA_WLOCKED)
68be4f3cd0SPaolo Pisati 
69be4f3cd0SPaolo Pisati static __inline void
70be4f3cd0SPaolo Pisati LIBALIAS_RLOCK(void)
71be4f3cd0SPaolo Pisati {
72be4f3cd0SPaolo Pisati 	rw_rlock(&handler_rw);
73be4f3cd0SPaolo Pisati }
74be4f3cd0SPaolo Pisati 
75be4f3cd0SPaolo Pisati static __inline void
76be4f3cd0SPaolo Pisati LIBALIAS_RUNLOCK(void)
77be4f3cd0SPaolo Pisati {
78be4f3cd0SPaolo Pisati 	rw_runlock(&handler_rw);
79be4f3cd0SPaolo Pisati }
80be4f3cd0SPaolo Pisati 
81be4f3cd0SPaolo Pisati static __inline void
82be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(void)
83be4f3cd0SPaolo Pisati {
84be4f3cd0SPaolo Pisati 	rw_wlock(&handler_rw);
85be4f3cd0SPaolo Pisati }
86be4f3cd0SPaolo Pisati 
87be4f3cd0SPaolo Pisati static __inline void
88be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(void)
89be4f3cd0SPaolo Pisati {
90be4f3cd0SPaolo Pisati 	rw_wunlock(&handler_rw);
91be4f3cd0SPaolo Pisati }
92be4f3cd0SPaolo Pisati 
93be4f3cd0SPaolo Pisati static void
94be4f3cd0SPaolo Pisati _handler_chain_init(void)
95be4f3cd0SPaolo Pisati {
96be4f3cd0SPaolo Pisati 
97be4f3cd0SPaolo Pisati 	if (!rw_initialized(&handler_rw))
98ccd57eeaSPaolo Pisati 		LIBALIAS_RWLOCK_INIT();
99be4f3cd0SPaolo Pisati }
100be4f3cd0SPaolo Pisati 
101be4f3cd0SPaolo Pisati static void
102be4f3cd0SPaolo Pisati _handler_chain_destroy(void)
103be4f3cd0SPaolo Pisati {
104be4f3cd0SPaolo Pisati 
105be4f3cd0SPaolo Pisati 	if (rw_initialized(&handler_rw))
106ccd57eeaSPaolo Pisati 		LIBALIAS_RWLOCK_DESTROY();
107be4f3cd0SPaolo Pisati }
108be4f3cd0SPaolo Pisati 
109be4f3cd0SPaolo Pisati #else
110ccd57eeaSPaolo Pisati #define	LIBALIAS_RWLOCK_INIT() ;
111ccd57eeaSPaolo Pisati #define	LIBALIAS_RWLOCK_DESTROY()	;
112be4f3cd0SPaolo Pisati #define	LIBALIAS_WLOCK_ASSERT()	;
113be4f3cd0SPaolo Pisati #define	LIBALIAS_RLOCK() ;
114be4f3cd0SPaolo Pisati #define	LIBALIAS_RUNLOCK() ;
115be4f3cd0SPaolo Pisati #define	LIBALIAS_WLOCK() ;
116be4f3cd0SPaolo Pisati #define	LIBALIAS_WUNLOCK() ;
117be4f3cd0SPaolo Pisati #define _handler_chain_init() ;
118be4f3cd0SPaolo Pisati #define _handler_chain_destroy() ;
119be4f3cd0SPaolo Pisati #endif
120be4f3cd0SPaolo Pisati 
121be4f3cd0SPaolo Pisati void
122be4f3cd0SPaolo Pisati handler_chain_init(void)
123be4f3cd0SPaolo Pisati {
124be4f3cd0SPaolo Pisati 	_handler_chain_init();
125be4f3cd0SPaolo Pisati }
126be4f3cd0SPaolo Pisati 
127be4f3cd0SPaolo Pisati void
128be4f3cd0SPaolo Pisati handler_chain_destroy(void)
129be4f3cd0SPaolo Pisati {
130be4f3cd0SPaolo Pisati 	_handler_chain_destroy();
131be4f3cd0SPaolo Pisati }
132be4f3cd0SPaolo Pisati 
133be4f3cd0SPaolo Pisati static int
134be4f3cd0SPaolo Pisati _attach_handler(struct proto_handler *p)
135be4f3cd0SPaolo Pisati {
13643197d29SPaolo Pisati 	struct proto_handler *b;
137be4f3cd0SPaolo Pisati 
138be4f3cd0SPaolo Pisati 	LIBALIAS_WLOCK_ASSERT();
13943197d29SPaolo Pisati 	b = NULL;
140be4f3cd0SPaolo Pisati 	LIST_FOREACH(b, &handler_chain, entries) {
141be4f3cd0SPaolo Pisati 		if ((b->pri == p->pri) &&
142be4f3cd0SPaolo Pisati 		    (b->dir == p->dir) &&
143be4f3cd0SPaolo Pisati 		    (b->proto == p->proto))
144be4f3cd0SPaolo Pisati 			return (EEXIST); /* Priority conflict. */
145be4f3cd0SPaolo Pisati 		if (b->pri > p->pri) {
146be4f3cd0SPaolo Pisati 			LIST_INSERT_BEFORE(b, p, entries);
147be4f3cd0SPaolo Pisati 			return (0);
148be4f3cd0SPaolo Pisati 		}
149be4f3cd0SPaolo Pisati 	}
150be4f3cd0SPaolo Pisati 	/* End of list or found right position, inserts here. */
151be4f3cd0SPaolo Pisati 	if (b)
152be4f3cd0SPaolo Pisati 		LIST_INSERT_AFTER(b, p, entries);
153be4f3cd0SPaolo Pisati 	else
154be4f3cd0SPaolo Pisati 		LIST_INSERT_HEAD(&handler_chain, p, entries);
155be4f3cd0SPaolo Pisati 	return (0);
156be4f3cd0SPaolo Pisati }
157be4f3cd0SPaolo Pisati 
158be4f3cd0SPaolo Pisati static int
159be4f3cd0SPaolo Pisati _detach_handler(struct proto_handler *p)
160be4f3cd0SPaolo Pisati {
161c2ede4b3SMartin Blapp 	struct proto_handler *b, *b_tmp;
162be4f3cd0SPaolo Pisati 
163be4f3cd0SPaolo Pisati 	LIBALIAS_WLOCK_ASSERT();
164be4f3cd0SPaolo Pisati 	LIST_FOREACH_SAFE(b, &handler_chain, entries, b_tmp) {
165be4f3cd0SPaolo Pisati 		if (b == p) {
166be4f3cd0SPaolo Pisati 			LIST_REMOVE(b, entries);
167be4f3cd0SPaolo Pisati 			return (0);
168be4f3cd0SPaolo Pisati 		}
169be4f3cd0SPaolo Pisati 	}
170be4f3cd0SPaolo Pisati 	return (ENOENT); /* Handler not found. */
171be4f3cd0SPaolo Pisati }
172be4f3cd0SPaolo Pisati 
173be4f3cd0SPaolo Pisati int
174be4f3cd0SPaolo Pisati LibAliasAttachHandlers(struct proto_handler *_p)
175be4f3cd0SPaolo Pisati {
17643197d29SPaolo Pisati 	int i, error;
177be4f3cd0SPaolo Pisati 
178be4f3cd0SPaolo Pisati 	LIBALIAS_WLOCK();
17943197d29SPaolo Pisati 	error = -1;
180be4f3cd0SPaolo Pisati 	for (i = 0; 1; i++) {
181be4f3cd0SPaolo Pisati 		if (*((int *)&_p[i]) == EOH)
182be4f3cd0SPaolo Pisati 			break;
183be4f3cd0SPaolo Pisati 		error = _attach_handler(&_p[i]);
184be4f3cd0SPaolo Pisati 		if (error != 0)
185be4f3cd0SPaolo Pisati 			break;
186be4f3cd0SPaolo Pisati 	}
187be4f3cd0SPaolo Pisati 	LIBALIAS_WUNLOCK();
188be4f3cd0SPaolo Pisati 	return (error);
189be4f3cd0SPaolo Pisati }
190be4f3cd0SPaolo Pisati 
191be4f3cd0SPaolo Pisati int
192be4f3cd0SPaolo Pisati LibAliasDetachHandlers(struct proto_handler *_p)
193be4f3cd0SPaolo Pisati {
19443197d29SPaolo Pisati 	int i, error;
195be4f3cd0SPaolo Pisati 
196be4f3cd0SPaolo Pisati 	LIBALIAS_WLOCK();
19743197d29SPaolo Pisati 	error = -1;
198be4f3cd0SPaolo Pisati 	for (i = 0; 1; i++) {
199be4f3cd0SPaolo Pisati 		if (*((int *)&_p[i]) == EOH)
200be4f3cd0SPaolo Pisati 			break;
201be4f3cd0SPaolo Pisati 		error = _detach_handler(&_p[i]);
202be4f3cd0SPaolo Pisati 		if (error != 0)
203be4f3cd0SPaolo Pisati 			break;
204be4f3cd0SPaolo Pisati 	}
205be4f3cd0SPaolo Pisati 	LIBALIAS_WUNLOCK();
206be4f3cd0SPaolo Pisati 	return (error);
207be4f3cd0SPaolo Pisati }
208be4f3cd0SPaolo Pisati 
209be4f3cd0SPaolo Pisati int
210be4f3cd0SPaolo Pisati detach_handler(struct proto_handler *_p)
211be4f3cd0SPaolo Pisati {
21243197d29SPaolo Pisati 	int error;
213be4f3cd0SPaolo Pisati 
214be4f3cd0SPaolo Pisati 	LIBALIAS_WLOCK();
21543197d29SPaolo Pisati 	error = -1;
216be4f3cd0SPaolo Pisati 	error = _detach_handler(_p);
217be4f3cd0SPaolo Pisati 	LIBALIAS_WUNLOCK();
218be4f3cd0SPaolo Pisati 	return (error);
219be4f3cd0SPaolo Pisati }
220be4f3cd0SPaolo Pisati 
221be4f3cd0SPaolo Pisati int
22243197d29SPaolo Pisati find_handler(int8_t dir, int8_t proto, struct libalias *la, __unused struct ip *pip,
223be4f3cd0SPaolo Pisati     struct alias_data *ad)
224be4f3cd0SPaolo Pisati {
225be4f3cd0SPaolo Pisati 	struct proto_handler *p;
22643197d29SPaolo Pisati 	int error;
227be4f3cd0SPaolo Pisati 
228be4f3cd0SPaolo Pisati 	LIBALIAS_RLOCK();
22943197d29SPaolo Pisati 	error = ENOENT;
230be4f3cd0SPaolo Pisati 	LIST_FOREACH(p, &handler_chain, entries) {
231be4f3cd0SPaolo Pisati 		if ((p->dir & dir) && (p->proto & proto))
23243197d29SPaolo Pisati 			if (p->fingerprint(la, ad) == 0) {
233be4f3cd0SPaolo Pisati 				error = p->protohandler(la, pip, ad);
234be4f3cd0SPaolo Pisati 				break;
235be4f3cd0SPaolo Pisati 			}
236be4f3cd0SPaolo Pisati 	}
237be4f3cd0SPaolo Pisati 	LIBALIAS_RUNLOCK();
238be4f3cd0SPaolo Pisati 	return (error);
239be4f3cd0SPaolo Pisati }
240be4f3cd0SPaolo Pisati 
241be4f3cd0SPaolo Pisati struct proto_handler *
242be4f3cd0SPaolo Pisati first_handler(void)
243be4f3cd0SPaolo Pisati {
244be4f3cd0SPaolo Pisati 
245be4f3cd0SPaolo Pisati 	return (LIST_FIRST(&handler_chain));
246be4f3cd0SPaolo Pisati }
247be4f3cd0SPaolo Pisati 
248*1019f603SGleb Smirnoff #ifndef _KERNEL
249be4f3cd0SPaolo Pisati /* Dll manipulation code - this code is not thread safe... */
250be4f3cd0SPaolo Pisati int
251be4f3cd0SPaolo Pisati attach_dll(struct dll *p)
252be4f3cd0SPaolo Pisati {
253be4f3cd0SPaolo Pisati 	struct dll *b;
254be4f3cd0SPaolo Pisati 
255be4f3cd0SPaolo Pisati 	SLIST_FOREACH(b, &dll_chain, next) {
256be4f3cd0SPaolo Pisati 		if (!strncmp(b->name, p->name, DLL_LEN))
257be4f3cd0SPaolo Pisati 			return (EEXIST); /* Dll name conflict. */
258be4f3cd0SPaolo Pisati 	}
259be4f3cd0SPaolo Pisati 	SLIST_INSERT_HEAD(&dll_chain, p, next);
260be4f3cd0SPaolo Pisati 	return (0);
261be4f3cd0SPaolo Pisati }
262be4f3cd0SPaolo Pisati 
263be4f3cd0SPaolo Pisati void *
264be4f3cd0SPaolo Pisati detach_dll(char *p)
265be4f3cd0SPaolo Pisati {
26643197d29SPaolo Pisati 	struct dll *b, *b_tmp;
26743197d29SPaolo Pisati 	void *error;
268be4f3cd0SPaolo Pisati 
26943197d29SPaolo Pisati 	b = NULL;
27043197d29SPaolo Pisati 	error = NULL;
271be4f3cd0SPaolo Pisati 	SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp)
272be4f3cd0SPaolo Pisati 		if (!strncmp(b->name, p, DLL_LEN)) {
273be4f3cd0SPaolo Pisati 			SLIST_REMOVE(&dll_chain, b, dll, next);
274be4f3cd0SPaolo Pisati 			error = b;
275be4f3cd0SPaolo Pisati 			break;
276be4f3cd0SPaolo Pisati 		}
277be4f3cd0SPaolo Pisati 	return (error);
278be4f3cd0SPaolo Pisati }
279be4f3cd0SPaolo Pisati 
280be4f3cd0SPaolo Pisati struct dll *
281be4f3cd0SPaolo Pisati walk_dll_chain(void)
282be4f3cd0SPaolo Pisati {
283be4f3cd0SPaolo Pisati 	struct dll *t;
284be4f3cd0SPaolo Pisati 
285be4f3cd0SPaolo Pisati 	t = SLIST_FIRST(&dll_chain);
286be4f3cd0SPaolo Pisati 	if (t == NULL)
287be4f3cd0SPaolo Pisati 		return (NULL);
288be4f3cd0SPaolo Pisati 	SLIST_REMOVE_HEAD(&dll_chain, next);
289be4f3cd0SPaolo Pisati 	return (t);
290be4f3cd0SPaolo Pisati }
291*1019f603SGleb Smirnoff #endif /* !_KERNEL */
292