4242#include " connection.h"
4343#include " Configuration.h"
4444
45+ #ifndef IP6T_SO_ORIGINAL_DST
46+ #define IP6T_SO_ORIGINAL_DST 80
47+ #endif
48+
4549extern Configuration* configuration;
4650
4751struct timeout_entry
@@ -130,9 +134,9 @@ static void conn_close(int fd, int epfd, struct conn_state* cs, int* nactive)
130134static void do_accept (int listenfd, int epfd, struct conn_state * cs,
131135 int maxfd, Configuration* conf, int * nactive, timeout_heap& heap)
132136{
133- struct sockaddr_in peer;
137+ struct sockaddr_storage peer;
134138 socklen_t peerlen;
135- struct sockaddr_in orig;
139+ struct sockaddr_storage orig;
136140 socklen_t origlen;
137141 int fd;
138142 uint64_t now = mono_now ();
@@ -145,6 +149,29 @@ static void do_accept(int listenfd, int epfd, struct conn_state* cs,
145149 {
146150 if (errno == EAGAIN || errno == EWOULDBLOCK )
147151 break ;
152+ if (errno == EMFILE || errno == ENFILE )
153+ {
154+ int victim = -1 ;
155+ while (!heap.empty ())
156+ {
157+ const timeout_entry& top = heap.top ();
158+ int v = top.fd ;
159+ uint32_t gen = top.gen ;
160+ heap.pop ();
161+
162+ if (cs[v].phase != 0 && cs[v].gen == gen)
163+ {
164+ victim = v;
165+ break ;
166+ }
167+ }
168+ if (victim >= 0 )
169+ {
170+ conn_close (victim, epfd, cs, nactive);
171+ continue ;
172+ }
173+ // If no connections to evict, we have a leak or something else took fds. Break to avoid spin.
174+ }
148175 perror (" accept" );
149176 break ;
150177 }
@@ -156,16 +183,17 @@ static void do_accept(int listenfd, int epfd, struct conn_state* cs,
156183 * free a slot for the next accept() call. */
157184 close (fd);
158185 int victim = -1 ;
159- uint64_t earliest = UINT64_MAX ;
160- for (int v = 0 ; v < maxfd; v++)
186+ while (!heap.empty ())
161187 {
162- if (cs[v].phase == 0 )
163- continue ;
164- uint64_t exp = cs[v].t_accept + cs[v].t_timeout ;
165- if (exp < earliest)
188+ const timeout_entry& top = heap.top ();
189+ int v = top.fd ;
190+ uint32_t gen = top.gen ;
191+ heap.pop ();
192+
193+ if (cs[v].phase != 0 && cs[v].gen == gen)
166194 {
167- earliest = exp;
168195 victim = v;
196+ break ;
169197 }
170198 }
171199 if (victim >= 0 )
@@ -177,11 +205,26 @@ static void do_accept(int listenfd, int epfd, struct conn_state* cs,
177205
178206 /* get the port the scanner was actually aiming for */
179207 origlen = sizeof (orig);
180- uint16_t dport = DEFAULT_PORT ;
181- if (getsockopt (fd, SOL_IP , SO_ORIGINAL_DST ,
182- (struct sockaddr *)&orig, &origlen) == 0 )
208+ uint16_t dport = conf->getPort () ? conf->getPort () : DEFAULT_PORT ;
209+
210+ if (getsockopt (fd, SOL_IP , SO_ORIGINAL_DST , &orig, &origlen) == 0 )
211+ {
212+ dport = ntohs (((struct sockaddr_in *)&orig)->sin_port );
213+ }
214+ else if (getsockopt (fd, SOL_IPV6 , IP6T_SO_ORIGINAL_DST , &orig, &origlen) == 0 )
215+ {
216+ dport = ntohs (((struct sockaddr_in6 *)&orig)->sin6_port );
217+ }
218+ else
183219 {
184- dport = ntohs (orig.sin_port );
220+ origlen = sizeof (orig);
221+ if (getsockname (fd, (struct sockaddr *)&orig, &origlen) == 0 )
222+ {
223+ if (orig.ss_family == AF_INET )
224+ dport = ntohs (((struct sockaddr_in *)&orig)->sin_port );
225+ else if (orig.ss_family == AF_INET6 )
226+ dport = ntohs (((struct sockaddr_in6 *)&orig)->sin6_port );
227+ }
185228 }
186229
187230 /* look up the banner for this port */
0 commit comments