From 15b6d0cf21927f2aa7311c9cfaad46261164f269 Mon Sep 17 00:00:00 2001
From: Erik Ekman <yarrick@kryo.se>
Date: Sat, 15 Aug 2009 21:52:49 +0000
Subject: [PATCH] #70 add -F option for writing pid file. Patch from
 misc@mandriva.org

---
 man/iodine.8  |  7 +++++++
 src/common.c  | 20 ++++++++++++++++++++
 src/common.h  |  1 +
 src/iodine.c  | 19 +++++++++++++++----
 src/iodined.c | 23 +++++++++++++++--------
 5 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/man/iodine.8 b/man/iodine.8
index b58890b..7146dd3 100644
--- a/man/iodine.8
+++ b/man/iodine.8
@@ -21,6 +21,8 @@ iodine, iodined \- tunnel IPv4 over DNS
 .I fragsize
 .B ] [-z
 .I context
+.B ] [-F
+.I pidfile
 .B ]
 .B [
 .I nameserver
@@ -51,6 +53,8 @@ iodine, iodined \- tunnel IPv4 over DNS
 .I password
 .B ] [-z
 .I context
+.B ] [-F
+.I pidfile
 .B ]
 .I tunnel_ip
 .B [
@@ -96,6 +100,9 @@ will be used as input. Only the first 32 characters will be used.
 .TP
 .B -z context
 Apply SELinux 'context' after initialization.
+.TP
+.B -F pidfile
+Create 'pidfile' and write process id in it.
 .SS Client Options:
 .TP
 .B -m fragsize
diff --git a/src/common.c b/src/common.c
index ba87a89..a4ef691 100644
--- a/src/common.c
+++ b/src/common.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <fcntl.h>
+#include <errno.h>
 
 #ifdef WINDOWS32
 #include <winsock2.h>
@@ -39,6 +40,7 @@
 #include <err.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <syslog.h>
 #endif
 
 #ifdef HAVE_SETCON
@@ -182,6 +184,24 @@ do_setcon(char *context)
 #endif
 }
 
+void
+do_pidfile(char *pidfile)
+{
+#ifndef WINDOWS32
+	FILE *file;
+
+	if ((file = fopen(pidfile, "w")) == NULL) {
+		syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
+		err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
+	} else {
+		fprintf(file, "%d\n", (int)getpid());
+		fclose(file);
+	}
+#else
+	fprintf(stderr, "Windows version does not support pid file\n");
+#endif
+}
+
 void
 do_detach()
 {
diff --git a/src/common.h b/src/common.h
index cc977d2..3570058 100644
--- a/src/common.h
+++ b/src/common.h
@@ -104,6 +104,7 @@ void close_dns(int);
 void do_chroot(char *);
 void do_setcon(char *);
 void do_detach();
+void do_pidfile(char *);
 
 void read_password(char*, size_t);
 
diff --git a/src/iodine.c b/src/iodine.c
index 036b7d0..5888535 100644
--- a/src/iodine.c
+++ b/src/iodine.c
@@ -1158,7 +1158,8 @@ usage() {
 	extern char *__progname;
 
 	fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
-			"[-P password] [-m maxfragsize] [-z context] [nameserver] topdomain\n", __progname);
+			"[-P password] [-m maxfragsize] [-z context] [-F pidfile] "
+			"[nameserver] topdomain\n", __progname);
 	exit(2);
 }
 
@@ -1168,7 +1169,8 @@ help() {
 
 	fprintf(stderr, "iodine IP over DNS tunneling client\n");
 	fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
-			"[-P password] [-m maxfragsize] [-z context] [nameserver] topdomain\n", __progname);
+			"[-P password] [-m maxfragsize] [-z context] [-F pidfile] "
+			"[nameserver] topdomain\n", __progname);
 	fprintf(stderr, "  -v to print version info and exit\n");
 	fprintf(stderr, "  -h to print this help and exit\n");
 	fprintf(stderr, "  -f to keep running in foreground\n");
