738028
diff -Naur libreswan-3.15-orig/programs/addconn/addconn.c libreswan-3.15/programs/addconn/addconn.c
738028
--- libreswan-3.15-orig/programs/addconn/addconn.c	2015-08-24 16:52:43.000000000 -0400
738028
+++ libreswan-3.15/programs/addconn/addconn.c	2015-09-04 09:21:23.866861084 -0400
738028
@@ -64,6 +64,8 @@
738028
  * If DST is not specified, full route table will be returned.
738028
  * 16kB was too small for biggish router, so do 32kB.
738028
  * TODO: This should be dynamic! Fix it in netlink_read_reply().
738028
+ * Note: due to our hack to dodge a bug in NLMSG_OK,
738028
+ * RTNL_BUFSIZE must be less than or equal to USHRT_MAX.
738028
  */
738028
 #define RTNL_BUFSIZE 32768
738028
 
738028
@@ -139,30 +141,34 @@
738028
 static
738028
 ssize_t netlink_read_reply(int sock, char *buf, unsigned int seqnum, __u32 pid)
738028
 {
738028
-	struct nlmsghdr *nlhdr;
738028
-	struct sockaddr_nl sa;
738028
-	socklen_t salen = sizeof(sa);
738028
-	ssize_t readlen = 0;
738028
 	ssize_t msglen = 0;
738028
 
738028
 	/* TODO: use dynamic buf */
738028
-	do {
738028
+	for (;;) {
738028
+		struct sockaddr_nl sa;
738028
+		ssize_t readlen;
738028
+
738028
 		/* Read netlink message, verifying kernel origin. */
738028
 		do {
738028
+			socklen_t salen = sizeof(sa);
738028
+
738028
 			readlen = recvfrom(sock, buf, RTNL_BUFSIZE - msglen, 0,
738028
 					(struct sockaddr *)&sa, &salen);
738028
-			if (readlen < 0)
738028
+			if (readlen < 0 || salen != sizeof(sa))
738028
 				return -1;
738028
 		} while (sa.nl_pid != 0);
738028
 
738028
 		/* Verify it's valid */
738028
-		nlhdr = (struct nlmsghdr *) buf;
738028
+		struct nlmsghdr *nlhdr = (struct nlmsghdr *) buf;
738028
+
738028
 		/*
738028
-		 * CAST TO unsigned short IS TO AVOID netlink.h:NLMSG_OK error
738028
-		 * which triggers a GCC warning in recent GCCs:
738028
+		 * The cast to unsigned short is to dodge an error in
738028
+		 * netlink.h:NLMSG_OK() which triggers a GCC warning in recent
738028
+		 * versions of GCC (2014 August):
738028
 		 * error: comparison between signed and unsigned integer expressions
738028
+		 * Note: as long as RTNL_BUFSIZE <= USHRT_MAX, this is safe.
738028
 		 */
738028
-		if (NLMSG_OK(nlhdr, (unsigned short)readlen) == 0 ||
738028
+		if (!NLMSG_OK(nlhdr, (unsigned short)readlen) ||
738028
 			nlhdr->nlmsg_type == NLMSG_ERROR)
738028
 			return -1;
738028
 
738028
@@ -174,11 +180,16 @@
738028
 		buf += readlen;
738028
 		msglen += readlen;
738028
 
738028
-		/* All done if it's not a multi part */
738028
+		/* all done if it's not a multi part */
738028
 		if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0)
738028
 			break;
738028
-	} while (nlhdr->nlmsg_seq != seqnum ||
738028
-			nlhdr->nlmsg_pid != pid);
738028
+
738028
+		/* all done if this is the one we were searching for */
738028
+		if (nlhdr->nlmsg_seq == seqnum &&
738028
+		    nlhdr->nlmsg_pid == pid)
738028
+			break;
738028
+	}
738028
+
738028
 	return msglen;
738028
 }
738028
 
738028
@@ -188,31 +199,33 @@
738028
 static
738028
 ssize_t netlink_query(char *msgbuf)
