IP to Geo

IP to Geo Commit Details

Date:2016-02-17 18:15:04 (4 years 8 months ago)
Author:Grégory Soutadé
Branch:master
Commit:2456039df1ee518705bdeec8a7157b1257bc2011
Parents: 3370e83f5582759fc485d392316e3ddd76cfcf71
Message:Add IPv6 support for listening sockets

Changes:
Msrc/Makefile (1 diff)
Msrc/server.c (6 diffs)

File differences

src/Makefile
11
2
3
4
5
6
2
3
4
5
6
77
88
99
BIN_DIR=../bin
SRCS = ip_to_geo.c test.c cmdline.c server.c
TARGET = $(BIN_DIR)/ip_to_geo
CFLAGS = -Wall
LDFLAGS= -lpthread
BIN_DIR =../bin
SRCS = ip_to_geo.c test.c cmdline.c server.c
TARGET = $(BIN_DIR)/ip_to_geo
CFLAGS = -Wall
LDFLAGS = -lpthread
ifneq ($(DEBUG),)
CFLAGS += -ggdb -O0
src/server.c
2525
2626
2727
28
2829
2930
3031
......
4647
4748
4849
50
51
4952
5053
5154
......
6972
7073
7174
72
75
76
7377
7478
7579
7680
81
82
7783
7884
79
85
86
87
8088
8189
8290
......
400408
401409
402410
403
404
411
412
405413
406414
407415
408
409
410
416
417
418
419
420
421
422
423
424
425
426
427
428
411429
412
430
431
413432
414
415
433
416434
417435
418436
419
420
421
422
437
438
423439
424
425
440
441
442
443
444
426445
427446
428
447
429448
430449
431
432
433
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
434475
435
436
437
438
439
440
441
476
477
478
479
480
481
482
442483
443
444
445
446
447
448
484
485
486
487
488
489
490
449491
450492
493
494
495
451496
452497
453498
......
497542
498543
499544
545
500546
501547
502548
......
513559
514560
515561
516
517
518
562
563
564
519565
520566
521
567
522568
523569
524
525
526
527
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
528610
529611
530
612
613
614
531615
532616
533617
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <syslog.h>
#include <signal.h>
#define WAIT_TIME 100
#define MAX_WAIT_TIME 500
#define MAX_LISTENING_SOCKETS 16
typedef struct {
int socket;
time_t timeout; // in µs
static pthread_mutex_t s_fastmutex = PTHREAD_MUTEX_INITIALIZER;
static thread_ctx_t* s_last_thread = NULL;
static int s_server_socket = -1;
static int s_server_sockets[MAX_LISTENING_SOCKETS];
static int s_nb_server_sockets = 0;
static int s_stop = 0;
void sigint(int sig)
{
int i;
syslog(LOG_WARNING, "signal received, stopping threads");
s_stop = 1;
shutdown(s_server_socket, SHUT_RDWR);
for (i=0; i<s_nb_server_sockets; i++)
shutdown(s_server_sockets[i], SHUT_RDWR);
}
static int check_request(request_t* req)
int daemonize(struct gengetopt_args_info* params)
{
int ret;
struct sockaddr_in sockaddr;
int ret, i;
struct sockaddr_in6 sockaddr;
socklen_t sockaddr_len;
int new_socket;
void* thread_ret;
// Should have both ipv4 & ipv6
s_server_socket = socket(AF_INET, SOCK_STREAM, 0); // Should have both TCP & UDP
struct addrinfo hints;
struct addrinfo *result, *rp;
char buffer[64];
int on;
struct pollfd pollfds[MAX_LISTENING_SOCKETS];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
hints.ai_flags = (params->bind_ip_given)?0:AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
snprintf(buffer, sizeof(buffer), "%d", params->port_arg);
if (!s_server_socket)
ret = getaddrinfo(params->bind_ip_arg, buffer, &hints, &result);
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Unable to create socket (%m)\n");
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET; // Should detect interface type (v4 or v6)
sockaddr.sin_port = htons(params->port_arg);
if (params->bind_ip_given)
for (rp=result; rp && s_nb_server_sockets < MAX_LISTENING_SOCKETS;
rp=rp->ai_next, s_nb_server_sockets++)
{
ret = inet_aton(params->bind_ip_arg, &sockaddr.sin_addr);
if (ret)
new_socket = socket(rp->ai_family,
rp->ai_socktype,
rp->ai_protocol); // Should have both TCP & UDP
if (!new_socket)
{
if (!params->quiet_flag)
fprintf(stderr, "Error with bind address %s (%m)\n", params->bind_ip_arg);
fprintf(stderr, "Unable to create socket (%m)\n");
return -1;
}
}
else
sockaddr.sin_addr.s_addr = INADDR_ANY;
s_server_sockets[s_nb_server_sockets] = new_socket;
pollfds[s_nb_server_sockets].fd = new_socket;
pollfds[s_nb_server_sockets].events = POLLIN|POLL_ERR_MASK;
on=1; setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (rp->ai_family == AF_INET6)
{
on=1; setsockopt(new_socket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
}
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin6_family = rp->ai_family; // Should detect interface type (v4 or v6)
sockaddr.sin6_port = htons(params->port_arg);
if (params->bind_ip_given)
{
ret = inet_pton(rp->ai_family, params->bind_ip_arg, &sockaddr.sin6_addr);
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Error with bind address %s (%m)\n", params->bind_ip_arg);
return -1;
}
}
else
sockaddr.sin6_addr = in6addr_any;
ret = bind(s_server_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Unable to bind (%m)\n");
return -2;
}
ret = bind(new_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Unable to bind (%m)\n");
return -2;
}
ret = listen(s_server_socket, 0);
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Unable to listen (%m)\n");
return -3;
ret = listen(new_socket, 0);
if (ret)
{
if (!params->quiet_flag)
fprintf(stderr, "Unable to listen (%m)\n");
return -3;
}
}
if (rp)
fprintf(stderr, "Warning, max listening sockets reached !!\n");
if (!params->no_background_flag)
{
ret = daemon(0, 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
seccomp_rule_add(seccomp_ctx, SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0);
while (!s_stop)
{
sockaddr_len = sizeof(sockaddr);
new_socket = accept(s_server_socket, (struct sockaddr *) &sockaddr, &sockaddr_len);
if (new_socket < 0)
ret = poll(pollfds, s_nb_server_sockets, 1000);
if (ret < 0)
{
if (!s_stop)
syslog(LOG_ERR, "accept error (%m), exiting");
syslog(LOG_ERR, "main poll err %d", ret);
break;
}
if (!params->quiet_flag)
syslog(LOG_INFO, "new connection from %s, socket %d",
inet_ntoa(sockaddr.sin_addr), new_socket);
fill_new_socket(params, new_socket);
if (ret == 0) continue; // timeout
for (i=0; i<s_nb_server_sockets; i++)
{
if (pollfds[i].revents & POLL_ERR_MASK)
{
if (!s_stop)
syslog(LOG_ERR, "Error with main socket %d (%m)", s_server_sockets[i]);
close (s_server_sockets[i]);
continue;
}
if (!(pollfds[i].revents & POLLIN)) continue;
sockaddr_len = sizeof(sockaddr);
new_socket = accept(s_server_sockets[i], (struct sockaddr *) &sockaddr, &sockaddr_len);
if (new_socket < 0)
{
if (!s_stop)
syslog(LOG_ERR, "accept error (%m), exiting");
goto end;
}
if (!params->quiet_flag)
{
switch(sockaddr.sin6_family)
{
case AF_INET:
inet_ntop(AF_INET, &((struct sockaddr_in *)&sockaddr)->sin_addr, buffer, sizeof(buffer));
break;
case AF_INET6:
inet_ntop(AF_INET6, &sockaddr.sin6_addr, buffer, sizeof(buffer));
break;
}
/* inet_ntop(sockaddr.sin6_family, &sockaddr.sin6_addr, buffer, sockaddr_len); */
syslog(LOG_INFO, "new connection from %s, socket %d", buffer, new_socket);
}
fill_new_socket(params, new_socket);
}
}
close(s_server_socket);
end:
for (i=0; i<s_nb_server_sockets; i++)
close(s_server_sockets[i]);
while (s_last_thread)
{

Archive Download the corresponding diff file

Branches

Tags