Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Aug 2010 16:00:36 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r211528 - projects/sv/usr.sbin/netdumpsrv
Message-ID:  <201008201600.o7KG0afn041853@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Fri Aug 20 16:00:36 2010
New Revision: 211528
URL: http://svn.freebsd.org/changeset/base/211528

Log:
  - Daemonize the server after the initial setup.
  - Use syslog(3) interface in order to store the errors, warnings and
    normal output after the daemonization.
  
  TODO (in this area):
  - Fix eventual unhandled/mishandled error conditions
  - Fix message ordering/printout of error conditions and make them uniform
  - Offer structured API for dealing with prints on infofile and corefile

Modified:
  projects/sv/usr.sbin/netdumpsrv/netdump_server.c

Modified: projects/sv/usr.sbin/netdumpsrv/netdump_server.c
==============================================================================
--- projects/sv/usr.sbin/netdumpsrv/netdump_server.c	Fri Aug 20 15:26:09 2010	(r211527)
+++ projects/sv/usr.sbin/netdumpsrv/netdump_server.c	Fri Aug 20 16:00:36 2010	(r211528)
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <syslog.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <netdb.h>
@@ -54,6 +55,15 @@
 /* Host name length (keep at least as big as INET_ADDRSTRLEN) */
 #define MAXHOSTNAMELEN 256
 
