diff --git a/external/bsd/blacklist/bin/Makefile b/external/bsd/blacklist/bin/Makefile new file mode 100644 index 000000000000..8a20d0ad573e --- /dev/null +++ b/external/bsd/blacklist/bin/Makefile @@ -0,0 +1,8 @@ +.include + +MKMAN=no +PROGS=srvtest cltest +SRCS.srvtest = client.c srvtest.c +SRCS.cltest = cltest.c + +.include diff --git a/external/bsd/blacklist/bin/internal.h b/external/bsd/blacklist/bin/internal.h new file mode 100644 index 000000000000..88703a748c2f --- /dev/null +++ b/external/bsd/blacklist/bin/internal.h @@ -0,0 +1,16 @@ + + +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 diff --git a/external/bsd/blacklist/include/bl.h b/external/bsd/blacklist/include/bl.h new file mode 100644 index 000000000000..d3048323ca6c --- /dev/null +++ b/external/bsd/blacklist/include/bl.h @@ -0,0 +1,13 @@ + +typedef enum { + BL_ADD, + BL_PING, +} bl_type_t; + +typedef struct blacklist *bl_t; + +bl_t bl_create(void); +void bl_destroy(bl_t); +int bl_add(bl_t, bl_type_t, int, int, const char *ctx); + +#define _PATH_BLACKLIST "/tmp/blacklist" diff --git a/external/bsd/blacklist/lib/bl.c b/external/bsd/blacklist/lib/bl.c new file mode 100644 index 000000000000..635f2d5d8579 --- /dev/null +++ b/external/bsd/blacklist/lib/bl.c @@ -0,0 +1,136 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "bl.h" +#include "internal.h" + +static int +bl_init(bl_t b) +{ + /* AF_UNIX address of local logger */ + static const struct sockaddr_un sun = { + .sun_family = AF_LOCAL, + .sun_len = sizeof(sun), + .sun_path = _PATH_BLACKLIST, + }; + + 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__); + return 0; + } + } + + if (b->b_connected) + return 0; + + if (connect(b->b_fd, (const void *)&sun, + (socklen_t)sizeof(sun)) == -1) { + syslog(LOG_ERR, "%s: connect failed (%m)", __func__); + return -1; + } + b->b_connected = 1; + return 0; +} + +bl_t +bl_create(void) +{ + bl_t b = malloc(sizeof(*b)); + if (b == NULL) { + syslog(LOG_ERR, "%s: malloc failed (%m)", __func__); + return NULL; + } + bl_init(b); + return b; +} + +void +bl_destroy(bl_t b) +{ + close(b->b_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_add(bl_t b, bl_type_t e, int lfd, int pfd, const char *ctx) +{ + struct msghdr msg; + struct iovec iov; + union { + char ctrl[CMSG_SPACE(2 * sizeof(int))]; + uint32_t fd[2]; + } uc; + struct cmsghdr *cmsg; + union { + bl_message_t bl; + char buf[512]; + } ub; + int *fd; + size_t ctxlen; + + ctxlen = strlen(ctx); + if (ctxlen > 256) + ctxlen = 256; + + iov.iov_base = ub.buf; + iov.iov_len = sizeof(bl_message_t) + ctxlen; + ub.bl.bl_len = iov.iov_len; + ub.bl.bl_version = BL_VERSION; + ub.bl.bl_type = (uint32_t)e; + memcpy(ub.bl.bl_data, ctx, ctxlen); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = uc.ctrl; + msg.msg_controllen = sizeof(uc.ctrl); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(2 * sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + fd = (void *)CMSG_DATA(cmsg); + fd[0] = lfd; + fd[1] = pfd; + + if (bl_init(b) == -1) + return -1; + + return sendmsg(b->b_fd, &msg, 0); +} diff --git a/external/bsd/blacklist/test/cltest.c b/external/bsd/blacklist/test/cltest.c new file mode 100644 index 000000000000..ac2f9c175c46 --- /dev/null +++ b/external/bsd/blacklist/test/cltest.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +static __dead void +usage(const char *msg) +{ + fprintf(stderr, "Usage: %s %s\n", getprogname(), msg); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int sfd; + struct sockaddr_in ssin; + + if (argc == 1) + usage(""); + 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) + err(1, "connect"); + + size_t len = strlen(argv[1]) + 1; + if (write(sfd, argv[1], len) != (ssize_t)len) + err(1, "write"); + return 0; +} diff --git a/external/bsd/blacklist/test/srvtest.c b/external/bsd/blacklist/test/srvtest.c new file mode 100644 index 000000000000..37e80e7d0e3a --- /dev/null +++ b/external/bsd/blacklist/test/srvtest.c @@ -0,0 +1,75 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bl.h" + +static void +process(bl_t bl, int sfd, int afd) +{ + ssize_t n; + char buffer[256]; + + memset(buffer, 0, sizeof(buffer)); + + if ((n = read(afd, buffer, sizeof(buffer))) == -1) + err(1, "read"); + buffer[sizeof(buffer) - 1] = '\0'; + bl_add(bl, BL_ADD, sfd, afd, buffer); + printf("received %s\n", buffer); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int sfd; + bl_t bl; + struct sockaddr_in ssin; + + if ((sfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) + err(1, "socket"); + + 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"); + + if (listen(sfd, 5) == -1) + err(1, "listen"); + + 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; + } + } +}