Merge branch 'vendor/MPC'
[dragonfly.git] / sys / net / libalias / alias_mod.c
1 /*-
2  * Copyright (c) 2005 Paolo Pisati <piso@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_mod.c,v 1.3.6.1 2008/11/25 02:59:29 kensmith Exp $");
29
30 #ifdef _KERNEL
31 #include <sys/libkern.h>
32 #include <sys/param.h>
33 #include <sys/lock.h>
34 #include <sys/idr.h>
35 #include <sys/queue.h>
36 #else
37 #include <stdio.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <errno.h>
41 #endif
42
43 #include <netinet/in_systm.h>
44 #include <netinet/in.h>
45 #include <netinet/ip.h>
46
47
48 #include "alias_local.h"
49 #include "alias_mod.h"
50
51 /* Protocol and userland module handlers chains. */
52 LIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(foo);
53
54 SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(foo);
55
56
57 #define LIBALIAS_RWLOCK_INIT() ;
58 #define LIBALIAS_RWLOCK_DESTROY()       ;
59 #define LIBALIAS_WLOCK_ASSERT() ;
60 #define LIBALIAS_RLOCK() ;
61 #define LIBALIAS_RUNLOCK() ;
62 #define LIBALIAS_WLOCK() ;
63 #define LIBALIAS_WUNLOCK() ;
64 #define _handler_chain_init() ;
65 #define _handler_chain_destroy() ;
66
67 void
68 handler_chain_init(void)
69 {
70         _handler_chain_init();
71 }
72
73 void
74 handler_chain_destroy(void)
75 {
76         _handler_chain_destroy();
77 }
78
79 static int
80 _attach_handler(struct proto_handler *p)
81 {
82         struct proto_handler *b = NULL;
83
84         LIBALIAS_WLOCK_ASSERT();
85         LIST_FOREACH(b, &handler_chain, entries) {
86                 if ((b->pri == p->pri) &&
87                         (b->dir == p->dir) &&
88                         (b->proto == p->proto))
89                         return (EEXIST); /* Priority conflict. */
90                 if (b->pri > p->pri) {
91                         LIST_INSERT_BEFORE(b, p, entries);
92                         return (0);
93                 }
94         }
95         /* End of list or found right position, inserts here. */
96         if (b)
97                 LIST_INSERT_AFTER(b, p, entries);
98         else
99                 LIST_INSERT_HEAD(&handler_chain, p, entries);
100         return (0);
101 }
102
103 static int
104 _detach_handler(struct proto_handler *p)
105 {
106         struct proto_handler *b, *b_tmp;;
107
108         LIBALIAS_WLOCK_ASSERT();
109
110         LIST_FOREACH_MUTABLE(b, &handler_chain, entries, b_tmp) {
111                 if (b == p) {
112                         LIST_REMOVE(b, entries);
113                         return (0);
114                 }
115         }
116
117
118         return (ENOENT); /* Handler not found. */
119 }
120
121 int
122 LibAliasAttachHandlers(struct proto_handler *_p)
123 {
124         int i, error = -1;
125
126         LIBALIAS_WLOCK();
127         for (i=0; 1; i++) {
128                 if (*((int *)&_p[i]) == EOH)
129                         break;
130                 error = _attach_handler(&_p[i]);
131                 if (error != 0)
132                         break;
133         }
134         LIBALIAS_WUNLOCK();
135         return (error);
136 }
137
138 int
139 LibAliasDetachHandlers(struct proto_handler *_p)
140 {
141         int i, error = -1;
142
143         LIBALIAS_WLOCK();
144         for (i=0; 1; i++) {
145                 if (*((int *)&_p[i]) == EOH)
146                         break;
147                 error = _detach_handler(&_p[i]);
148                 if (error != 0)
149                         break;
150         }
151         LIBALIAS_WUNLOCK();
152         return (error);
153 }
154
155 int
156 detach_handler(struct proto_handler *_p)
157 {
158         int error = -1;
159
160         LIBALIAS_WLOCK();
161         error = _detach_handler(_p);
162         LIBALIAS_WUNLOCK();
163         return (error);
164 }
165
166 int
167 find_handler(int8_t dir, int8_t proto, struct libalias *la, struct ip *pip,
168                  struct alias_data *ad)
169 {
170         struct proto_handler *p;
171         int error = ENOENT;
172
173         LIBALIAS_RLOCK();
174
175         LIST_FOREACH(p, &handler_chain, entries) {
176                 if ((p->dir & dir) && (p->proto & proto))
177                         if (p->fingerprint(la, pip, ad) == 0) {
178                                 error = p->protohandler(la, pip, ad);
179                                 break;
180                         }
181         }
182         LIBALIAS_RUNLOCK();
183         return (error);
184 }
185
186 struct proto_handler *
187 first_handler(void)
188 {
189
190         return (LIST_FIRST(&handler_chain));
191 }
192
193 /* Dll manipulation code - this code is not thread safe... */
194
195
196
197 struct dll *
198 walk_dll_chain(void)
199 {
200         struct dll *t;
201
202         t = SLIST_FIRST(&dll_chain);
203         if (t == NULL)
204                 return (NULL);
205         SLIST_REMOVE_HEAD(&dll_chain, next);
206         return (t);
207 }