summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <cfchris6@ts2server.com>2010-09-08 22:12:12 (GMT)
committerChristian Franke <cfchris6@ts2server.com>2010-09-08 22:12:12 (GMT)
commitd50a06a4022e4f328da21209aa82296ab8b8f661 (patch)
tree7eed5b33b3871f97094e60832e053ede2ad5b2c2
parent6a2c876e08b5ed13b3b052b89e812a0afd66f61e (diff)
add daemon code
-rw-r--r--src/replarp.c109
1 files changed, 99 insertions, 10 deletions
diff --git a/src/replarp.c b/src/replarp.c
index 44e4f56..2692266 100644
--- a/src/replarp.c
+++ b/src/replarp.c
@@ -48,11 +48,14 @@
#if DEBUG
#define debug_printf(a) printf(a)
+#define daemonize()
#else
#define debug_printf(a)
#define debug_print_hwaddr(a,b,c)
#endif
+FILE *perr;
+
union ether_arp_ip {
unsigned char raw[32768];
struct __attribute__((packed)) {
@@ -99,19 +102,92 @@ static void debug_print_hwaddr(const char*, const uint8_t*, uint8_t);
static void main_loop();
int main(int,char**);
+#if !DEBUG
+static void daemonize();
+
+static void daemonize()
+{
+ if (chdir("/") < 0) {
+ perror("Error chdiring to /");
+ exit(EXIT_FAILURE);
+ }
+
+ int fd = open("/dev/null", O_RDWR | O_NOCTTY);
+ if (fd < 0) {
+ perror("Error opening /dev/null");
+ exit(EXIT_FAILURE);
+ }
+
+ int pipefd[2];
+
+ if (pipe(pipefd) < 0) {
+ perror("Error creating pipe");
+ exit(EXIT_FAILURE);
+ }
+
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ perror("Error spawning child process");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pid > 0) {
+ char buffer[1000];
+ close(pipefd[1]);
+
+ ssize_t red = read(pipefd[0], buffer, 1000);
+ buffer[red] = '\0';
+ if (!red) {
+ exit(EXIT_SUCCESS);
+ }
+
+ if (red < 0) {
+ perror("Reading from pipe");
+ } else {
+ fputs(buffer, stderr);
+ }
+
+ exit(EXIT_FAILURE);
+ }
+
+ close(pipefd[0]);
+
+ perr = fdopen(pipefd[1], "w");
+
+ if (setsid() < 0) {
+ fprintf(perr, "Error getting session id: %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ int fds[] = { STDIN_FILENO, STDOUT_FILENO , STDERR_FILENO , -1 };
+ int *iofd = fds;
+
+ while (*iofd >= 0) {
+ if (dup2(fd, *iofd) < 0) {
+ fprintf(perr, "Error closing fds: %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ iofd++;
+ }
+}
+#endif
+
static void open_socket()
{
struct sockaddr_ll lla;
arp_socket = socket(PF_PACKET, SOCK_RAW, ETHERTYPE_ARP);
if (arp_socket < 0) {
- perror("Error creating raw socket");
+ fprintf(perr, "Error creating raw socket: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
ifindex = if_nametoindex(ifname);
if (!ifindex) {
- fprintf(stderr, "Error: No interface with name `%s' found.\n",
+ fprintf(perr, "Error: No interface with name `%s' found.\n",
ifname);
close(arp_socket);
exit(EXIT_FAILURE);
@@ -123,7 +199,8 @@ static void open_socket()
lla.sll_ifindex = ifindex;
if (bind(arp_socket, (struct sockaddr*)(&lla), sizeof(lla)) < 0) {
- perror("Error binding socket to ARP");
+ fprintf(perr, "Error binding socket to ARP: %s\n",
+ strerror(errno));
close(arp_socket);
exit(EXIT_FAILURE);
}
@@ -139,13 +216,14 @@ static void get_hwaddr()
request.ifr_ifindex = ifindex;
if (ioctl(arp_socket, SIOCGIFHWADDR, &request) < 0) {
- perror("Error in get_hwaddr(): ioctl failed");
+ fprintf(perr, "Error in get_hwaddr(): ioctl failed:%s\n",
+ strerror(errno));
close(arp_socket);
exit(EXIT_FAILURE);
}
if (request.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
- fprintf(stderr, "This is no ethernet device.\n");
+ fprintf(perr, "This is no ethernet device.\n");
close(arp_socket);
exit(EXIT_FAILURE);
}
@@ -177,16 +255,22 @@ static void main_loop()
while (1) {
memset(&lla, 0, sizeof(lla));
lla_size = sizeof(lla);
+ if (perr && perr != stderr) {
+ fclose(perr);
+ perr = NULL;
+ }
+
red = recvfrom(arp_socket, recvbuffer.raw, sizeof(recvbuffer), 0,
(struct sockaddr*)(&lla), &lla_size);
if (red <= 0) {
if (red < 0)
- perror("Error reading from socket");
+ fprintf(perr, "Error reading from socket: %s\n",
+ strerror(errno));
break;
}
if (red < sizeof(recvbuffer.hdr)) {
- fprintf(stderr, "Received a shorted packet.\n");
+ fprintf(perr, "Received a shorted packet.\n");
continue;
}
@@ -232,16 +316,21 @@ static void main_loop()
if (send(arp_socket, sendbuffer.raw, sizeof(sendbuffer.hdr), 0)
!= sizeof(sendbuffer.hdr)) {
- perror("Error sending the answer");
+ fprintf(perr, "Error sending the answer: %s\n",
+ strerror(errno));
}
}
}
int main(int argc, char **argv)
{
+ perr = stderr;
debug_printf("Built with debug code.\n");
+
+ daemonize();
+
if (argc < 3) {
- fprintf(stderr, "Usage: %s <ifname> <ip> [...]\n", argv[0]);
+ fprintf(perr, "Usage: %s <ifname> <ip> [...]\n", argv[0]);
exit(EXIT_FAILURE);
}
ifname = argv[1];
@@ -250,7 +339,7 @@ int main(int argc, char **argv)
addresses = malloc(addr_count*sizeof(struct in_addr));
for (int i = 0; i < addr_count; i++) {
if (inet_pton(AF_INET, argv[2 + i], &addresses[i]) < 1) {
- fprintf(stderr,
+ fprintf(perr,
"An error occured while parsing the IP `%s'.\n",
argv[2 + i]);
exit(EXIT_FAILURE);