diff --git a/discardd.c b/discardd.c index 01b2e1b..fd2d51e 100644 --- a/discardd.c +++ b/discardd.c @@ -12,10 +12,101 @@ */ #include +#include #include #include +#include #include +#include +#include +#include + +#define nelems(_a) (sizeof((_a)) / sizeof((_a)[0])) + +static void +print_listen_address(const struct sockaddr *sa, socklen_t salen, int family) +{ + char host[NI_MAXHOST], serv[NI_MAXSERV]; + int error; + int flags = NI_NUMERICHOST | NI_NUMERICSERV; + + error = getnameinfo(sa, salen, host, NI_MAXHOST, serv, NI_MAXSERV, + flags); + if (error) { + warnx("%s", gai_strerror(error)); + } else { + if (family == AF_INET6) + fprintf(stderr, "Listening on [%s]:%s\n", host, serv); + else + fprintf(stderr, "Listening on %s:%s\n", host, serv); + } +} + +static void +listen_sock_setup(const char *port, int socktype, int *s, size_t *maxsocks) +{ + struct addrinfo hints, *res, *res0; + const char *cause = NULL; + int error, save_errno, nsock; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = socktype; + hints.ai_flags = AI_PASSIVE; + + error = getaddrinfo(NULL, port, &hints, &res0); + if (error) + errx(1, "%s", gai_strerror(error)); + + nsock = 0; + for (res = res0; res && nsock < *maxsocks; res = res->ai_next) { + s[nsock] = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (s[nsock] == -1) { + cause = "socket"; + continue; + } + + if (bind(s[nsock], res->ai_addr, res->ai_addrlen) == -1) { + cause = "bind"; + save_errno = errno; + close(s[nsock]); + errno = save_errno; + continue; + } + + if (listen(s[nsock], 5) == -1) { + cause = "listen"; + continue; + } + + print_listen_address(res->ai_addr, res->ai_addrlen, + res->ai_family); + nsock++; + } + if (nsock == 0) + err(1, "%s", cause); + freeaddrinfo(res0); + + *maxsocks = nsock; +} + +static void +handle_tcp(const char *port) +{ + int s[8]; + size_t nsocks = nelems(s); + + listen_sock_setup(port, SOCK_STREAM, s, &nsocks); +} + +static void +handle_udp(const char *port) +{ + errx(1, "UDP unimplemented"); +} + static void usage(void) { @@ -54,9 +145,9 @@ main(int argc, char *argv[]) if (do_tcp && do_udp) errx(1, "-t and -u are mutually exclusive"); if (do_udp) - errx(1, "UDP unimplemented"); + handle_udp(port); if (do_tcp) - errx(1, "TCP unimplemented"); + handle_tcp(port); return 0; }