*** empty log message ***

This commit is contained in:
christos 2015-01-19 18:52:55 +00:00
parent 6c408a1c40
commit 474e893b1c
8 changed files with 385 additions and 155 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: blacklist.h,v 1.1 2015/01/19 18:52:55 christos Exp $ */
/* $NetBSD: blacklist.h,v 1.2 2015/01/19 19:02:35 christos Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@ -43,6 +43,7 @@ typedef struct blacklist *bl_t;
__BEGIN_DECLS
bl_t bl_create(void);
int bl_getfd(bl_t);
int bl_send(bl_t, bl_type_t, int, int, const char *);
void bl_destroy(bl_t);

View File

@ -1,6 +1,6 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: blacklistd.c,v 1.2 2015/01/19 18:52:55 christos Exp $");
__RCSID("$NetBSD: blacklistd.c,v 1.3 2015/01/19 19:02:35 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
@ -47,7 +47,8 @@ sighup(int n)
static __dead void
usage(void)
{
fprintf(stderr, "Usage: %s -d [-c <config>]\n", getprogname());
fprintf(stderr, "Usage: %s -d [-c <config>] [-s <sockpath>]\n",
getprogname());
exit(EXIT_FAILURE);
}
@ -111,7 +112,7 @@ process(bl_t bl)
rfd = bi->bi_fd[1];
rsl = sizeof(rss);
if (getpeername(rfd, (void *)&rss, &rsl) == -1) {
(*bl->b_fun)(LOG_ERR, "getsockname failed (%m)");
(*lfun)(LOG_ERR, "getsockname failed (%m)");
goto out;
}
sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
@ -163,11 +164,11 @@ main(int argc, char *argv[])
}
bl = bl_create2(true, spath, lfun);
if (bl == NULL || !bl->b_connected)
if (bl == NULL || !bl_isconnected(bl))
return EXIT_FAILURE;
struct pollfd pfd;
pfd.fd = bl->b_fd;
pfd.fd = bl_getfd(bl);
pfd.events = POLLIN;
for (;;) {
if (rconf) {

View File

@ -1,3 +1,35 @@
/* $NetBSD: conf.h,v 1.2 2015/01/19 19:02:35 christos Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CONF_H
#define _CONF_H
struct conf {
int c_port;
@ -8,5 +40,9 @@ struct conf {
int c_duration;
};
__BEGIN_DECLS
void parseconf(const char *);
const struct conf *findconf(bl_info_t *);
__END_DECLS
#endif /* _CONF_H */

View File

@ -1,16 +1,6 @@
struct conf *conf;
size_t nconf;
int debug;
typedef struct {
uint32_t bl_len;
uint32_t bl_version;
uint32_t bl_type;
char bl_data[];
} bl_message_t;
struct blacklist {
int b_fd;
int b_connected;
};
#define BL_VERSION 1
void (*lfun)(int, const char *, ...);

View File

@ -1,17 +1,70 @@
/* $NetBSD: bl.h,v 1.4 2015/01/19 18:52:55 christos Exp $ */
#include <stdbool.h>
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BL_H
#define _BL_H
typedef enum {
BL_INVALID,
BL_ADD,
} bl_type_t;
#include "blacklist.h"
struct sockcred;
typedef struct {
bl_type_t bi_type;
int *bi_fd;
struct sockcred *bi_cred;
char bi_msg[1024];
} bl_info_t;
typedef struct blacklist *bl_t;
bl_t bl_create(bool);
void bl_destroy(bl_t);
int bl_send(bl_t, bl_type_t, int, int, const char *);
int bl_recv(bl_t, bl_type_t *, int *, int *, char *, size_t);
__BEGIN_DECLS
bl_t bl_create2(bool, const char *, void (*)(int, const char *, ...));
bl_info_t *bl_recv(bl_t);
__END_DECLS
#define _PATH_BLSOCK "/tmp/blsock"
#define _PATH_BLCONF "/etc/blacklist.conf"
#define _PATH_BLCONF "/etc/blacklistd/conf"
#endif /* _BL_H */
typedef struct {
uint32_t bl_len;
uint32_t bl_version;
uint32_t bl_type;
char bl_data[];
} bl_message_t;
struct blacklist {
int b_fd;
int b_connected;
const char *b_path;
void (*b_fun)(int, const char *, ...);
bl_info_t b_info;
};
#define BL_VERSION 1

