# HG changeset patch # User Sebastien Decugis # Date 1278317086 -32400 # Node ID 7337305ee51e56478dd1b53478c581056ecfeeec # Parent 41e3c2a3721ce898e18b20f8c4340bb9db3fd813 Workaround to prevent peer connecting to itself (ipv6 local addresses) diff -r 41e3c2a3721c -r 7337305ee51e freeDiameter/endpoints.c --- a/freeDiameter/endpoints.c Mon Jul 05 16:21:22 2010 +0900 +++ b/freeDiameter/endpoints.c Mon Jul 05 17:04:46 2010 +0900 @@ -192,6 +192,68 @@ return 0; } +/* Remove any endpoint from the exclude list in the list */ +int fd_ep_filter_list( struct fd_list * list, struct fd_list * exclude_list ) +{ + struct fd_list * li_out, *li_ex, *li; + struct fd_endpoint * out, * ex; + + TRACE_ENTRY("%p %p", list, exclude_list); + CHECK_PARAMS(list && exclude_list); + + /* initialize. Both lists are ordered */ + li_out = list->next; + li_ex = exclude_list; + + /* Now browse both lists in parallel */ + while ((li_out != list) && (li_ex != exclude_list)) { + int cmp; + + out = (struct fd_endpoint *)li_out; + ex = (struct fd_endpoint *)li_ex; + + /* Compare the next elements families */ + if (out->sa.sa_family < ex->sa.sa_family) { + li_out = li_out->next; + continue; + } + if (out->sa.sa_family > ex->sa.sa_family) { + li_ex = li_ex->next; + continue; + } + + /* Then compare the address fields */ + switch (out->sa.sa_family) { + case AF_INET: + cmp = memcmp(&out->sin.sin_addr, &ex->sin.sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + cmp = memcmp(&out->sin6.sin6_addr, &ex->sin6.sin6_addr, sizeof(struct in6_addr)); + break; + default: + /* Filter this out */ + cmp = 0; + } + if (cmp < 0) { + li_out = li_out->next; + continue; + } + if (cmp > 0) { + li_ex = li_ex->next; + continue; + } + + /* We remove this element then loop */ + li = li_out; + li_out = li->next; + fd_list_unlink(li); + free(li); + } + return 0; + +} + + /* Reset the given flag(s) from all items in the list */ int fd_ep_clearflags( struct fd_list * list, uint32_t flags ) { diff -r 41e3c2a3721c -r 7337305ee51e freeDiameter/p_cnx.c --- a/freeDiameter/p_cnx.c Mon Jul 05 16:21:22 2010 +0900 +++ b/freeDiameter/p_cnx.c Mon Jul 05 17:04:46 2010 +0900 @@ -117,6 +117,9 @@ AF_INET)); } + /* Remove any local address that would be here, it should not happen but it does sometimes... */ + CHECK_FCT( fd_ep_filter_list(&peer->p_hdr.info.pi_endpoints, &fd_g_config->cnf_endpoints) ); + /* Now check we have at least one address to attempt */ if (FD_IS_LIST_EMPTY(&peer->p_hdr.info.pi_endpoints)) { fd_log_debug("No address %savailable to connect to peer '%s', aborting\n", peer->p_hdr.info.config.pic_flags.pro3 ? "in the configured family " : "", peer->p_hdr.info.pi_diamid);