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
"Welcome to our mercurial repository"