comparison freeDiameter/endpoints.c @ 210:2b5027949f85

Fix issue where the same address can be added several times in a list
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 16 Feb 2010 16:33:03 +0900
parents a32646b7e7d7
children 5df55136361b
comparison
equal deleted inserted replaced
209:b9f48f2f2a22 210:2b5027949f85
44 union { 44 union {
45 sSA * sa; 45 sSA * sa;
46 sSA4 *sin; 46 sSA4 *sin;
47 sSA6 *sin6; 47 sSA6 *sin6;
48 } ptr; 48 } ptr;
49 in_port_t * port;
49 int cmp = -1; 50 int cmp = -1;
50 51
51 TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags); 52 TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags);
52 CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) ); 53 CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) );
53 54
55 ptr.sa = sa;
56
54 /* Filter out a bunch of invalid addresses */ 57 /* Filter out a bunch of invalid addresses */
55 if (! (flags & EP_ACCEPTALL)) { 58 switch (sa->sa_family) {
56 ptr.sa = sa; 59 case AF_INET:
57 switch (sa->sa_family) { 60 if (! (flags & EP_ACCEPTALL)) {
58 case AF_INET:
59 if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr) 61 if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr)
60 || IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr) 62 || IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr)
61 || IN_MULTICAST(ptr.sin->sin_addr.s_addr) 63 || IN_MULTICAST(ptr.sin->sin_addr.s_addr)
62 || IN_EXPERIMENTAL(ptr.sin->sin_addr.s_addr) 64 || IN_EXPERIMENTAL(ptr.sin->sin_addr.s_addr)
63 || IN_BADCLASS(ptr.sin->sin_addr.s_addr) 65 || IN_BADCLASS(ptr.sin->sin_addr.s_addr)
64 || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) 66 || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST))
65 return 0; 67 return 0;
66 break; 68 }
67 69 port = &ptr.sin->sin_port;
68 case AF_INET6: 70 break;
71
72 case AF_INET6:
73 if (! (flags & EP_ACCEPTALL)) {
69 if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr) 74 if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr)
70 || IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr) 75 || IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr)
71 || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr) 76 || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr)
72 || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr) 77 || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr)
73 || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) 78 || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr))
74 return 0; 79 return 0;
80 }
81 port = &ptr.sin6->sin6_port;
82 break;
83
84 default:
85 return 0;
86 }
87
88 /* remove the ACCEPTALL flag */
89 flags &= ~EP_ACCEPTALL;
90
91 /* Search place in the list */
92 for (li = list->next; li != list; li = li->next) {
93 ep = (struct fd_endpoint *)li;
94 in_port_t * ep_port;
95
96 /* First, compare the address family */
97 if (ep->sa.sa_family < sa->sa_family)
98 continue;
99 if (ep->sa.sa_family > sa->sa_family)
100 break;
101
102 /* Then compare the address field */
103 switch (sa->sa_family) {
104 case AF_INET:
105 cmp = memcmp(&ep->sin.sin_addr, &ptr.sin->sin_addr, sizeof(struct in_addr));
106 ep_port = &ep->sin.sin_port;
75 break; 107 break;
76 108 case AF_INET6:
109 cmp = memcmp(&ep->sin6.sin6_addr, &ptr.sin6->sin6_addr, sizeof(struct in6_addr));
110 ep_port = &ep->sin6.sin6_port;
111 break;
77 default: 112 default:
113 /* Filter this out */
78 return 0; 114 return 0;
79 } 115 }
80 } else { 116 if (cmp < 0)
81 /* remove it */ 117 continue;
82 flags &= ~EP_ACCEPTALL; 118 if (cmp > 0)
83 } 119 break;
84 120
85 /* Search place in the list */ 121 /* Finally compare the port, only if not 0 */
86 for (li = list->next; li != list; li = li->next) { 122 if (*port == 0)
87 ep = (struct fd_endpoint *)li; 123 break;
88 124 if (*ep_port == 0) {
89 cmp = memcmp(&ep->ss, sa, sl); 125 /* save the port information in the list, and break */
90 if (cmp >= 0) 126 *ep_port = *port;
91 break; 127 break;
128 }
129 if (*ep_port < *port)
130 continue;
131 if (*ep_port > *port)
132 cmp = 1;
133 break;
92 } 134 }
93 135
94 if (cmp) { 136 if (cmp) {
95 /* new item to be added */ 137 /* new item to be added */
96 CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) ); 138 CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) );
"Welcome to our mercurial repository"