aboutsummaryrefslogtreecommitdiffstats
path: root/glougloud/glougloud.c
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2012-11-29 10:58:30 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2012-11-29 10:58:30 +0100
commitb9decf4304d2204173a8d8a706e003cdde2b1bf7 (patch)
treed2a271e59d13cf1c01268931e79602f239a86ea4 /glougloud/glougloud.c
parentinclude event.h here, and also the default queue.h of the system instead of the (diff)
downloadglouglou-b9decf4304d2204173a8d8a706e003cdde2b1bf7.tar.xz
glouglou-b9decf4304d2204173a8d8a706e003cdde2b1bf7.zip
move glougloud to old
Diffstat (limited to 'glougloud/glougloud.c')
-rw-r--r--glougloud/glougloud.c487
1 files changed, 0 insertions, 487 deletions
diff --git a/glougloud/glougloud.c b/glougloud/glougloud.c
deleted file mode 100644
index 49a1608..0000000
--- a/glougloud/glougloud.c
+++ /dev/null
@@ -1,487 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/ioctl.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-
-#include <netdb.h>
-#include <pcap.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <err.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-
-#include "glougloud.h"
-#include "external/imsgev.h"
-#if defined(__OpenBSD__)
-#include "pcap-int.h"
-#endif
-
-struct server_proc {
- pid_t pid;
- int fd[2];
- struct imsgev iev;
-};
-struct user_proc {
- pid_t pid;
- int fd[2];
- struct imsgev iev;
-};
-enum user_status {
- USER_REQUESTED,
- USER_ACCEPTED
-};
-struct user {
- LIST_ENTRY(user) entry;
- struct sockaddr_in addr;
- enum user_status status;
-};
-
-// XXX CONF
-#define PCAP_INTERFACE "lo"
-#define PCAP_SNAPLEN 100
-#define PCAP_FILTER "not port 4430 and not port 53"
-
-static void imsgev_server(struct imsgev *, int, struct imsg *);
-static void imsgev_user(struct imsgev *, int, struct imsg *);
-static void imsgev_server_needfd(struct imsgev *);
-static void imsgev_user_needfd(struct imsgev *);
-
-struct server_proc *srv_proc;
-struct user_proc *usr_proc;
-LIST_HEAD(, user) usr_list;
-int net_socket;
-
-#if defined(__OPENBSD__)
-void __dead
-#else
-void
-#endif
-usage(void)
-{
- extern char *__progname;
-
- fprintf(stderr, "usage: %s [-vi]",
- __progname);
- exit(1);
-}
-
-static void
-sig_handler(int sig, short why, void *data)
-{
- log_info("got signal %d", sig);
- if (sig == SIGINT || sig == SIGTERM)
- event_loopexit(NULL);
-}
-
-/*
- * reimplement pcap_open_live with more restrictions on the bpf fd :
- * - open device read only
- * - lock the fd
- * based on OpenBSD tcpdump, privsep_pcap.c v1.16
- */
-
-static pcap_t *
-my_pcap_open_live(const char *dev, int slen, int promisc, int to_ms,
- char *ebuf, u_int dlt, u_int dirfilt)
-{
-#if defined(__OpenBSD__)
- struct bpf_version bv;
- u_int v;
- pcap_t *p;
- char bpf[sizeof "/dev/bpf0000000000"];
- int fd, n = 0;
- struct ifreq ifr;
-
- p = xmalloc(sizeof(*p));
- bzero(p, sizeof(*p));
-
- /* priv part */
-
- do {
- snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++);
- fd = open(bpf, O_RDONLY);
- } while (fd < 0 && errno == EBUSY);
- if (fd < 0)
- return NULL;
-
- v = 32768; /* XXX this should be a user-accessible hook */
- ioctl(fd, BIOCSBLEN, &v);
-
- strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
- if (ioctl(fd, BIOCSETIF, &ifr) < 0)
- return NULL;
-
- if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt))
- return NULL;
-
- if (promisc)
- /* this is allowed to fail */
- ioctl(fd, BIOCPROMISC, NULL);
- if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
- return NULL;
-
- /* lock the descriptor */
- if (ioctl(fd, BIOCLOCK, NULL) < 0)
- return NULL;
-
- /* end of priv part */
-
- /* fd is locked, can only use 'safe' ioctls */
- if (ioctl(fd, BIOCVERSION, &bv) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
- pcap_strerror(errno));
- return NULL;
- }
-
- if (bv.bv_major != BPF_MAJOR_VERSION ||
- bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "kernel bpf filter out of date");
- return NULL;
- }
-
- p->fd = fd;
- p->snapshot = slen;
-
- /* Get the data link layer type. */
- if (ioctl(fd, BIOCGDLT, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
- pcap_strerror(errno));
- return NULL;
- }
-#if _BSDI_VERSION - 0 >= 199510
- /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
- switch (v) {
-
- case DLT_SLIP:
- v = DLT_SLIP_BSDOS;
- break;
-
- case DLT_PPP:
- v = DLT_PPP_BSDOS;
- break;
- }
-#endif
- p->linktype = v;
-
- /* XXX hack from tcpdump */
- if (p->linktype == DLT_PFLOG && p->snapshot < 160)
- p->snapshot = 160;
-
- /* set timeout */
- if (to_ms != 0) {
- struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
- if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
- pcap_strerror(errno));
- return NULL;
- }
- }
-
- if (ioctl(fd, BIOCGBLEN, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
- pcap_strerror(errno));
- return NULL;
- }
- p->bufsize = v;
- p->buffer = (u_char *)malloc(p->bufsize);
- if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return NULL;
- }
- return p;
-#else /* defined(__OpenBSD__) */
- return pcap_open_live(dev, slen, promisc, to_ms, ebuf);
-#endif
-}
-
-int
-main(int argc, char **argv)
-{
- struct sockaddr_in sock_addr;
- struct event ev_sigint, ev_sigterm, ev_sigchld, ev_sighup;
- char errbuf[PCAP_ERRBUF_SIZE];
- struct bpf_program bprog;
- pcap_t *pcap;
- int loglevel = 0, logpinvalid = 0;
- int op;
- int sock_on = 1;
-
- if (geteuid() != 0)
- errx(1, "need root privileges");
-
- while ((op = getopt(argc, argv, "hvi")) != -1) {
- switch (op) {
- case 'h':
- usage();
- /* NOTREACHED */
- case 'v':
- loglevel++;
- break;
- case 'i':
- logpinvalid = 1;
- break;
- default:
- usage();
- /* NOTREACHED */
- }
- }
-
- log_init(loglevel, logpinvalid);
- event_init();
-
- net_socket = socket(AF_INET, SOCK_DGRAM, 0);
- if (net_socket < 0)
- fatal("server: socket failed");
- setsockopt(net_socket, SOL_SOCKET, SO_REUSEADDR,
- &sock_on, sizeof(sock_on));
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- sock_addr.sin_port = htons(4430);
- if (bind(net_socket, (struct sockaddr *)&sock_addr,
- sizeof(sock_addr)) != 0)
- fatal("server: socket bind failed, %s", strerror(errno));
- fd_nonblock(net_socket);
-
- srv_proc = xmalloc(sizeof(struct server_proc));
- socketpair_prepare(srv_proc->fd);
- srv_proc->pid = server_init(srv_proc->fd);
- close(srv_proc->fd[1]);
- imsgev_init(&srv_proc->iev, srv_proc->fd[0], NULL, imsgev_server, imsgev_server_needfd);
-
- pcap = my_pcap_open_live(PCAP_INTERFACE, PCAP_SNAPLEN, 1, PCAP_TO, errbuf, -1, 0);
- if (pcap == NULL)
- fatal("capture: pcap_open_live failed on interface %s\n"
- "with snaplen %d : %s",
- PCAP_INTERFACE, PCAP_SNAPLEN, errbuf);
- if (pcap_compile(pcap, &bprog, PCAP_FILTER, 0, 0) < 0)
- fatal("capture: pcap_compile failed with filter %s : %s",
- PCAP_FILTER, pcap_geterr(pcap));
- if (pcap_setfilter(pcap, &bprog) < 0)
- fatal("capture: pcap_setfilter failed : %s",
- pcap_geterr(pcap));
-
- usr_proc = xmalloc(sizeof(struct user_proc));
- socketpair_prepare(usr_proc->fd);
- usr_proc->pid = user_init(usr_proc->fd, pcap);
- close(usr_proc->fd[1]);
- imsgev_init(&usr_proc->iev, usr_proc->fd[0], NULL, imsgev_user, imsgev_user_needfd);
-
- signal_set(&ev_sigint, SIGINT, sig_handler, NULL);
- signal_set(&ev_sigterm, SIGTERM, sig_handler, NULL);
- signal_set(&ev_sigchld, SIGCHLD, sig_handler, NULL);
- signal_set(&ev_sighup, SIGHUP, sig_handler, NULL);
- signal_add(&ev_sigint, NULL);
- signal_add(&ev_sigterm, NULL);
- signal_add(&ev_sigchld, NULL);
- signal_add(&ev_sighup, NULL);
- signal(SIGPIPE, SIG_IGN);
-
- log_info("entering event loop");
- event_dispatch();
-
- log_info("exiting");
- exit(0);
-}
-
-static struct user *
-finduser(struct sockaddr_in *remote) {
- struct user *usr;
- struct sockaddr_in *u;
-
- LIST_FOREACH(usr, &usr_list, entry) {
- u = &usr->addr;
- if (u->sin_addr.s_addr == remote->sin_addr.s_addr &&
- u->sin_port == remote->sin_port)
- return usr;
- }
- return NULL;
-}
-
-static void
-srvconn(struct imsgev *iev, struct imsg *imsg)
-{
- struct imsg_srvconn *req;
- struct imsg_srvconn res;
- struct imsg_usrconn req2;
- struct user *usr;
-
- req = imsg->data;
-
- if (req->deco) {
- log_tmp("srvconn deco");
- usr = finduser(&req->addr);
- if (!usr)
- fatal("trying to deco an inexistant user !");
-
- addrcpy(&req2.addr, &usr->addr);
- req2.deco = 1;
- imsgev_compose(&usr_proc->iev, IMSG_USRCONN_REQ, 0, 0, -1,
- &req2, sizeof(req2));
-
- LIST_REMOVE(usr, entry);
- free(usr);
-
- return;
- }
-
- if (req->addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
- log_tmp("srvconn accepted");
-
- usr = xmalloc(sizeof(struct user));
- addrcpy(&usr->addr, &req->addr);
- usr->status = USER_REQUESTED;
- LIST_INSERT_HEAD(&usr_list, usr, entry);
-
- addrcpy(&req2.addr, &req->addr);
- req2.deco = 0;
- imsgev_compose(&usr_proc->iev, IMSG_USRCONN_REQ, 0, 0, -1,
- &req2, sizeof(req2));
- }
- else
- {
- log_tmp("srvconn refused");
- res.ok = 0;
- addrcpy(&res.addr, &req->addr);
- imsgev_compose(iev, IMSG_SRVCONN_RES, 0, 0, -1,
- &res, sizeof(res));
- }
-
-}
-
-static void
-imsgev_server(struct imsgev *iev, int code, struct imsg *imsg)
-{
- switch (code) {
- case IMSGEV_IMSG:
- log_debug("%s, got imsg %i on fd %i",
- __func__, imsg->hdr.type, iev->ibuf.fd);
- switch (imsg->hdr.type) {
- case IMSG_SRVCONN_REQ:
- srvconn(iev, imsg);
- break;
- default:
- fatal("%s, unexpected imsg %d",
- __func__, imsg->hdr.type);
- }
- break;
- case IMSGEV_EREAD:
- case IMSGEV_EWRITE:
- case IMSGEV_EIMSG:
- fatal("imsgev server read/write error");
- /* NOTREACHED */
- break;
- case IMSGEV_DONE:
- event_loopexit(NULL);
- break;
- }
-}
-
-static void
-usrconn(struct imsgev *iev, struct imsg *imsg)
-{
- struct user *usr;
- struct imsg_usrconn *res;
- struct imsg_srvconn res2;
-
- res = imsg->data;
-
- usr = finduser(&res->addr);
- if (!usr || usr->status != USER_REQUESTED)
- fatal("received usrconn result that wasn't initiated !");
- usr->status = USER_ACCEPTED;
-
- addrcpy(&res2.addr, &res->addr);
- res2.ok = 1;
- imsgev_compose(&srv_proc->iev, IMSG_SRVCONN_RES, 0, 0, -1,
- &res2, sizeof(res2));
-}
-
-/* XXX drop imsg when msgbuf->queued is too high ? */
-/* XXX review that func for correctness and security */
-static void
-usrdns(struct imsgev *iev, struct imsg *imsg)
-{
- struct imsg_usrdns_req *req;
- struct imsg_usrdns_res res;
- struct hostent *ent;
- int len;
- char *name;
- extern int h_errno;
- struct in_addr addr;
-
- req = imsg->data;
-
- res.addr.s_addr = req->addr.s_addr;
- addr.s_addr = htonl(req->addr.s_addr);
- ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
- if (ent) {
- len = strlen(ent->h_name);
- if (len > DNSNAME_MAX)
- name = ent->h_name - DNSNAME_MAX; /* keep right part */
- else
- name = ent->h_name;
- strncpy(res.name, name, sizeof(res.name));
- } else {
- log_debug("usrdns failed for %x : %s",
- addr, hstrerror(h_errno));
- res.name[0] = '\0';
- }
-
- imsgev_compose(&usr_proc->iev, IMSG_USRDNS_RES, 0, 0, -1,
- &res, sizeof(res));
-}
-
-static void
-imsgev_user(struct imsgev *iev, int code, struct imsg *imsg)
-{
- switch (code) {
- case IMSGEV_IMSG:
- log_debug("%s, got imsg %i on fd %i",
- __func__, imsg->hdr.type, iev->ibuf.fd);
- switch (imsg->hdr.type) {
- case IMSG_USRCONN_RES:
- usrconn(iev, imsg);
- break;
- case IMSG_USRDNS_REQ:
- usrdns(iev, imsg);
- break;
- default:
- fatal("%s, unexpected imsg %d",
- __func__, imsg->hdr.type);
- }
- break;
- case IMSGEV_EREAD:
- case IMSGEV_EWRITE:
- case IMSGEV_EIMSG:
- fatal("imsgev user read/write error");
- /* NOTREACHED */
- break;
- case IMSGEV_DONE:
- event_loopexit(NULL);
- break;
- }
-}
-
-static void
-imsgev_server_needfd(struct imsgev *iev)
-{
- fatal("imsgev_server_needfd");
-}
-
-static void
-imsgev_user_needfd(struct imsgev *iev)
-{
- fatal("imsgev_user_needfd");
-}