Permalink
Browse files

Merge branch 'fixes'

  • Loading branch information...
2 parents cf3faa2 + b50e4c1 commit 7755e767290059b5f0f99fad02fe1b2475502788 @msantos committed Jul 1, 2012
Showing with 80 additions and 14 deletions.
  1. +47 −12 c_src/epcap.c
  2. +5 −0 c_src/epcap.h
  3. +25 −0 c_src/epcap_priv.c
  4. +3 −2 rebar.config
View
@@ -40,15 +40,26 @@ void epcap_ctrl(const char *ctrl_evt);
void epcap_response(struct pcap_pkthdr *hdr, const u_char *pkt, unsigned int datalink);
void epcap_send_free(ei_x_buff *msg);
void epcap_watch();
+void gotsig(int sig);
void usage(EPCAP_STATE *ep);
+int child_exited = 0;
+
+/* On some platforms (Linux), poll() (used by pcap)
+ * will return EINVAL if RLIMIT_NOFILES < numfd */
+#ifndef EPCAP_RLIMIT_NOFILES
+#define EPCAP_RLIMIT_NOFILES 0
+#warning "Using default value of EPCAP_RLIMIT_NOFILES=0"
+#endif
+
int
main(int argc, char *argv[])
{
EPCAP_STATE *ep = NULL;
pid_t pid = 0;
int ch = 0;
+ int fd = 0;
IS_NULL(ep = calloc(1, sizeof(EPCAP_STATE)));
@@ -100,27 +111,39 @@ main(int argc, char *argv[])
IS_NULL(ep->filt = strdup( (argc == 1) ? argv[0] : EPCAP_FILTER));
+ IS_LTZERO(fd = open("/dev/null", O_RDWR));
+
epcap_priv_issetuid(ep);
IS_LTZERO(epcap_open(ep));
if (epcap_priv_drop(ep) < 0)
exit (1);
+ signal(SIGCHLD, gotsig);
+
switch (pid = fork()) {
case -1:
err(EXIT_FAILURE, "fork");
case 0:
- (void)close(fileno(stdin));
+ IS_LTZERO(dup2(fd, STDIN_FILENO));
+ IS_LTZERO(close(fd));
IS_LTZERO(epcap_init(ep));
+ IS_LTZERO(epcap_priv_rlimits(EPCAP_RLIMIT_NOFILES));
epcap_loop(ep);
break;
default:
- (void)close(fileno(stdout));
+ if ( (dup2(fd, STDOUT_FILENO) < 0) ||
+ (close(fd) < 0))
+ goto CLEANUP;
+
pcap_close(ep->p);
+
+ if (epcap_priv_rlimits(0) < 0)
+ goto CLEANUP;
+
epcap_watch();
- (void)kill(pid, SIGTERM);
- free(ep->filt);
- free(ep);
+CLEANUP:
+ (void)kill(pid, SIGTERM);
break;
}
@@ -131,14 +154,14 @@ main(int argc, char *argv[])
void
epcap_watch()
{
- int fd = fileno(stdin);
+ int fd = STDIN_FILENO;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
- (void)select(fd+1, &rfds, NULL, NULL, NULL);
-
+ if (child_exited == 0)
+ (void)select(fd+1, &rfds, NULL, NULL, NULL);
}
@@ -178,7 +201,7 @@ epcap_init(EPCAP_STATE *ep)
if (pcap_lookupnet(ep->dev, &ipaddr, &ipmask, errbuf) == -1) {
VERBOSE(1, "%s", errbuf);
- ipmask=PCAP_NETMASK_UNKNOWN;
+ ipmask=PCAP_NETMASK_UNKNOWN;
}
VERBOSE(2, "[%s] Using filter: %s\n", __progname, ep->filt);
@@ -222,7 +245,7 @@ epcap_loop(EPCAP_STATE *ep)
read_packet = 0;
break;
case -1: /* error reading packet */
- VERBOSE(1, "error reading packet");
+ VERBOSE(1, "%s", pcap_geterr(p));
/* fall through */
default:
read_packet = 0;
@@ -279,16 +302,28 @@ void epcap_send_free(ei_x_buff *msg)
u_int16_t len = 0;
len = htons(msg->index);
- if (write(fileno(stdout), &len, sizeof(len)) != sizeof(len))
+ if (write(STDOUT_FILENO, &len, sizeof(len)) != sizeof(len))
errx(EXIT_FAILURE, "write header failed");
- if (write(fileno(stdout), msg->buff, msg->index) != msg->index)
+ if (write(STDOUT_FILENO, msg->buff, msg->index) != msg->index)
errx(EXIT_FAILURE, "write packet failed: %d", msg->index);
ei_x_free(msg);
}
void
+gotsig(int sig)
+{
+ switch (sig) {
+ case SIGCHLD:
+ child_exited = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+ void
usage(EPCAP_STATE *ep)
{
(void)fprintf(stderr, "%s, %s\n", __progname, EPCAP_VERSION);
View
@@ -35,9 +35,13 @@
#include <unistd.h>
#include <err.h>
#include <signal.h>
+#include <fcntl.h>
#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
#include <pcap.h>
#define EPCAP_VERSION "0.03"
@@ -104,3 +108,4 @@ typedef struct {
int epcap_priv_drop(EPCAP_STATE *ep);
void epcap_priv_issetuid(EPCAP_STATE *ep);
+int epcap_priv_rlimits(int nfd);
View
@@ -87,3 +87,28 @@ epcap_priv_issetuid(EPCAP_STATE *ep)
IS_LTZERO(setuid(getuid()));
}
}
+
+ int
+epcap_priv_rlimits(int nfd)
+{
+ struct rlimit rl = {0};
+
+#ifdef RLIMIT_FSIZE
+ if (setrlimit(RLIMIT_FSIZE, &rl) != 0)
+ return -1;
+#endif
+
+#ifdef RLIMIT_NPROC
+ if (setrlimit(RLIMIT_NPROC, &rl) != 0)
+ return -1;
+#endif
+
+#ifdef RLIMIT_NOFILE
+ rl.rlim_cur = nfd;
+ rl.rlim_max = nfd;
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
+ return -1;
+#endif
+
+ return 0;
+}
View
@@ -1,6 +1,7 @@
{port_env, [
- {"EXE_CFLAGS", "-g -Wall $ERL_CFLAGS"},
- {"EXE_LDFLAGS", "-lpcap $ERL_LDFLAGS"}
+ {"EXE_LDFLAGS", "-lpcap $ERL_LDFLAGS"},
+ {"linux", "EXE_CFLAGS", "$EXE_CFLAGS -DEPCAP_RLIMIT_NOFILES=1"},
+ {"solaris", "EXE_CFLAGS", "$EXE_CFLAGS -DEPCAP_RLIMIT_NOFILES=1"}
]}.
{port_specs, [
{"priv/epcap", ["c_src/epcap.c", "c_src/epcap_priv.c"]}

0 comments on commit 7755e76

Please sign in to comment.