Commit 4e393b66 authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Fix issue where the same address can be added several times in a list

parent 69709bbd
......@@ -46,16 +46,18 @@ int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t fla
sSA4 *sin;
sSA6 *sin6;
} ptr;
in_port_t * port;
int cmp = -1;
TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags);
CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) );
ptr.sa = sa;
/* Filter out a bunch of invalid addresses */
if (! (flags & EP_ACCEPTALL)) {
ptr.sa = sa;
switch (sa->sa_family) {
case AF_INET:
switch (sa->sa_family) {
case AF_INET:
if (! (flags & EP_ACCEPTALL)) {
if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr)
|| IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr)
|| IN_MULTICAST(ptr.sin->sin_addr.s_addr)
......@@ -63,32 +65,72 @@ int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t fla
|| IN_BADCLASS(ptr.sin->sin_addr.s_addr)
|| (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST))
return 0;
break;
}
port = &ptr.sin->sin_port;
break;
case AF_INET6:
case AF_INET6:
if (! (flags & EP_ACCEPTALL)) {
if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr))
return 0;
break;
}
port = &ptr.sin6->sin6_port;
break;
default:
return 0;
}
} else {
/* remove it */
flags &= ~EP_ACCEPTALL;
default:
return 0;
}
/* remove the ACCEPTALL flag */
flags &= ~EP_ACCEPTALL;
/* Search place in the list */
for (li = list->next; li != list; li = li->next) {
ep = (struct fd_endpoint *)li;
in_port_t * ep_port;
/* First, compare the address family */
if (ep->sa.sa_family < sa->sa_family)
continue;
if (ep->sa.sa_family > sa->sa_family)
break;
cmp = memcmp(&ep->ss, sa, sl);
if (cmp >= 0)
/* Then compare the address field */
switch (sa->sa_family) {
case AF_INET:
cmp = memcmp(&ep->sin.sin_addr, &ptr.sin->sin_addr, sizeof(struct in_addr));
ep_port = &ep->sin.sin_port;
break;
case AF_INET6:
cmp = memcmp(&ep->sin6.sin6_addr, &ptr.sin6->sin6_addr, sizeof(struct in6_addr));
ep_port = &ep->sin6.sin6_port;
break;
default:
/* Filter this out */
return 0;
}
if (cmp < 0)
continue;
if (cmp > 0)
break;
/* Finally compare the port, only if not 0 */
if (*port == 0)
break;
if (*ep_port == 0) {
/* save the port information in the list, and break */
*ep_port = *port;
break;
}
if (*ep_port < *port)
continue;
if (*ep_port > *port)
cmp = 1;
break;
}
if (cmp) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment