Mercurial > hg > freeDiameter
comparison libfdcore/endpoints.c @ 658:f198d16fa7f4
Initial commit for 1.1.0:
* Restructuring:
* libfreeDiameter:
- renamed folder & binary into libfdproto
- renamed libfD.h into fdproto-internal.h
- removed signals management (replaced by triggers in libfdcore)
* freeDiameter split into:
- libfdcore (most contents)
- renamed fD.h into fdcore-internal.h
- added core.c for framework init/shutdown.
- new triggers mechanism in events.c.
- freeDiameterd (main, command line parsing, signals management)
* tests:
- now in top-level directory tests.
* other changes:
- fd_dict_new now returns 0 on duplicate identical entries.
- fixes in dict_legacy_xml
- fixes in some dictionaries
- moved FD_DEFAULT_CONF_FILENAME definition to freeDiameter-host.h
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Fri, 14 Jan 2011 15:15:23 +0900 |
parents | freeDiameter/endpoints.c@237cf6339546 |
children | 2e94ef0515d7 |
comparison
equal
deleted
inserted
replaced
656:5b05d85682f1 | 658:f198d16fa7f4 |
---|---|
1 /********************************************************************************************************* | |
2 * Software License Agreement (BSD License) * | |
3 * Author: Sebastien Decugis <sdecugis@nict.go.jp> * | |
4 * * | |
5 * Copyright (c) 2010, WIDE Project and NICT * | |
6 * All rights reserved. * | |
7 * * | |
8 * Redistribution and use of this software in source and binary forms, with or without modification, are * | |
9 * permitted provided that the following conditions are met: * | |
10 * * | |
11 * * Redistributions of source code must retain the above * | |
12 * copyright notice, this list of conditions and the * | |
13 * following disclaimer. * | |
14 * * | |
15 * * Redistributions in binary form must reproduce the above * | |
16 * copyright notice, this list of conditions and the * | |
17 * following disclaimer in the documentation and/or other * | |
18 * materials provided with the distribution. * | |
19 * * | |
20 * * Neither the name of the WIDE Project or NICT nor the * | |
21 * names of its contributors may be used to endorse or * | |
22 * promote products derived from this software without * | |
23 * specific prior written permission of WIDE Project and * | |
24 * NICT. * | |
25 * * | |
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * | |
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * | |
28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * | |
29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * | |
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * | |
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * | |
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * | |
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | |
34 *********************************************************************************************************/ | |
35 | |
36 #include "fdcore-internal.h" | |
37 | |
38 | |
39 /* Add an endpoint information in a list */ | |
40 int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags ) | |
41 { | |
42 struct fd_endpoint * ep; | |
43 struct fd_list * li; | |
44 union { | |
45 sSA * sa; | |
46 sSA4 *sin; | |
47 sSA6 *sin6; | |
48 } ptr; | |
49 in_port_t * port; | |
50 int cmp = -1; | |
51 | |
52 TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags); | |
53 CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) ); | |
54 | |
55 if (list->next == NULL) { | |
56 /* the list is not initialized yet, do it */ | |
57 fd_list_init(list, NULL); | |
58 } | |
59 | |
60 if (TRACE_BOOL(ANNOYING + 1)) { | |
61 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Current list:"); | |
62 fd_ep_dump( 4, list ); | |
63 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Adding:"); | |
64 fd_log_debug(" "); | |
65 sSA_DUMP_NODE_SERV( sa, NI_NUMERICHOST | NI_NUMERICSERV ); | |
66 fd_log_debug(" {%s%s%s%s}\n", | |
67 (flags & EP_FL_CONF) ? "C" : "-", | |
68 (flags & EP_FL_DISC) ? "D" : "-", | |
69 (flags & EP_FL_ADV) ? "A" : "-", | |
70 (flags & EP_FL_LL) ? "L" : "-", | |
71 (flags & EP_FL_PRIMARY) ? "P" : "-"); | |
72 } | |
73 ptr.sa = sa; | |
74 | |
75 /* Filter out a bunch of invalid addresses */ | |
76 switch (sa->sa_family) { | |
77 case AF_INET: | |
78 if (! (flags & EP_ACCEPTALL)) { | |
79 if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr) | |
80 || IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr) | |
81 /* the next one filters both EXPERIMENTAL, BADCLASS and MULTICAST. */ | |
82 || ((ntohl(ptr.sin->sin_addr.s_addr) & 0xe0000000) == 0xe0000000) | |
83 || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) { | |
84 if (TRACE_BOOL(ANNOYING + 1)) { | |
85 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); | |
86 } | |
87 return 0; | |
88 } | |
89 } | |
90 port = &ptr.sin->sin_port; | |
91 break; | |
92 | |
93 case AF_INET6: | |
94 if (! (flags & EP_ACCEPTALL)) { | |
95 if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr) | |
96 || IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr) | |
97 || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr) | |
98 || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr) | |
99 || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) { | |
100 if (TRACE_BOOL(ANNOYING + 1)) { | |
101 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); | |
102 } | |
103 return 0; | |
104 } | |
105 } | |
106 port = &ptr.sin6->sin6_port; | |
107 break; | |
108 | |
109 default: | |
110 if (TRACE_BOOL(ANNOYING + 1)) { | |
111 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address family was unknown, not added."); | |
112 } | |
113 return 0; | |
114 } | |
115 | |
116 /* remove the ACCEPTALL flag */ | |
117 flags &= ~EP_ACCEPTALL; | |
118 | |
119 /* Search place in the list */ | |
120 for (li = list->next; li != list; li = li->next) { | |
121 ep = (struct fd_endpoint *)li; | |
122 in_port_t * ep_port; | |
123 | |
124 /* First, compare the address family */ | |
125 if (ep->sa.sa_family < sa->sa_family) | |
126 continue; | |
127 if (ep->sa.sa_family > sa->sa_family) | |
128 break; | |
129 | |
130 /* Then compare the address field */ | |
131 switch (sa->sa_family) { | |
132 case AF_INET: | |
133 cmp = memcmp(&ep->sin.sin_addr, &ptr.sin->sin_addr, sizeof(struct in_addr)); | |
134 ep_port = &ep->sin.sin_port; | |
135 break; | |
136 case AF_INET6: | |
137 cmp = memcmp(&ep->sin6.sin6_addr, &ptr.sin6->sin6_addr, sizeof(struct in6_addr)); | |
138 ep_port = &ep->sin6.sin6_port; | |
139 break; | |
140 default: | |
141 ASSERT( 0 ); /* we got a different value previously in this same function */ | |
142 } | |
143 if (cmp < 0) | |
144 continue; | |
145 if (cmp > 0) | |
146 break; | |
147 | |
148 /* Finally compare the port, only if not 0 */ | |
149 if (*port == 0) | |
150 break; | |
151 if (*ep_port == 0) { | |
152 /* save the port information in the list, and break */ | |
153 *ep_port = *port; | |
154 break; | |
155 } | |
156 if (*ep_port < *port) | |
157 continue; | |
158 if (*ep_port > *port) | |
159 cmp = 1; | |
160 break; | |
161 } | |
162 | |
163 if (cmp) { | |
164 /* new item to be added */ | |
165 CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) ); | |
166 memset(ep, 0, sizeof(struct fd_endpoint)); | |
167 fd_list_init(&ep->chain, NULL); | |
168 memcpy(&ep->ss, sa, sl); | |
169 | |
170 /* Insert in the list */ | |
171 fd_list_insert_before(li, &ep->chain); | |
172 } | |
173 | |
174 /* Merge the flags */ | |
175 ep->flags |= flags; | |
176 | |
177 if (TRACE_BOOL(ANNOYING + 1)) { | |
178 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge New list:"); | |
179 fd_ep_dump( 4, list ); | |
180 } | |
181 return 0; | |
182 } | |
183 | |
184 /* Delete endpoints that do not have a matching flag from a list (0: delete all endpoints) */ | |
185 int fd_ep_filter( struct fd_list * list, uint32_t flags ) | |
186 { | |
187 struct fd_list * li; | |
188 | |
189 TRACE_ENTRY("%p %x", list, flags); | |
190 CHECK_PARAMS(list); | |
191 | |
192 if (TRACE_BOOL(ANNOYING + 1)) { | |
193 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Filter this list for flags %x:", flags); | |
194 fd_ep_dump( 4, list ); | |
195 } | |
196 for (li = list->next; li != list; li = li->next) { | |
197 struct fd_endpoint * ep = (struct fd_endpoint *)li; | |
198 | |
199 if (! (ep->flags & flags)) { | |
200 li = li->prev; | |
201 fd_list_unlink(&ep->chain); | |
202 free(ep); | |
203 } | |
204 } | |
205 | |
206 if (TRACE_BOOL(ANNOYING + 1)) { | |
207 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Resulting list:"); | |
208 fd_ep_dump( 4, list ); | |
209 } | |
210 return 0; | |
211 } | |
212 | |
213 /* Keep only endpoints of the same family as af */ | |
214 int fd_ep_filter_family( struct fd_list * list, int af ) | |
215 { | |
216 struct fd_list * li; | |
217 | |
218 TRACE_ENTRY("%p %d", list, af); | |
219 CHECK_PARAMS(list); | |
220 | |
221 if (TRACE_BOOL(ANNOYING + 1)) { | |
222 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Filter this list for family %d:", af); | |
223 fd_ep_dump( 4, list ); | |
224 } | |
225 for (li = list->next; li != list; li = li->next) { | |
226 struct fd_endpoint * ep = (struct fd_endpoint *)li; | |
227 | |
228 if (ep->sa.sa_family != af) { | |
229 li = li->prev; | |
230 fd_list_unlink(&ep->chain); | |
231 free(ep); | |
232 } | |
233 } | |
234 | |
235 if (TRACE_BOOL(ANNOYING + 1)) { | |
236 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Resulting list:"); | |
237 fd_ep_dump( 4, list ); | |
238 } | |
239 return 0; | |
240 } | |
241 | |
242 /* Remove any endpoint from the exclude list in the list */ | |
243 int fd_ep_filter_list( struct fd_list * list, struct fd_list * exclude_list ) | |
244 { | |
245 struct fd_list * li_out, *li_ex, *li; | |
246 struct fd_endpoint * out, * ex; | |
247 | |
248 TRACE_ENTRY("%p %p", list, exclude_list); | |
249 CHECK_PARAMS(list && exclude_list); | |
250 | |
251 /* initialize. Both lists are ordered */ | |
252 li_out = list->next; | |
253 li_ex = exclude_list->next; | |
254 | |
255 if (TRACE_BOOL(ANNOYING + 1)) { | |
256 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Filter this list "); | |
257 fd_ep_dump( 4, list ); | |
258 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Removing from list"); | |
259 fd_ep_dump( 6, exclude_list ); | |
260 } | |
261 /* Now browse both lists in parallel */ | |
262 while ((li_out != list) && (li_ex != exclude_list)) { | |
263 int cmp; | |
264 | |
265 out = (struct fd_endpoint *)li_out; | |
266 ex = (struct fd_endpoint *)li_ex; | |
267 | |
268 /* Compare the next elements families */ | |
269 if (out->sa.sa_family < ex->sa.sa_family) { | |
270 li_out = li_out->next; | |
271 continue; | |
272 } | |
273 if (out->sa.sa_family > ex->sa.sa_family) { | |
274 li_ex = li_ex->next; | |
275 continue; | |
276 } | |
277 | |
278 /* Then compare the address fields */ | |
279 switch (out->sa.sa_family) { | |
280 case AF_INET: | |
281 cmp = memcmp(&out->sin.sin_addr, &ex->sin.sin_addr, sizeof(struct in_addr)); | |
282 break; | |
283 case AF_INET6: | |
284 cmp = memcmp(&out->sin6.sin6_addr, &ex->sin6.sin6_addr, sizeof(struct in6_addr)); | |
285 break; | |
286 default: | |
287 /* Filter this out */ | |
288 cmp = 0; | |
289 } | |
290 if (cmp < 0) { | |
291 li_out = li_out->next; | |
292 continue; | |
293 } | |
294 if (cmp > 0) { | |
295 li_ex = li_ex->next; | |
296 continue; | |
297 } | |
298 | |
299 /* We remove this element then loop */ | |
300 li = li_out; | |
301 li_out = li->next; | |
302 fd_list_unlink(li); | |
303 free(li); | |
304 } | |
305 | |
306 if (TRACE_BOOL(ANNOYING + 1)) { | |
307 TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Resulting list:"); | |
308 fd_ep_dump( 4, list ); | |
309 } | |
310 return 0; | |
311 | |
312 } | |
313 | |
314 | |
315 /* Reset the given flag(s) from all items in the list */ | |
316 int fd_ep_clearflags( struct fd_list * list, uint32_t flags ) | |
317 { | |
318 struct fd_list * li; | |
319 | |
320 TRACE_ENTRY("%p %x", list, flags); | |
321 CHECK_PARAMS(list); | |
322 | |
323 for (li = list->next; li != list; li = li->next) { | |
324 struct fd_endpoint * ep = (struct fd_endpoint *)li; | |
325 ep->flags &= ~flags; | |
326 if (ep->flags == 0) { | |
327 li = li->prev; | |
328 fd_list_unlink(&ep->chain); | |
329 free(ep); | |
330 } | |
331 } | |
332 | |
333 return 0; | |
334 } | |
335 | |
336 void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep, char * suffix ) | |
337 { | |
338 if (prefix) | |
339 fd_log_debug("%s", prefix); | |
340 | |
341 sSA_DUMP_NODE_SERV( &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ); | |
342 fd_log_debug(" {%s%s%s%s}", | |
343 (ep->flags & EP_FL_CONF) ? "C" : "-", | |
344 (ep->flags & EP_FL_DISC) ? "D" : "-", | |
345 (ep->flags & EP_FL_ADV) ? "A" : "-", | |
346 (ep->flags & EP_FL_LL) ? "L" : "-", | |
347 (ep->flags & EP_FL_PRIMARY) ? "P" : "-"); | |
348 if (suffix) | |
349 fd_log_debug("%s", suffix); | |
350 } | |
351 | |
352 void fd_ep_dump( int indent, struct fd_list * eps ) | |
353 { | |
354 struct fd_list * li; | |
355 for (li = eps->next; li != eps; li = li->next) { | |
356 struct fd_endpoint * ep = (struct fd_endpoint *)li; | |
357 fd_log_debug("%*s", indent, ""); | |
358 fd_ep_dump_one( NULL, ep, "\n" ); | |
359 } | |
360 } | |
361 |