738028
 {
738028
-	struct nlmsghdr *nlmsg;
738028
-	int sock;
738028
+	int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
738028
 
738028
-	/* Create socket */
738028
-	if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
738028
+	if (sock < 0) {
738028
 		int e = errno;
738028
-		printf("create netlink socket: (%d: %s)", e, strerror(e));
738028
+
738028
+		printf("create netlink socket failure: (%d: %s)\n", e, strerror(e));
738028
 		return -1;
738028
 	}
738028
 
738028
 	/* Send request */
738028
-	nlmsg = (struct nlmsghdr *)msgbuf;
738028
+	struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;
738028
+
738028
 	if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) {
738028
 		int e = errno;
738028
-		printf("write netlink socket: (%d: %s)", e, strerror(e));
738028
+
738028
+		printf("write netlink socket failure: (%d: %s)\n", e, strerror(e));
738028
 		return -1;
738028
 	}
738028
 
738028
 	/* Read response */
738028
+	errno = 0;	/* in case failure does not set it */
738028
 	ssize_t len = netlink_read_reply(sock, msgbuf, 1, getpid());
738028
 
738028
 	if (len < 0) {
738028
 		int e = errno;
738028
 
738028
-		printf("read netlink socket: (%d: %s)", e, strerror(e));
738028
+		printf("read netlink socket failure: (%d: %s)\n", e, strerror(e));
738028
 		return -1;
738028
 	}
738028
 	close(sock);
738028
@@ -331,11 +344,9 @@
738028
 	 * 1) find out default gateway
738028
 	 * 2) find out src for that default gateway
738028
 	 */
