Mercurial > hg > freeDiameter
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)) ); |