+#define	LOGERR(m, ...)							\
+	syslog(LOG_ERR | LOG_DAEMON, (m), ## __VA_ARGS__)
+#define	LOGERR_PERROR(m)						\
+	syslog(LOG_ERR | LOG_DAEMON, "%s: %s\n", m, strerror(errno))
+#define	LOGINFO(m, ...)							\
+	syslog(LOG_INFO | LOG_DAEMON, (m), ## __VA_ARGS__)
+#define	LOGWARN(m, ...)							\
+	syslog(LOG_WARNING | LOG_DAEMON, (m), ## __VA_ARGS__)
+
 #define	client_ntoa(cl)		inet_ntoa((cl)->ip)
 
 struct netdump_client
@@ -118,7 +128,7 @@ static struct netdump_client *alloc_clie
     client = calloc(1, sizeof(*client));
     if (!client)
     {
-	perror("calloc");
+	LOGERR_PERROR("calloc()");
 	return NULL;
     }
     bcopy(ip, &client->ip, sizeof(*ip));
@@ -154,12 +164,12 @@ static struct netdump_client *alloc_clie
     /* Set up the client socket */
     if ((client->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
     {
-	perror("socket");
+	LOGERR_PERROR("socket()");
 	free(client);
 	return NULL;
     }
     if (fcntl(client->sock, F_SETFL, O_NONBLOCK) == -1) {
-	perror("fcntl(client->sock, F_SETFL, O_NONBLOCK)");
+	LOGERR_PERROR("fcntl()");
 	close(client->sock);
 	free(client);
 	return NULL;
@@ -170,7 +180,7 @@ static struct netdump_client *alloc_clie
     saddr.sin_addr.s_addr = bindip.s_addr;
     saddr.sin_port = htons(0);
     if (bind(client->sock, (struct sockaddr *)&saddr, sizeof(saddr))) {
-	perror("bind");
+	LOGERR_PERROR("bind()");
 	close(client->sock);
 	free(client);
 	return NULL;
@@ -181,7 +191,7 @@ static struct netdump_client *alloc_clie
     saddr.sin_addr.s_addr = ip->s_addr;
     saddr.sin_port = htons(NETDUMP_ACKPORT);
     if (connect(client->sock, (struct sockaddr *)&saddr, sizeof(saddr))) {
-	perror("connect");
+	LOGERR_PERROR("connect()");
 	close(client->sock);
 	free(client);
 	return NULL;
@@ -190,9 +200,9 @@ static struct netdump_client *alloc_clie
 		   * plenty for any 1 client. */
     if (setsockopt(client->sock, SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz)))
     {
-	perror("setsockopt(SOL_SOCKET, SO_RCVBUF)");
-	fprintf(stderr, "Warning: May drop packets from %s due to small receive"
-		" buffer\n", client->hostname);
+	LOGERR_PERROR("setsockopt()");
+	LOGWARN("May drop packets from %s due to small receive buffer\n",
+	    client->hostname);
     }
 
     /* Try info.host.0 through info.host.255 in sequence */
@@ -211,14 +221,12 @@ static struct netdump_client *alloc_clie
 	    {
 		continue;
 	    }
-
-	    fprintf(stderr, "open(\"%s\"): %s\n", client->infofilename,
-			    strerror(errno));
+	    LOGERR("open(\"%s\"): %s\n", client->infofilename, strerror(errno));
 	    continue;
 	}
 	if (!(client->infofile = fdopen(fd, "w")))
 	{
-	    perror("fdopen");
+	    LOGERR_PERROR("fdopen()");
 	    close(fd);
 	    /* XXX */
 	    unlink(client->infofilename);
@@ -238,9 +246,7 @@ static struct netdump_client *alloc_clie
 	    {
 		continue;
 	    }
-
-	    fprintf(stderr, "open(\"%s\"): %s\n", client->corefilename,
-			    strerror(errno));
+	    LOGERR("open(\"%s\"): %s\n", client->corefilename, strerror(errno));
 	    continue;
 	}
 	client->corefd = fd;
@@ -249,8 +255,8 @@ static struct netdump_client *alloc_clie
 
     if (!client->infofile || client->corefd == -1)
     {
-	fprintf(stderr, "Can't create output files for new client %s [%s]\n",
-		client->hostname, client_ntoa(client));
+	LOGERR("Can't create output files for new client %s [%s]\n",
+	    client->hostname, client_ntoa(client));
 	if (client->infofile)
 	{
 	    fclose(client->infofile);
@@ -292,7 +298,7 @@ static void exec_handler(struct netdump_
     pid=fork();
     if (pid == -1)
     {
-	perror("fork");
+	LOGERR_PERROR("fork()");
 	return;
     }
     else if (pid)
@@ -303,11 +309,12 @@ static void exec_handler(struct netdump_
     {
 	close(sock);
 	pidfile_close(pfh);
-	execl(handler_script, handler_script, reason, client_ntoa(client),
+	if (execl(handler_script, handler_script, reason, client_ntoa(client),
 		client->hostname, client->infofilename, client->corefilename,
-		NULL);
-	perror("execl");
-	_exit(1);
+		NULL) == -1) {
+		LOGERR_PERROR("fork()");
+		_exit(1);
+	}
     }
 }
 
@@ -316,7 +323,7 @@ static void handle_timeout(struct netdum
 
     assert(client != NULL);
 
-    printf("Client %s timed out\n", client_ntoa(client));
+    LOGINFO("Client %s timed out\n", client_ntoa(client));
     fputs("Dump incomplete: client timed out\n", client->infofile);
     exec_handler(client, "timeout");
     free_client(client);
@@ -369,7 +376,7 @@ static void send_ack(struct netdump_clie
 	    /* XXX: On EAGAIN, we should probably queue the packet to be sent
 	     * when the socket is writable... but that's too much effort, since
 	     * it's mostly harmless to wait for the client to retransmit. */
-	    perror("sendto");
+	    LOGERR_PERROR("send()");
 	}
     }
     while (tryagain);
@@ -407,8 +414,8 @@ static int handle_herald(struct sockaddr
     fprintf(client->infofile, "Dump from %s [%s]\n", client->hostname,
 	    client_ntoa(client));
 
-    printf("New dump from client %s [%s] (to %s)\n", client->hostname,
-	    client_ntoa(client), client->corefilename);
+    LOGINFO("New dump from client %s [%s] (to %s)\n", client->hostname,
+        client_ntoa(client), client->corefilename);
 
     send_ack(client, msg);
 
@@ -436,8 +443,8 @@ static int handle_kdh(struct netdump_cli
     
     if (msg->hdr.len < sizeof(struct kerneldumpheader))
     {
-	fprintf(stderr, "Bad KDH from %s [%s]: packet too small\n",
-		client->hostname, client_ntoa(client));
+	LOGERR("Bad KDH from %s [%s]: packet too small\n", client->hostname,
+	    client_ntoa(client));
 	fputs("Bad KDH: packet too small\n", f);
 	fflush(f);
 	send_ack(client, msg);
@@ -467,9 +474,7 @@ static int handle_kdh(struct netdump_cli
     fprintf(f, "  Header parity check: %s\n", parity_check ? "Fail" : "Pass");
     fflush(f);
 
-    fprintf(stdout, "(KDH from %s [%s])", client->hostname,
-	    client_ntoa(client));
-    fflush(stdout);
+    LOGINFO("(KDH from %s [%s])", client->hostname, client_ntoa(client));
 
     send_ack(client, msg);
     
@@ -491,14 +496,13 @@ static int handle_vmcore(struct netdump_
     if (msg->hdr.seqno % 11523 == 0)
     {
 	/* Approximately every 16MB with MTU of 1500 */
-	putc('.', stdout);
-	fflush(stdout);
+	LOGINFO(".");
     }
 
     if (pwrite(client->corefd, msg->data, msg->hdr.len, msg->hdr.offset) == -1)
     {
-	fprintf(stderr, "pwrite (for client %s [%s]): %s\n", client->hostname,
-		client_ntoa(client), strerror(errno));
+	LOGERR("pwrite (for client %s [%s]): %s\n", client->hostname,
+	    client_ntoa(client), strerror(errno));
 	fprintf(client->infofile, "Dump unsuccessful: write error at offset %08"PRIx64": %s\n",
 		msg->hdr.offset, strerror(errno));
 	exec_handler(client, "error");
@@ -522,9 +526,8 @@ static int handle_finish(struct netdump_
     }
 
 
-    printf("\nCompleted dump from client %s [%s]\n", client->hostname,
-	    client_ntoa(client));
-    fflush(stdout);
+    LOGINFO("\nCompleted dump from client %s [%s]\n", client->hostname,
+	client_ntoa(client));
     fputs("Dump complete\n", client->infofile);
 
     /* Do this before we free the client */
@@ -563,8 +566,8 @@ static int receive_message(int sock, str
 
     if ((size_t)len < sizeof(struct netdump_msg_hdr))
     {
-	fprintf(stderr, "Ignoring runt packet from %s (got %zu)\n", fromstr,
-		(size_t)len);
+	LOGERR("Ignoring runt packet from %s (got %zu)\n", fromstr,
+	    (size_t)len);
 	return 0;
     }
 
@@ -576,8 +579,9 @@ static int receive_message(int sock, str
 
     if ((size_t)len < sizeof(struct netdump_msg_hdr) + msg->hdr.len)
     {
-	fprintf(stderr, "Packet too small from %s (got %zu, expected %zu)\n",
-		fromstr, (size_t)len, sizeof(struct netdump_msg_hdr) + msg->hdr.len);
+	LOGERR("Packet too small from %s (got %zu, expected %zu)\n",
+	    fromstr, (size_t)len,
+	    sizeof(struct netdump_msg_hdr) + msg->hdr.len);
 	return 0;
     }
 
@@ -612,8 +616,8 @@ static int handle_packet(struct netdump_
 	    break;
 	default:
 	    freed_client=0;
-	    fprintf(stderr, "Received unknown message type %d from %s\n",
-		    msg->hdr.type, fromstr);
+	    LOGERR("Received unknown message type %d from %s\n",
+		msg->hdr.type, fromstr);
     }
 
     return freed_client;
@@ -653,7 +657,7 @@ static void eventloop()
 		continue;
 	    }
 
-	    perror("select");
+	    LOGERR_PERROR("select()");
 	    /* Errors with select() probably won't go away if we just try to
 	     * select() again */
 	    exit(1);
@@ -675,8 +679,7 @@ static void eventloop()
 
 		if (errno != EAGAIN)
 		{
-		    /* Server socket is broken for some reason */
-		    perror("recvfrom");
+		    LOGERR_PERROR("recvfrom()");
 		    exit(1);
 		}
 	    }
@@ -707,8 +710,8 @@ static void eventloop()
 		if (client && msg.hdr.type != NETDUMP_HERALD &&
 			!client->printed_port_warning)
 		{
-		    printf("Warning: Client %s responding on server port\n",
-			    client->hostname);
+		    LOGWARN("Client %s responding on server port\n",
+			client->hostname);
 		    client->printed_port_warning = 1;
 		}
 
@@ -728,7 +731,7 @@ static void eventloop()
 			continue;
 		    }
 
-		    perror("recvfrom");
+		    LOGERR_PERROR("recvfrom()");
 		    /* Client socket is broken for some reason */
 		    handle_timeout(client);
 		    /* The client pointer is now invalid */
@@ -762,7 +765,7 @@ static void eventloop()
 	timeout_clients();
     }
 
-    puts("Shutting down...");
+    LOGINFO("Shutting down...");
     /* Clients is the head of the list, so clients != NULL iff the list isn't
      * empty. Call it a timeout so that the scripts get run. */
     while (!SLIST_EMPTY(&clients))
@@ -790,7 +793,6 @@ int main(int argc, char **argv)
             printf("Impossible to open the pid file\n");
         exit(1);
     }
-    pidfile_write(pfh);
 
     /* Check argc and set the bindaddr and handler_script */
     switch (argc)
@@ -847,11 +849,18 @@ int main(int argc, char **argv)
     strncpy(dumpdir, argv[1], sizeof(dumpdir)-1);
     dumpdir[sizeof(dumpdir)-1]='\0';
 
+    if (daemon(0, 0) == -1) {
+	pidfile_remove(pfh);
+	perror("daemon()");
+	return 1;
+    }
+    pidfile_write(pfh);
+
     /* Set up the server socket */
     if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
     {
         pidfile_remove(pfh);
-	perror("socket");
+	LOGERR_PERROR("socket()");
 	return 1;
     }
     bzero(&bindaddr, sizeof(bindaddr));
@@ -862,13 +871,13 @@ int main(int argc, char **argv)
     if (bind(sock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)))
     {
         pidfile_remove(pfh);
-	perror("bind");
+	LOGERR_PERROR("bind()");
 	close(sock);
 	return 1;
     }
     if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
         pidfile_remove(pfh);
-	perror("fcntl(sock, F_SETFL, O_NONBLOCK)");
+	LOGERR_PERROR("fcntl()");
 	close(sock);
 	return 1;
     }
@@ -879,7 +888,7 @@ int main(int argc, char **argv)
     if (sigaction(SIGINT, &sa, NULL) || sigaction(SIGTERM, &sa, NULL))
     {
         pidfile_remove(pfh);
-	perror("sigaction");
+	LOGERR_PERROR("sigaction(SIGINT | SIGTERM)");
 	close(sock);
 	return 1;
     }
@@ -889,13 +898,12 @@ int main(int argc, char **argv)
     if (sigaction(SIGCHLD, &sa, NULL))
     {
         pidfile_remove(pfh);
-	perror("sigaction");
+	LOGERR_PERROR("sigaction(SIGCHLD)");
 	close(sock);
 	return 1;
     }
 
-    printf("Waiting for clients.\n");
-    fflush(stdout);
+    LOGINFO("Waiting for clients.\n");
 
     do_shutdown=0;
     eventloop();



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008201600.o7KG0afn041853>