Use syslog for log output

We should be logging to syslog rather than stdout/stderr

This change implements logging to syslog (via vsyslog()), and adds a
couple of arguments to control debug behaviour.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/inarp.c b/inarp.c
index c63d0a2..08a0c30 100644
--- a/inarp.c
+++ b/inarp.c
@@ -15,12 +15,13 @@
  * limitations under the License.
  ******************************************************************************/
 
-#include <err.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <syslog.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -62,8 +63,31 @@
 	int			nl_sd;
 	struct interface	*interfaces;
 	unsigned int		n_interfaces;
+	bool			syslog;
+	bool			debug;
 };
 
+static __attribute__((format(printf, 3, 4)))
+	void inarp_log(struct inarp_ctx *inarp,
+		int priority,
+		const char *format, ...)
+{
+	va_list ap;
+
+	if (priority > LOG_INFO && !inarp->debug)
+		return;
+
+	va_start(ap, format);
+	if (inarp->syslog) {
+		vsyslog(priority, format, ap);
+	} else {
+		vprintf(format, ap);
+		printf("\n");
+	}
+
+	va_end(ap);
+}
+
 /* helpers for rtnetlink message iteration */
 #define for_each_nlmsg(buf, nlmsg, len) \
 	for (nlmsg = (struct nlmsghdr *)buf; \
@@ -74,7 +98,7 @@
 	for (rta = (struct rtattr *)(buf); RTA_OK(rta, attrlen); \
 			rta = RTA_NEXT(rta, attrlen))
 
-static int send_arp_packet(int fd,
+static int send_arp_packet(struct inarp_ctx *inarp,
 		int ifindex,
 		const struct eth_addr *src_mac,
 		const struct in_addr *src_ip,
@@ -117,10 +141,11 @@
 	memcpy(&arp.dest_ip, dest_ip, sizeof(arp.dest_ip));
 
 	/* send the packet */
-	rc = sendto(fd, &arp, sizeof(arp), 0,
+	rc = sendto(inarp->arp_sd, &arp, sizeof(arp), 0,
 			(struct sockaddr *)&addr, sizeof(addr));
 	if (rc < 0)
-		warn("failure sending ARP response");
+		inarp_log(inarp, LOG_NOTICE,
+				"Failure sending ARP response: %m");
 
 	return rc;
 }
@@ -147,21 +172,25 @@
 	return ioctl(fd, type, ifreq);
 }
 
-static int get_local_ipaddr(int fd, const char *ifname, struct in_addr *addr)
+static int get_local_ipaddr(struct inarp_ctx *inarp,
+		const char *ifname, struct in_addr *addr)
 {
 	struct sockaddr_in *sa;
 	struct ifreq ifreq;
 	int rc;
 
-	rc = do_ifreq(fd, SIOCGIFADDR, ifname, &ifreq);
+	rc = do_ifreq(inarp->arp_sd, SIOCGIFADDR, ifname, &ifreq);
 	if (rc) {
-		warn("Error querying local IP address for %s", ifname);
+		inarp_log(inarp, LOG_WARNING,
+			"Error querying local IP address for %s: %m",
+			ifname);
 		return -1;
 	}
 
 	if (ifreq.ifr_addr.sa_family != AF_INET) {
-		warnx("Unknown address family %d in address response",
-				ifreq.ifr_addr.sa_family);
+		inarp_log(inarp, LOG_WARNING,
+			"Unknown address family %d in address response",
+			ifreq.ifr_addr.sa_family);
 		return -1;
 	}
 
@@ -196,7 +225,7 @@
 	/* create our socket to listen for rtnetlink events */
 	inarp->nl_sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
 	if (inarp->nl_sd < 0) {
-		warn("Error opening netlink socket");
+		inarp_log(inarp, LOG_ERR, "Error opening netlink socket: %m");
 		return -1;
 	}
 
@@ -206,7 +235,8 @@
 
 	rc = bind(inarp->nl_sd, (struct sockaddr *)&addr, sizeof(addr));
 	if (rc) {
-		warn("Error binding to netlink address");
+		inarp_log(inarp, LOG_ERR,
+				"Error binding to netlink address: %m");
 		goto err_close;
 	}
 
@@ -220,7 +250,7 @@
 
 	rc = send(inarp->nl_sd, &msg, sizeof(msg), MSG_NOSIGNAL);
 	if (rc != sizeof(msg)) {
-		warn("Failed to query current links");
+		inarp_log(inarp, LOG_ERR, "Failed to query current links: %m");
 		goto err_close;
 	}
 
@@ -239,8 +269,8 @@
 	if (!iface)
 		return;
 
-	printf("dropping interface: %s, [%s]\n", iface->ifname,
-			eth_mac_to_str(&iface->eth_addr));
+	inarp_log(inarp, LOG_NOTICE, "dropping interface: %s, [%s]",
+			iface->ifname, eth_mac_to_str(&iface->eth_addr));
 
 	/* find the index of the array element to remove */
 	i = iface - inarp->interfaces;
@@ -289,11 +319,10 @@
 		}
 	}
 
-	printf("%s interface: %s, [%s]\n",
+	inarp_log(inarp, LOG_NOTICE, "%s interface: %s, [%s]",
 			new ? "adding" : "updating",
 			iface->ifname,
 			eth_mac_to_str(&iface->eth_addr));
-	fflush(stdout);
 }
 
 static void netlink_nlmsg(struct inarp_ctx *inarp, struct nlmsghdr *nlmsg)
@@ -327,7 +356,7 @@
 
 	len = recv(inarp->nl_sd, &buf, sizeof(buf), 0);
 	if (len < 0) {
-		warn("Error receiving netlink msg");
+		inarp_log(inarp, LOG_NOTICE, "Error receiving netlink msg");
 		return;
 	}
 
@@ -351,7 +380,8 @@
 	if (len <= 0) {
 		if (errno == EINTR)
 			return;
-		err(EXIT_FAILURE, "Error recieving ARP packet");
+		inarp_log(inarp, LOG_WARNING,
+				"Error recieving ARP packet");
 	}
 
 	/*
@@ -380,36 +410,51 @@
 	if (memcmp(&iface->eth_addr, inarp_req.eh.h_dest, ETH_ALEN))
 		return;
 
-	printf("src mac:  %s\n", eth_mac_to_str(&inarp_req.src_mac));
-	printf("src ip:   %s\n", inet_ntoa(inarp_req.src_ip));
+	inarp_log(inarp, LOG_DEBUG,
+			"request from src mac: %s",
+			eth_mac_to_str(&inarp_req.src_mac));
 
-	rc = get_local_ipaddr(inarp->arp_sd, iface->ifname,
-			&local_ip);
+	rc = get_local_ipaddr(inarp, iface->ifname, &local_ip);
 	/* if we don't have a local IP address to send, just drop the
 	 * request */
 	if (rc)
 		return;
+	inarp_log(inarp, LOG_DEBUG,
+			"responding with %s ip %s",
+			eth_mac_to_str(&iface->eth_addr),
+			inet_ntoa(local_ip));
 
-	printf("local mac: %s\n", eth_mac_to_str(&iface->eth_addr));
-	printf("local ip: %s\n", inet_ntoa(local_ip));
-
-	send_arp_packet(inarp->arp_sd, iface->ifindex,
+	send_arp_packet(inarp, iface->ifindex,
 			&inarp_req.dest_mac,
 			&local_ip,
 			&inarp_req.src_mac,
 			&inarp_req.src_ip);
 }
 
-int main(void)
+int main(int argc, char **argv)
 {
 	struct inarp_ctx inarp;
-	int ret;
+	int ret, i;
 
 	memset(&inarp, 0, sizeof(inarp));
 
+	inarp.syslog = true;
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp(argv[i], "--debug"))
+			inarp.debug = true;
+		else if (!strcmp(argv[i], "--no-syslog"))
+			inarp.syslog = false;
+	}
+
+	if (inarp.syslog)
+		openlog("inarp", 0, LOG_DAEMON);
+
 	inarp.arp_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
-	if (inarp.arp_sd < 0)
-		err(EXIT_FAILURE, "Error opening ARP socket");
+	if (inarp.arp_sd < 0) {
+		inarp_log(&inarp, LOG_ERR, "Error opening ARP socket");
+		exit(EXIT_FAILURE);
+	}
 
 	ret = init_netlink(&inarp);
 	if (ret)
@@ -424,8 +469,10 @@
 		pollfds[1].events = POLLIN;
 
 		ret = poll(pollfds, 2, -1);
-		if (ret < 0)
-			err(EXIT_FAILURE, "Poll failed");
+		if (ret < 0) {
+			inarp_log(&inarp, LOG_ERR, "poll failed, exiting");
+			break;
+		}
 
 		if (pollfds[0].revents)
 			arp_recv(&inarp);