proper IPv6 handling
Costa Tsaousis (ktsaou) committed
Mar 25, 2015 at 23:33 UTC
222f3dd7a3b910df9cd703f69fcf6b49b229a45d
3 files changed
+50
-22
src/web_client.c
+42
-18
@@ -5,9 +5,10 @@
5
#include <arpa/inet.h>
6
7
#include "global_statistics.h"
8
-#include "web_client.h"
8
#include "log.h"
9
10
+#include "web_client.h"
11
+
12
#define INITIAL_WEB_DATA_LENGTH 65536
13
14
struct web_client *web_clients = NULL;
@@ -16,7 +17,6 @@ unsigned long long web_clients_count = 0;
17
struct web_client *web_client_create(int listener)
18
{
19
struct web_client *w;
19
- socklen_t addrlen;
20
21
w = calloc(1, sizeof(struct web_client));
22
if(!w) {
@@ -27,22 +27,46 @@ struct web_client *web_client_create(int listener)
27
w->id = ++web_clients_count;
28
w->mode = WEB_CLIENT_MODE_NORMAL;
29
30
- addrlen = sizeof(w->clientaddr);
31
- w->ifd = accept(listener, (struct sockaddr *)&w->clientaddr, &addrlen);
32
- if (w->ifd == -1) {
33
- error("%llu: Cannot accept new incoming connection.", w->id);
34
- free(w);
35
- return NULL;
36
- }
37
- w->ofd = w->ifd;
38
-
39
- strncpy(w->client_ip, inet_ntoa(w->clientaddr.sin_addr), 100);
40
- w->client_ip[100] = '\0';
41
-
42
- debug(D_WEB_CLIENT_ACCESS, "%llu: New web client from %s on socket %d.", w->id, w->client_ip, w->ifd);
43
-
30
{
45
- int flag = 1;
31
+ struct sockaddr *sadr;
32
+ socklen_t addrlen;
33
+
34
+ sadr = (struct sockaddr*) &w->clientaddr;
35
+ addrlen = sizeof(w->clientaddr);
36
+
37
+ w->ifd = accept(listener, sadr, &addrlen);
38
+ if (w->ifd == -1) {
39
+ error("%llu: Cannot accept new incoming connection.", w->id);
40
+ free(w);
41
+ return NULL;
42
+ }
43
+ w->ofd = w->ifd;
44
+
45
+ if(getnameinfo(sadr, addrlen, w->client_ip, NI_MAXHOST, w->client_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
46
+ error("Cannot getnameinfo() on received client connection.");
47
+ strncpy(w->client_ip, "UNKNOWN", NI_MAXHOST);
48
+ strncpy(w->client_port, "UNKNOWN", NI_MAXSERV);
49
+ }
50
+ w->client_ip[NI_MAXHOST] = '\0';
51
+ w->client_port[NI_MAXSERV] = '\0';
52
+
53
+ switch(sadr->sa_family) {
54
+ case AF_INET:
55
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
56
+ break;
57
+ case AF_INET6:
58
+ if(strncmp(w->client_ip, "::ffff:", 7) == 0) {
59
+ strcpy(w->client_ip, &w->client_ip[7]);
60
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
61
+ }
62
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv6 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
63
+ break;
64
+ default:
65
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New UNKNOWN web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
66
+ break;
67
+ }
68
+
69
+ int flag = 1;
70
if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0) error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
71
}
72
@@ -68,7 +92,7 @@ struct web_client *web_client_free(struct web_client *w)
92
{
93
struct web_client *n = w->next;
94
71
- debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s.", w->id, inet_ntoa(w->clientaddr.sin_addr));
95
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
96
97
if(w->prev) w->prev->next = w->next;
98
if(w->next) w->next->prev = w->prev;
src/web_client.h
+6
-2
@@ -4,6 +4,7 @@
4
#include <sys/socket.h>
5
#include <netinet/in.h>
6
#include <arpa/inet.h>
7
+#include <netdb.h>
8
9
#include "web_buffer.h"
10
@@ -19,7 +20,10 @@
20
21
struct web_client {
22
unsigned long long id;
22
- char client_ip[101];
23
+
24
+ char client_ip[NI_MAXHOST+1];
25
+ char client_port[NI_MAXSERV+1];
26
+
27
char last_url[URL_MAX+1];
28
29
struct timeval tv_in, tv_ready;
@@ -27,7 +31,7 @@ struct web_client {
31
int mode;
32
int keepalive;
33
30
- struct sockaddr_in clientaddr;
34
+ struct sockaddr_storage clientaddr;
35
36
pthread_t thread; // the thread servicing this client
37
int obsolete; // if set to 1, the listener will remove this client
src/web_server.c
+2
-2
@@ -1296,7 +1296,7 @@ void *socket_listen_main(void *ptr)
1296
w->obsolete = 1;
1297
}
1298
1299
- log_access("%llu: %s connected", w->id, w->client_ip);
1299
+ log_access("%llu: %s port %s connected", w->id, w->client_ip, w->client_port);
1300
}
1301
else debug(D_WEB_CLIENT, "LISTENER: select() didn't do anything.");
1302
@@ -1308,7 +1308,7 @@ void *socket_listen_main(void *ptr)
1308
// cleanup unused clients
1309
for(w = web_clients; w ; w = w?w->next:NULL) {
1310
if(w->obsolete) {
1311
- log_access("%llu: %s disconnected", w->id, w->client_ip);
1311
+ log_access("%llu: %s port %s disconnected", w->id, w->client_ip, w->client_port);
1312
debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
1313
// pthread_join(w->thread, NULL);
1314
w = web_client_free(w);