96 lines
2.3 KiB
C
96 lines
2.3 KiB
C
/* Copyright (C) 2010 Tony Garnock-Jones. All rights reserved. */
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/uio.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <fcntl.h>
|
|
#include <sys/wait.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
|
|
typedef unsigned char u_char;
|
|
#include <event.h>
|
|
|
|
#include "cmsg_private.h"
|
|
#include "relay.h"
|
|
|
|
static struct event accept_event;
|
|
|
|
void get_addr_name(char *namebuf, size_t buflen, struct sockaddr_in const *sin) {
|
|
unsigned char *addr = (unsigned char *) &sin->sin_addr.s_addr;
|
|
struct hostent *h = gethostbyaddr(addr, 4, AF_INET);
|
|
|
|
if (h == NULL) {
|
|
snprintf(namebuf, buflen, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
|
|
} else {
|
|
snprintf(namebuf, buflen, "%s", h->h_name);
|
|
}
|
|
}
|
|
|
|
void endpoint_name(struct sockaddr_in const *peername, cmsg_bytes_t result) {
|
|
char name[256];
|
|
get_addr_name(name, sizeof(name), peername);
|
|
snprintf((char *) result.bytes, result.len, "%s:%d", name, ntohs(peername->sin_port));
|
|
}
|
|
|
|
static void accept_connection(int servfd, short what, void *arg) {
|
|
struct sockaddr_in s;
|
|
socklen_t addrlen = sizeof(s);
|
|
int fd = accept(servfd, (struct sockaddr *) &s, &addrlen);
|
|
|
|
if (fd == -1) {
|
|
if (errno != EAGAIN && errno != EINTR) {
|
|
warn("accept: errno %d (%s)\n", errno, strerror(errno));
|
|
}
|
|
return;
|
|
}
|
|
|
|
start_relay(&s, fd);
|
|
}
|
|
|
|
void start_net(int listen_port) {
|
|
int servfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
struct sockaddr_in s;
|
|
|
|
if (servfd < 0) {
|
|
die("Could not open listen socket.\n");
|
|
}
|
|
|
|
s.sin_family = AF_INET;
|
|
s.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
s.sin_port = htons(listen_port);
|
|
|
|
{
|
|
int i = 1;
|
|
setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); // don't care if this fails
|
|
}
|
|
|
|
if (bind(servfd, (struct sockaddr *) &s, sizeof(s)) < 0) {
|
|
die("Could not bind listen socket.\n");
|
|
}
|
|
|
|
if (listen(servfd, 5) < 0) {
|
|
int savedErrno = errno;
|
|
die("Could not listen on listen socket (errno %d: %s).\n",
|
|
savedErrno, strerror(savedErrno));
|
|
}
|
|
|
|
event_set(&accept_event, servfd, EV_READ | EV_PERSIST, accept_connection, NULL);
|
|
if (event_add(&accept_event, NULL) == -1) {
|
|
die("Could not add accept_event.");
|
|
}
|
|
|
|
info("Accepting connections on port %d.\n", listen_port);
|
|
}
|