@@ -1178,6 +1180,7 @@ help() {
 	fprintf(stderr, "  -P password used for authentication (max 32 chars will be used)\n");
 	fprintf(stderr, "  -m maxfragsize, to limit size of downstream packets\n");
 	fprintf(stderr, "  -z context, to apply specified SELinux context after initialization\n");
+	fprintf(stderr, "  -F pidfile to write pid to a file\n");
 	fprintf(stderr, "nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n");
 	fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
 
@@ -1208,6 +1211,7 @@ main(int argc, char **argv)
 	char *newroot;
 	char *context;
 	char *device;
+	char *pidfile;
 	int choice;
 	int tun_fd;
 	int dns_fd;
@@ -1227,6 +1231,7 @@ main(int argc, char **argv)
 	context = NULL;
 	device = NULL;
 	chunkid = 0;
+	pidfile = NULL;
 
 	outpkt.seqno = 0;
 	inpkt.len = 0;
@@ -1256,7 +1261,7 @@ main(int argc, char **argv)
 		__progname++;
 #endif
 
-	while ((choice = getopt(argc, argv, "vfhru:t:d:P:m:")) != -1) {
+	while ((choice = getopt(argc, argv, "vfhru:t:d:P:m:F:")) != -1) {
 		switch(choice) {
 		case 'v':
 			version();
@@ -1294,6 +1299,9 @@ main(int argc, char **argv)
 		case 'z':
 			context = optarg;
 			break;
+		case 'F':
+			pidfile = optarg;
+			break;    
 		default:
 			usage();
 			/* NOTREACHED */
@@ -1382,6 +1390,9 @@ main(int argc, char **argv)
 
 	if (foreground == 0) 
 		do_detach();
+	
+	if (pidfile != NULL)
+		do_pidfile(pidfile);
 
 	if (newroot != NULL)
 		do_chroot(newroot);
@@ -1400,7 +1411,7 @@ main(int argc, char **argv)
 
 	if (context != NULL)
 		do_setcon(context);
-	
+
 	downstream_seqno = 0;
 	downstream_fragment = 0;
 	down_ack_seqno = 0;
diff --git a/src/iodined.c b/src/iodined.c
index 5028c84..8e3b9d7 100644
--- a/src/iodined.c
+++ b/src/iodined.c
@@ -1068,8 +1068,9 @@ usage() {
 
 	fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
 		"[-t chrootdir] [-d device] [-m mtu] [-z context] "
-		"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
-		" tunnel_ip[/netmask] topdomain\n", __progname);
+		"[-l ip address to listen on] [-p port] [-n external ip] "
+		"[-b dnsport] [-P password] [-F pidfile] "
+		"tunnel_ip[/netmask] topdomain\n", __progname);
 	exit(2);
 }
 
@@ -1080,8 +1081,8 @@ help() {
 	fprintf(stderr, "iodine IP over DNS tunneling server\n");
 	fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
 		"[-t chrootdir] [-d device] [-m mtu] [-z context] "
-		"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
-		" tunnel_ip[/netmask] topdomain\n", __progname);
+		"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password] "
+		"[-F pidfile] tunnel_ip[/netmask] topdomain\n", __progname);
 	fprintf(stderr, "  -v to print version info and exit\n");
 	fprintf(stderr, "  -h to print this help and exit\n");
 	fprintf(stderr, "  -c to disable check of client IP/port on each request\n");
@@ -1100,6 +1101,7 @@ help() {
 	fprintf(stderr, "  -n ip to respond with to NS queries\n");
 	fprintf(stderr, "  -b port to forward normal DNS queries to (on localhost)\n");
 	fprintf(stderr, "  -P password used for authentication (max 32 chars will be used)\n");
+	fprintf(stderr, "  -F pidfile to write pid to a file\n");
 	fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n");
 	fprintf(stderr, "   /netmask sets the size of the tunnel network.\n");
 	fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n");
@@ -1128,6 +1130,7 @@ main(int argc, char **argv)
 	char *newroot;
 	char *context;
 	char *device;
+	char *pidfile;
 	int dnsd_fd;
 	int tun_fd;
 
@@ -1161,6 +1164,7 @@ main(int argc, char **argv)
 	skipipconfig = 0;
 	debug = 0;
 	netmask = 27;
+	pidfile = NULL;
 
 	b32 = get_base32_encoder();
 	
@@ -1182,7 +1186,7 @@ main(int argc, char **argv)
 	srand(time(NULL));
 	fw_query_init();
 	
-	while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:")) != -1) {
+	while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:")) != -1) {
 		switch(choice) {
 		case 'v':
 			version();
@@ -1227,6 +1231,9 @@ main(int argc, char **argv)
 			bind_enable = 1;
 			bind_port = atoi(optarg);
 			break;
+		case 'F':
+			pidfile = optarg;
+			break;    
 		case 'P':
 			strncpy(password, optarg, sizeof(password));
 			password[sizeof(password)-1] = 0;
@@ -1374,6 +1381,9 @@ main(int argc, char **argv)
 	if (foreground == 0) 
 		do_detach();
 	
+	if (pidfile != NULL)
+		do_pidfile(pidfile);
+
 	if (newroot != NULL)
 		do_chroot(newroot);
 
@@ -1392,9 +1402,6 @@ main(int argc, char **argv)
 	if (context != NULL)
 		do_setcon(context);
 
-#ifndef WINDOWS32
-	openlog(__progname, LOG_NOWAIT, LOG_DAEMON);
-#endif
 	syslog(LOG_INFO, "started, listening on port %d", port);
 	
 	tunnel(tun_fd, dnsd_fd, bind_fd);