diff options
author | Laurent Ghigonis <laurent@p1sec.com> | 2012-11-29 10:58:30 +0100 |
---|---|---|
committer | Laurent Ghigonis <laurent@p1sec.com> | 2012-11-29 10:58:30 +0100 |
commit | b9decf4304d2204173a8d8a706e003cdde2b1bf7 (patch) | |
tree | d2a271e59d13cf1c01268931e79602f239a86ea4 /glougloud/glougloud.c | |
parent | include event.h here, and also the default queue.h of the system instead of the (diff) | |
download | glouglou-b9decf4304d2204173a8d8a706e003cdde2b1bf7.tar.xz glouglou-b9decf4304d2204173a8d8a706e003cdde2b1bf7.zip |
move glougloud to old
Diffstat (limited to 'glougloud/glougloud.c')
-rw-r--r-- | glougloud/glougloud.c | 487 |
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"); -} |