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