738028
-	if (!has_dst) {
738028
-		if (seeking_src && seeking_gateway) {
738028
-			seeking_src = FALSE;
738028
-			query_again = 1;
738028
-		}
738028
+	if (!has_dst && seeking_src && seeking_gateway) {
738028
+		seeking_src = FALSE;
738028
+		query_again = 1;
738028
 	}
738028
 	if (seeking_gateway) {
738028
 		struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;
738028
@@ -358,19 +369,17 @@
738028
 	struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;
738028
 
738028
 	/*
738028
-	 * CAST TO unsigned short IS TO AVOID netlink.h:NLMSG_OK error
738028
-	 * which triggers a GCC warning in recent GCCs:
738028
+	 * The cast to unsigned short is to dodge an error in
738028
+	 * netlink.h:NLMSG_OK() which triggers a GCC warning in recent
738028
+	 * versions of GCC (2014 August):
738028
 	 * error: comparison between signed and unsigned integer expressions
738028
+	 * Note: as long as RTNL_BUFSIZE <= USHRT_MAX, this is safe.
738028
 	 */
738028
-	for (; NLMSG_OK(nlmsg,  (unsigned short)len); nlmsg = NLMSG_NEXT(nlmsg, len)) {
738028
-		struct rtmsg *rtmsg;
738028
-		struct rtattr *rtattr;
738028
-		int rtlen;
738028
+	for (; NLMSG_OK(nlmsg, (unsigned short)len); nlmsg = NLMSG_NEXT(nlmsg, len)) {
738028
 		char r_interface[IF_NAMESIZE+1];
738028
 		char r_source[ADDRTOT_BUF];
738028
 		char r_gateway[ADDRTOT_BUF];
738028
 		char r_destination[ADDRTOT_BUF];
738028
-		bool ignore;
738028
 
738028
 		if (nlmsg->nlmsg_type == NLMSG_DONE)
738028
 			break;
738028
@@ -378,23 +387,23 @@
738028
 		if (nlmsg->nlmsg_type == NLMSG_ERROR) {
738028
 			printf("netlink error\n");
738028
 			return -1;
738028
-			break;
738028
 		}
738028
 
738028
 		/* ignore all but IPv4 and IPv6 */
738028
-		rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg);
738028
+		struct rtmsg *rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg);
738028
+
738028
 		if (rtmsg->rtm_family != AF_INET &&
738028
 			rtmsg->rtm_family != AF_INET6)
738028
 			continue;
738028
 
738028
 		/* Parse one route entry */
738028
-		r_interface[0] = r_interface[IF_NAMESIZE] = r_source[0] =
738028
-			r_gateway[0] = r_destination[0] = '\0';
738028
-		rtattr = (struct rtattr *) RTM_RTA(rtmsg);
738028
-		rtlen = RTM_PAYLOAD(nlmsg);
738028
-		for (;
738028
-			RTA_OK(rtattr, rtlen);
738028
-			rtattr = RTA_NEXT(rtattr, rtlen)) {
738028
+		zero(&r_interface);
738028
+		r_source[0] = r_gateway[0] = r_destination[0] = '\0';
738028
+
738028
+		struct rtattr *rtattr = (struct rtattr *) RTM_RTA(rtmsg);
738028
+		int rtlen = RTM_PAYLOAD(nlmsg);
738028
+
738028
+		while (RTA_OK(rtattr, rtlen)) {
738028
 			switch (rtattr->rta_type) {
738028
 			case RTA_OIF:
738028
 				if_indextoname(*(int *)RTA_DATA(rtattr),
738028
@@ -417,13 +426,14 @@
738028
 					sizeof(r_destination));
738028
 				break;
738028
 			}
738028
+			rtattr = RTA_NEXT(rtattr, rtlen);
738028
 		}
738028
 
738028
 		/*
738028
 		 * Ignore if not main table.
738028
 		 * Ignore ipsecX or mastX interfaces.
738028
 		 */
738028
-		ignore = rtmsg->rtm_table != RT_TABLE_MAIN ||
738028
+		bool ignore = rtmsg->rtm_table != RT_TABLE_MAIN ||
738028
 			startswith(r_interface, "ipsec") ||
738028
 			startswith(r_interface, "mast");
738028
 
738028
@@ -548,20 +558,23 @@
738028
 int main(int argc, char *argv[])
738028
 {
738028
 	int opt = 0;
738028
-	int autoall = 0;
738028
+	bool autoall = FALSE;
738028
 	int configsetup = 0;
738028
 	int checkconfig = 0;
738028
-	char *export = "export"; /* display export before the foo=bar or not */
738028
-	int listroute = 0, liststart = 0, listignore = 0, listadd = 0,
738028
-		listall = 0, dolist = 0, liststack = 0;
738028
-	struct starter_config *cfg = NULL;
738028
-	err_t err = NULL;
738028
-	char *confdir = NULL;
738028
+	const char *export = "export"; /* display export before the foo=bar or not */
738028
+	bool
738028
+		dolist = FALSE,
738028
+		listadd = FALSE,
738028
+		listroute = FALSE,
738028
+		liststart = FALSE,
738028
+		listignore = FALSE,
738028
+		listall = FALSE,
738028
+		liststack = FALSE;
738028
 	char *configfile = NULL;
738028
-	char *varprefix = "";
738028
+	const char *varprefix = "";
738028
 	int exit_status = 0;
738028
 	struct starter_conn *conn = NULL;
738028
-	char *ctlbase = NULL;
738028
+	const char *ctlbase = NULL;
738028
 	bool resolvip = TRUE; /* default to looking up names */
738028
 
738028
 #if 0
738028
@@ -586,7 +599,7 @@
738028
 			break;
738028
 
738028
 		case 'a':
738028
-			autoall = 1;
738028
+			autoall = TRUE;
738028
 			break;
738028
 
738028
 		case 'D':
738028
@@ -595,11 +608,11 @@
738028
 			break;
738028
 
738028
 		case 'T':
738028
-			configsetup++;
738028
+			configsetup++;	/* ??? is this not idempotent? */
738028
 			break;
738028
 
738028
 		case 'K':
738028
-			checkconfig++;
738028
+			checkconfig++;	/* ??? is this not idempotent? */
738028
 			break;
738028
 
738028
 		case 'N':
738028
@@ -615,33 +628,33 @@
738028
 			break;
738028
 
738028
 		case 'L':
738028
-			listadd = 1;
738028
-			dolist = 1;
738028
+			listadd = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 'r':
738028
-			listroute = 1;
738028
-			dolist = 1;
738028
+			listroute = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 's':
738028
-			liststart = 1;
738028
-			dolist = 1;
738028
+			liststart = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 'S':
738028
-			liststack = 1;
738028
-			dolist = 1;
738028
+			liststack = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 'i':
738028
-			listignore = 1;
738028
-			dolist = 1;
738028
+			listignore = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 'A':
738028
-			listall = 1;
738028
-			dolist = 1;
738028
+			listall = TRUE;
738028
+			dolist = TRUE;
738028
 			break;
738028
 
738028
 		case 'P':
738028
@@ -672,9 +685,7 @@
738028
 		yydebug = 1;
738028
 	}
738028
 
738028
-	/* find config file */
738028
-	if (confdir == NULL)
738028
-		confdir = IPSEC_CONFDIR;
738028
+	char *confdir = IPSEC_CONFDIR;
738028
 
738028
 	if (configfile == NULL) {
738028
 		/* ??? see code clone in programs/readwriteconf/readwriteconf.c */
738028
@@ -694,29 +705,32 @@
738028
 
738028
 	starter_use_log(verbose != 0, TRUE, verbose == 0);
738028
 
738028
-	err = NULL;	/* reset to no error */
738028
-
738028
 	if (configsetup || checkconfig || dolist) {
738028
 		/* skip if we have no use for them... causes delays */
738028
 		resolvip = FALSE;
738028
 	}
738028
 
738028
-	cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup);
738028
+	struct starter_config *cfg = NULL;
738028
 
738028
-	if (cfg == NULL) {
738028
-		fprintf(stderr, "cannot load config '%s': %s\n",
738028
-			configfile, err);
738028
-		exit(3);
738028
-	} else if (checkconfig) {
738028
-		confread_free(cfg);
738028
-		exit(0);
738028
+	{
738028
+		err_t err = NULL;
738028
+
738028
+		cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup);
738028
+
738028
+		if (cfg == NULL) {
738028
+			fprintf(stderr, "cannot load config '%s': %s\n",
738028
+				configfile, err);
738028
+			exit(3);
738028
+		} else if (checkconfig) {
738028
+			confread_free(cfg);
738028
+			exit(0);
738028
+		}
738028
 	}
738028
 
738028
 	if (autoall) {
738028
 		if (verbose)
738028
 			printf("loading all conns according to their auto= settings\n");
738028
 
738028
-
738028
 		/*
738028
 		 * Load all conns marked as auto=add or better.
738028
 		 * First, do the auto=route and auto=add conns to quickly
738028
@@ -727,7 +741,6 @@
738028
 		if (verbose)
738028
 			printf("  Pass #1: Loading auto=add, auto=route and auto=start connections\n");
738028
 
738028
-
738028
 		for (conn = cfg->conns.tqh_first;
738028
 			conn != NULL;
738028
 			conn = conn->link.tqe_next) {
738028
@@ -828,7 +841,6 @@
738028
 							conn->
738028
 							strings[KSF_CONNALIAS]
738028
 							)) {
738028
-
738028
 						if (conn->state ==
738028
 							STATE_ADDED) {
738028
 							printf("\nalias: %s conn %s already added\n",
738028
@@ -875,12 +887,10 @@
738028
 			printf("%s ", conn->name);
738028
 		printf("\n");
738028
 	} else {
738028
-
738028
 		if (listadd) {
738028
 			if (verbose)
738028
 				printf("listing all conns marked as auto=add\n");
738028
 
738028
-
738028
 			/* list all conns marked as auto=add */
738028
 			for (conn = cfg->conns.tqh_first;
738028
 				conn != NULL;
738028
@@ -893,7 +903,6 @@
738028
 			if (verbose)
738028
 				printf("listing all conns marked as auto=route and auto=start\n");
738028
 
738028
-
738028
 			/*
738028
 			 * list all conns marked as auto=route or start or
738028
 			 * better
738028
@@ -911,7 +920,6 @@
738028
 			if (verbose)
738028
 				printf("listing all conns marked as auto=start\n");
738028
 
738028
-
738028
 			/* list all conns marked as auto=start */
738028
 			for (conn = cfg->conns.tqh_first;
738028
 				conn != NULL;
738028
@@ -925,7 +933,6 @@
738028
 			if (verbose)
738028
 				printf("listing all conns marked as auto=ignore\n");
738028
 
738028
-
738028
 			/* list all conns marked as auto=start */
738028
 			for (conn = cfg->conns.tqh_first;
738028
 				conn != NULL;
738028
@@ -942,14 +949,14 @@
738028
 
738028
 		for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) {
738028
 			if (strstr(kd->keyname, "protostack")) {
738028
-				if (cfg->setup.strings[kd->field])
738028
+				if (cfg->setup.strings[kd->field]) {
738028
 					printf("%s\n",
738028
 						cfg->setup.strings[kd->field]);
738028
-				else
738028
+				} else {
738028
 					/* implicit default */
738028
 					printf("netkey\n");
738028
+				}
738028
 			}
738028
-
738028
 		}
738028
 		confread_free(cfg);
738028
 		exit(0);
738028
@@ -1008,7 +1015,6 @@
738028
 		}
738028
 		confread_free(cfg);
738028
 		exit(0);
738028
-
738028
 	}
738028
 
738028
 	confread_free(cfg);