View File

@ -1,8 +1,42 @@
/* $NetBSD: bl.c,v 1.4 2015/01/19 18:52:55 christos Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: bl.c,v 1.4 2015/01/19 18:52:55 christos Exp $");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <fcntl.h>
@ -11,23 +45,34 @@
#include <stdbool.h>
#include "bl.h"
#include "internal.h"
static void
bl_reset(bl_t b)
{
close(b->b_fd);
b->b_fd = -1;
b->b_connected = false;
}
static int
bl_init(bl_t b, bool srv)
{
static int one = 1;
/* AF_UNIX address of local logger */
static const struct sockaddr_un sun = {
struct sockaddr_un sun = {
.sun_family = AF_LOCAL,
.sun_len = sizeof(sun),
.sun_path = _PATH_BLSOCK,
};
strlcpy(sun.sun_path, b->b_path, sizeof(sun.sun_path));
if (srv)
(void)unlink(b->b_path);
if (b->b_fd == -1) {
b->b_fd = socket(PF_LOCAL,
SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0);
if (b->b_fd == -1) {
syslog(LOG_ERR, "%s: socket failed (%m)", __func__);
(*b->b_fun)(LOG_ERR, "%s: socket failed (%m)",
__func__);
return 0;
}
}
@ -37,63 +82,81 @@ bl_init(bl_t b, bool srv)
if ((srv ? bind : connect)(b->b_fd, (const void *)&sun,
(socklen_t)sizeof(sun)) == -1) {
syslog(LOG_ERR, "%s: %s failed (%m)", __func__,
(*b->b_fun)(LOG_ERR, "%s: %s failed (%m)", __func__,
srv ? "bind" : "connect");
return -1;
goto out;
}
b->b_connected = true;
if (setsockopt(b->b_fd, 0, LOCAL_CREDS,
&one, sizeof(one)) == -1) {
(*b->b_fun)(LOG_ERR, "%s: setsockopt LOCAL_CREDS "
"failed (%m)", __func__);
goto out;
}
if (srv)
if (listen(b->b_fd, 5) == -1) {
syslog(LOG_ERR, "%s: listen failed (%m)", __func__);
close(b->b_fd);
b->b_fd = -1;
b->b_connected = false;
(*b->b_fun)(LOG_ERR, "%s: listen failed (%m)",
__func__);
goto out;
}
return 0;
out:
bl_reset(b);
return -1;
}
bl_t
bl_create(bool srv)
bl_create2(bool srv, const char *path, void (*fun)(int, const char *, ...))
{
bl_t b = malloc(sizeof(*b));
if (b == NULL) {
syslog(LOG_ERR, "%s: malloc failed (%m)", __func__);
return NULL;
}
bl_info_t *bi;
if (b == NULL)
goto out;
bi = &b->b_info;
bi->bi_fd = malloc(2 * sizeof(int));
if (bi->bi_fd == NULL)
goto out1;
bi->bi_cred = malloc(SOCKCREDSIZE(NGROUPS_MAX));
if (bi->bi_cred == NULL)
goto out2;
b->b_fun = fun == NULL ? syslog : fun;
b->b_fd = -1;
b->b_path = strdup(path ? path : _PATH_BLSOCK);
if (b->b_path == NULL)
goto out3;
b->b_connected = false;
bl_init(b, srv);
return b;
out3:
free(bi->bi_cred);
out2:
free(bi->bi_fd);
out1:
free(b);
out:
(*fun)(LOG_ERR, "%s: malloc failed (%m)", __func__);
return NULL;
}
bl_t
bl_create(void)
{
return bl_create2(false, NULL, NULL);
}
void
bl_destroy(bl_t b)
{
close(b->b_fd);
bl_reset(b);
free(__UNCONST(b->b_path));
free(b->b_info.bi_cred);
free(b->b_info.bi_fd);
free(b);
}
#if 0
static int
bl_post(bl_t b, const struct sockaddr_storage *lss,
const struct sockaddr_storage *pss, bl_event_t e, const char *ctx)
{
struct sockaddr_storage lss, pss;
socklen_t lsl, psl;
lsl = sizeof(lss);
psl = sizeof(pss);
if (getsockname(lfd, &lss, &lsl) == -1) {
syslog(LOG_ERR, "%s: getsockname failed (%m)", __func__);
return -1;
}
if (getpeername(pfd, &pss, &psl) == -1) {
syslog(LOG_ERR, "%s: getpeername failed (%m)", __func__);
return -1;
}
return bl_post(&lss, &pss, e, ctx);
}
#endif
int
bl_send(bl_t b, bl_type_t e, int lfd, int pfd, const char *ctx)
{
@ -102,14 +165,15 @@ bl_send(bl_t b, bl_type_t e, int lfd, int pfd, const char *ctx)
union {
char ctrl[CMSG_SPACE(2 * sizeof(int))];
uint32_t fd[2];
} uc;
} ua;
struct cmsghdr *cmsg;
union {
bl_message_t bl;
char buf[512];
} ub;
int *fd;
size_t ctxlen;
size_t ctxlen, tried;
#define NTRIES 5
ctxlen = strlen(ctx);
if (ctxlen > 256)
@ -127,8 +191,8 @@ bl_send(bl_t b, bl_type_t e, int lfd, int pfd, const char *ctx)
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = uc.ctrl;
msg.msg_controllen = sizeof(uc.ctrl);
msg.msg_control = ua.ctrl;
msg.msg_controllen = sizeof(ua.ctrl);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(2 * sizeof(int));
@ -139,33 +203,38 @@ bl_send(bl_t b, bl_type_t e, int lfd, int pfd, const char *ctx)
fd[0] = lfd;
fd[1] = pfd;
tried = 0;
again:
if (bl_init(b, false) == -1)
return -1;
return sendmsg(b->b_fd, &msg, 0);
if ((sendmsg(b->b_fd, &msg, 0) == -1) && tried++ < NTRIES) {
bl_reset(b);
goto again;
}
return tried >= NTRIES ? -1 : 0;
}
int
bl_recv(bl_t b, bl_type_t *e, int *lfd, int *pfd, char *ctx, size_t clen)
bl_info_t *
bl_recv(bl_t b)
{
struct msghdr msg;
struct iovec iov;
union {
char ctrl[CMSG_SPACE(2 * sizeof(int))];
char ctrl[CMSG_SPACE(2 * sizeof(int)) +
CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX))];
uint32_t fd[2];
} uc;
struct sockcred sc;
} ua;
struct cmsghdr *cmsg;
struct sockcred *sc;
union {
bl_message_t bl;
char buf[512];
} ub;
int *fd;
ssize_t rlen;
*e = BL_INVALID;
*lfd = *pfd = -1;
if (clen > 0)
*ctx = '\0';
bl_info_t *bi = &b->b_info;
iov.iov_base = ub.buf;
iov.iov_len = sizeof(ub);
@ -175,49 +244,59 @@ bl_recv(bl_t b, bl_type_t *e, int *lfd, int *pfd, char *ctx, size_t clen)
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = uc.ctrl;
msg.msg_controllen = sizeof(uc.ctrl);
msg.msg_control = ua.ctrl;
msg.msg_controllen = sizeof(ua.ctrl) + 100;
rlen = recvmsg(b->b_fd, &msg, 0);
if (rlen == -1) {
syslog(LOG_ERR, "%s: recvmsg failed (%m)", __func__);
return -1;
(*b->b_fun)(LOG_ERR, "%s: recvmsg failed (%m)", __func__);
return NULL;
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level != SOL_SOCKET) {
syslog(LOG_ERR, "%s: unexpected cmsg_level %d",
(*b->b_fun)(LOG_ERR, "%s: unexpected cmsg_level %d",
__func__, cmsg->cmsg_level);
continue;
}
if (cmsg->cmsg_type != SCM_RIGHTS) {
syslog(LOG_ERR, "%s: unexpected cmsg_type %d",
switch (cmsg->cmsg_type) {
case SCM_RIGHTS:
if (cmsg->cmsg_len != CMSG_LEN(2 * sizeof(int))) {
(*b->b_fun)(LOG_ERR,
"%s: unexpected cmsg_len %d != %zu",
__func__, cmsg->cmsg_len,
CMSG_LEN(2 * sizeof(int)));
continue;
}
fd = (void *)CMSG_DATA(cmsg);
memcpy(bi->bi_fd, fd, sizeof(bi->bi_fd));
break;
case SCM_CREDS:
sc = (void *)CMSG_DATA(cmsg);
if (sc->sc_ngroups > NGROUPS_MAX)
sc->sc_ngroups = NGROUPS_MAX;
memcpy(bi->bi_cred, sc, SOCKCREDSIZE(sc->sc_ngroups));
break;
default:
(*b->b_fun)(LOG_ERR, "%s: unexpected cmsg_type %d",
__func__, cmsg->cmsg_type);
continue;
}
if (cmsg->cmsg_len == CMSG_LEN(2 * sizeof(int))) {
syslog(LOG_ERR, "%s: unexpected cmsg_len %d != %zu",
__func__, cmsg->cmsg_len,
CMSG_LEN(2 * sizeof(int)));
continue;
}
fd = (void *)CMSG_DATA(cmsg);
*lfd = fd[0];
*pfd = fd[1];
}
if (rlen <= sizeof(ub.bl)) {
syslog(LOG_ERR, "message too short %zd", rlen);
return rlen;
(*b->b_fun)(LOG_ERR, "message too short %zd", rlen);
return NULL;
}
if (ub.bl.bl_version != BL_VERSION) {
syslog(LOG_ERR, "bad version %d", ub.bl.bl_version);
return rlen;
(*b->b_fun)(LOG_ERR, "bad version %d", ub.bl.bl_version);
return NULL;
}
*e = ub.bl.bl_type;
strlcpy(ctx, ub.bl.bl_data, MIN(clen, rlen - sizeof(ub.bl)));
return rlen;
bi->bi_type = ub.bl.bl_type;
strlcpy(bi->bi_msg, ub.bl.bl_data, MIN(sizeof(bi->bi_msg),
rlen - sizeof(ub.bl) + 1));
return bi;
}

View File

@ -1,6 +1,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
@ -9,34 +10,69 @@
#include <err.h>
static __dead void
usage(const char *msg)
usage(void)
{
fprintf(stderr, "Usage: %s %s\n", getprogname(), msg);
fprintf(stderr, "Usage: %s [-a <addr>] [-m <msg>]\n", getprogname());
exit(1);
}
static void
getaddr(const char *a, in_port_t p, struct sockaddr_storage *ss)
{
int c;
memset(ss, 0, sizeof(*ss));
p = htons(p);
if (strchr(a, ':')) {
struct sockaddr_in6 *s6 = (void *)ss;
c = inet_pton(AF_INET6, a, &s6->sin6_addr);
s6->sin6_family = AF_INET6;
s6->sin6_len = sizeof(*s6);
s6->sin6_port = p;
} else {
struct sockaddr_in *s = (void *)ss;
c = inet_pton(AF_INET, a, &s->sin_addr);
s->sin_family = AF_INET;
s->sin_len = sizeof(*s);
s->sin_port = p;
}
if (c == -1)
err(EXIT_FAILURE, "Invalid address `%s'", a);
}
int
main(int argc, char *argv[])
{
int sfd;
struct sockaddr_in ssin;
int c;
struct sockaddr_storage ss;
const char *msg = "hello";
const char *addr = "127.0.0.1";
while ((c = getopt(argc, argv, "a:m:")) == -1) {
switch (c) {
case 'a':
addr = optarg;
break;
case 'm':
msg = optarg;
break;
default:
usage();
}
}
getaddr(addr, 6161, &ss);
if (argc == 1)
usage("<message>");
if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
err(1, "socket");
memset(&ssin, 0, sizeof(ssin));
ssin.sin_family = AF_INET;
ssin.sin_len = sizeof(ssin);
ssin.sin_addr.s_addr = htonl(INADDR_ANY);
ssin.sin_port = htons(6161);
if (connect(sfd, (const void *)&ssin, sizeof(ssin)) == -1)
if (connect(sfd, (const void *)&ss, ss.ss_len) == -1)
err(1, "connect");
size_t len = strlen(argv[1]) + 1;
if (write(sfd, argv[1], len) != (ssize_t)len)
size_t len = strlen(msg) + 1;
if (write(sfd, msg, len) != (ssize_t)len)
err(1, "write");
return 0;
}

View File

@ -5,11 +5,13 @@
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <poll.h>
#include <err.h>
#include "bl.h"
#include "blacklist.h"
static void
process(bl_t bl, int sfd, int afd)
@ -22,54 +24,86 @@ process(bl_t bl, int sfd, int afd)
if ((n = read(afd, buffer, sizeof(buffer))) == -1)
err(1, "read");
buffer[sizeof(buffer) - 1] = '\0';
printf("%s: sending %d %d %s\n", getprogname(), sfd, afd, buffer);
bl_send(bl, BL_ADD, sfd, afd, buffer);
printf("received %s\n", buffer);
exit(0);
}
static int
cr(int af, in_port_t p)
{
int sfd;
struct sockaddr_storage ss;
sfd = socket(af == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0);
if (sfd == -1)
err(1, "socket");
p = htons(p);
memset(&ss, 0, sizeof(ss));
if (af == AF_INET) {
struct sockaddr_in *s = (void *)&ss;
s->sin_family = AF_INET;
s->sin_len = sizeof(*s);
s->sin_port = p;
} else {
struct sockaddr_in6 *s6 = (void *)&ss;
s6->sin6_family = AF_INET6;
s6->sin6_len = sizeof(*s6);
s6->sin6_port = p;
}
if (bind(sfd, (const void *)&ss, ss.ss_len) == -1)
err(1, "bind");
if (listen(sfd, 5) == -1)
err(1, "listen");
return sfd;
}
static void
handle(bl_t bl, int sfd)
{
struct sockaddr_storage ss;
socklen_t alen = sizeof(ss);
int afd;
if ((afd = accept(sfd, (void *)&ss, &alen)) == -1)
err(1, "accept");
/* Create child process */
switch (fork()) {
case -1:
err(1, "fork");
case 0:
process(bl, sfd, afd);
break;
default:
close(afd);
break;
}
}
int
main(int argc, char *argv[])
{
int sfd;
int s4fd, s6fd;
bl_t bl;
struct sockaddr_in ssin;
if ((sfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
err(1, "socket");
struct pollfd pfd[2];
signal(SIGCHLD, SIG_IGN);
memset(&ssin, 0, sizeof(ssin));
ssin.sin_family = AF_INET;
ssin.sin_len = sizeof(ssin);
ssin.sin_addr.s_addr = htonl(INADDR_ANY);
ssin.sin_port = htons(6161);
if (bind(sfd, (const void *)&ssin, sizeof(ssin)) == -1)
err(1, "bind");
pfd[0].fd = cr(AF_INET, 6161);
pfd[1].fd = cr(AF_INET6, 6161);
pfd[0].events = pfd[1].events = POLLIN;
if (listen(sfd, 5) == -1)
err(1, "listen");
bl = bl_create(false);
bl = bl_create();
for (;;) {
struct sockaddr_in asin;
socklen_t alen = sizeof(asin);
int afd;
if ((afd = accept(sfd, (void *)&asin, &alen)) == -1)
err(1, "accept");
/* Create child process */
switch (fork()) {
case -1:
err(1, "fork");
case 0:
process(bl, sfd, afd);
break;
default:
close(afd);
break;
if (poll(pfd, __arraycount(pfd), INFTIM) == -1)
err(1, "poll");
for (int i = 0; i < __arraycount(pfd); i++) {
if ((pfd[i].revents & POLLIN) == 0)
continue;
handle(bl, pfd[i].fd);
}
}
}