Update strace to 4.18.

Noteworthy changes in release 4.18 (2017-07-05)
===============================================

* Improvements
  * Implemented decoding of SCM_TIMESTAMP* control messages.
  * Implemented decoding of netlink NLMSG_DONE messages.
  * Implemented decoding of netlink generic nlmsg_type and nlmsg_flags.
  * Implemented decoding of NETLINK_AUDIT, NETLINK_NETFILTER, NETLINK_ROUTE,
    NETLINK_SELINUX, NETLINK_SOCK_DIAG, and NETLINK_XFRM message types.
  * Implemented decoding of NETLINK_GENERIC protocol families.
  * Implemented basic protocol specific decoding of AF_INET, AF_INET6,
    AF_NETLINK, AF_PACKET, AF_SMC, and AF_UNIX messages of NETLINK_SOCK_DIAG.
  * Implemented basic decoding of netlink attributes.
  * Implemented basic protocol specific decoding of AF_INET, AF_NETLINK,
    AF_PACKET, AF_SMC, and AF_UNIX netlink attributes of NETLINK_SOCK_DIAG.
  * Implemented decoding of inet_diag_msg, netlink_diag_msg, and unix_diag_msg
    netlink attributes of NETLINK_SOCK_DIAG.
  * Updated lists of ARPHRD_*, KEYCTL_*, NDIAG_SHOW_*, RTM_*, SCM_*, SCTP_*,
    SO_*, V4L2_*, and prctl ARCH_* constants.
  * Updated lists of ioctl commands from Linux 4.12.

* Bug fixes
  * In interactive mode (-I2), those signals that were blocked at startup
    will remain blocked for the whole period of strace execution.
  * strace no longer resets SIGCHLD handler in tracees to the default action.
  * When traced command is terminated by a blocked signal, strace unblocks
    that signal to ensure its own termination with the same signal.
  * Fixed corner cases in decoding of old sigaction syscall.
  * Fixed build with old kernel headers on mips.
  * Fixed build on aarch64 and tile with glibc >= 2.26.
  * Fixed build on arc and nios2.

Bug: N/A
Test: strace date
Change-Id: Ib34873ff60824b04f67332380c3460721f66002e
diff --git a/socketutils.c b/socketutils.c
index ef8269c..ce4e524 100644
--- a/socketutils.c
+++ b/socketutils.c
@@ -31,22 +31,21 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
-#include <linux/netlink.h>
+#include "netlink.h"
 #include <linux/sock_diag.h>
 #include <linux/inet_diag.h>
 #include <linux/unix_diag.h>
 #include <linux/netlink_diag.h>
 #include <linux/rtnetlink.h>
+#if HAVE_LINUX_GENETLINK_H
+#include <linux/genetlink.h>
+#endif
 
 #include <sys/un.h>
 #ifndef UNIX_PATH_MAX
 # define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) 0)->sun_path)
 #endif
 
-#ifndef NETLINK_SOCK_DIAG
-# define NETLINK_SOCK_DIAG 4
-#endif
-
 typedef struct {
 	unsigned long inode;
 	char *details;
@@ -57,23 +56,29 @@
 #define CACHE_MASK (CACHE_SIZE - 1)
 
 static int
-cache_and_print_inode_details(const unsigned long inode, char *const details)
+cache_inode_details(const unsigned long inode, char *const details)
 {
 	cache_entry *e = &cache[inode & CACHE_MASK];
 	free(e->details);
 	e->inode = inode;
 	e->details = details;
 
-	tprints(details);
 	return 1;
 }
 
-bool
-print_sockaddr_by_inode_cached(const unsigned long inode)
+static const char *
+get_sockaddr_by_inode_cached(const unsigned long inode)
 {
 	const cache_entry *const e = &cache[inode & CACHE_MASK];
-	if (e && inode == e->inode) {
-		tprints(e->details);
+	return (e && inode == e->inode) ? e->details : NULL;
+}
+
+static bool
+print_sockaddr_by_inode_cached(const unsigned long inode)
+{
+	const char *const details = get_sockaddr_by_inode_cached(inode);
+	if (details) {
+		tprints(details);
 		return true;
 	}
 	return false;
@@ -128,9 +133,10 @@
 }
 
 static int
-inet_parse_response(const char *const proto_name, const void *const data,
-		    const int data_len, const unsigned long inode)
+inet_parse_response(const void *const data, const int data_len,
+		    const unsigned long inode, void *opaque_data)
 {
+	const char *const proto_name = opaque_data;
 	const struct inet_diag_msg *const diag_msg = data;
 	static const char zero_addr[sizeof(struct in6_addr)];
 	socklen_t addr_size, text_size;
@@ -140,7 +146,7 @@
 	if (diag_msg->idiag_inode != inode)
 		return 0;
 
-	switch(diag_msg->idiag_family) {
+	switch (diag_msg->idiag_family) {
 		case AF_INET:
 			addr_size = sizeof(struct in_addr);
 			text_size = INET_ADDRSTRLEN;
@@ -178,14 +184,15 @@
 			return false;
 	}
 
-	return cache_and_print_inode_details(inode, details);
+	return cache_inode_details(inode, details);
 }
 
 static bool
 receive_responses(const int fd, const unsigned long inode,
-		  const char *proto_name,
-		  int (* parser) (const char *, const void *,
-				  int, unsigned long))
+		  const unsigned long expected_msg_type,
+		  int (*parser)(const void *, int,
+				unsigned long, void *),
+		  void *opaque_data)
 {
 	static union {
 		struct nlmsghdr hdr;
@@ -220,10 +227,10 @@
 		if (!NLMSG_OK(h, ret))
 			return false;
 		for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
-			if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY)
+			if (h->nlmsg_type != expected_msg_type)
 				return false;
-			const int rc = parser(proto_name, NLMSG_DATA(h),
-					      h->nlmsg_len, inode);
+			const int rc = parser(NLMSG_DATA(h),
+					      h->nlmsg_len, inode, opaque_data);
 			if (rc > 0)
 				return true;
 			if (rc < 0)
@@ -234,14 +241,6 @@
 }
 
 static bool
-inet_print(const int fd, const int family, const int protocol,
-	   const unsigned long inode, const char *proto_name)
-{
-	return inet_send_query(fd, family, protocol)
-		&& receive_responses(fd, inode, proto_name, inet_parse_response);
-}
-
-static bool
 unix_send_query(const int fd, const unsigned long inode)
 {
 	struct {
@@ -264,9 +263,10 @@
 }
 
 static int
-unix_parse_response(const char *proto_name, const void *data,
-		    const int data_len, const unsigned long inode)
+unix_parse_response(const void *data, const int data_len,
+		    const unsigned long inode, void *opaque_data)
 {
+	const char *proto_name = opaque_data;
 	const struct unix_diag_msg *diag_msg = data;
 	struct rtattr *attr;
 	int rta_len = data_len - NLMSG_LENGTH(sizeof(*diag_msg));
@@ -337,7 +337,7 @@
 		     peer_str, path_str) < 0)
 		return -1;
 
-	return cache_and_print_inode_details(inode, details);
+	return cache_inode_details(inode, details);
 }
 
 static bool
@@ -362,9 +362,10 @@
 }
 
 static int
-netlink_parse_response(const char *proto_name, const void *data,
-		    const int data_len, const unsigned long inode)
+netlink_parse_response(const void *data, const int data_len,
+		       const unsigned long inode, void *opaque_data)
 {
+	const char *proto_name = opaque_data;
 	const struct netlink_diag_msg *const diag_msg = data;
 	const char *netlink_proto;
 	char *details;
@@ -381,12 +382,7 @@
 				diag_msg->ndiag_protocol);
 
 	if (netlink_proto) {
-		static const char netlink_prefix[] = "NETLINK_";
-		const size_t netlink_prefix_len =
-			sizeof(netlink_prefix) -1;
-		if (strncmp(netlink_proto, netlink_prefix,
-			    netlink_prefix_len) == 0)
-			netlink_proto += netlink_prefix_len;
+		netlink_proto = STR_STRIP_PREFIX(netlink_proto, "NETLINK_");
 		if (asprintf(&details, "%s:[%s:%u]", proto_name,
 			     netlink_proto, diag_msg->ndiag_portid) < 0)
 			return -1;
@@ -396,58 +392,71 @@
 			return -1;
 	}
 
-	return cache_and_print_inode_details(inode, details);
+	return cache_inode_details(inode, details);
 }
 
-static bool
-unix_print(const int fd, const unsigned long inode)
+static const char *
+unix_get(const int fd, const unsigned long inode)
 {
 	return unix_send_query(fd, inode)
-		&& receive_responses(fd, inode, "UNIX", unix_parse_response);
+		&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
+				     unix_parse_response, (void *) "UNIX")
+		? get_sockaddr_by_inode_cached(inode) : NULL;
 }
 
-static bool
-tcp_v4_print(const int fd, const unsigned long inode)
+static const char *
+inet_get(const int fd, const int family, const int protocol,
+	 const unsigned long inode, const char *proto_name)
 {
-	return inet_print(fd, AF_INET, IPPROTO_TCP, inode, "TCP");
+	return inet_send_query(fd, family, protocol)
+		&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
+				     inet_parse_response, (void *) proto_name)
+		? get_sockaddr_by_inode_cached(inode) : NULL;
 }
 
-static bool
-udp_v4_print(const int fd, const unsigned long inode)
+static const char *
+tcp_v4_get(const int fd, const unsigned long inode)
 {
-	return inet_print(fd, AF_INET, IPPROTO_UDP, inode, "UDP");
+	return inet_get(fd, AF_INET, IPPROTO_TCP, inode, "TCP");
 }
 
-static bool
-tcp_v6_print(const int fd, const unsigned long inode)
+static const char *
+udp_v4_get(const int fd, const unsigned long inode)
 {
-	return inet_print(fd, AF_INET6, IPPROTO_TCP, inode, "TCPv6");
+	return inet_get(fd, AF_INET, IPPROTO_UDP, inode, "UDP");
 }
 
-static bool
-udp_v6_print(const int fd, const unsigned long inode)
+static const char *
+tcp_v6_get(const int fd, const unsigned long inode)
 {
-	return inet_print(fd, AF_INET6, IPPROTO_UDP, inode, "UDPv6");
+	return inet_get(fd, AF_INET6, IPPROTO_TCP, inode, "TCPv6");
 }
 
-static bool
-netlink_print(const int fd, const unsigned long inode)
+static const char *
+udp_v6_get(const int fd, const unsigned long inode)
+{
+	return inet_get(fd, AF_INET6, IPPROTO_UDP, inode, "UDPv6");
+}
+
+static const char *
+netlink_get(const int fd, const unsigned long inode)
 {
 	return netlink_send_query(fd, inode)
-		&& receive_responses(fd, inode, "NETLINK",
-				     netlink_parse_response);
+		&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
+				     netlink_parse_response, (void *) "NETLINK")
+		? get_sockaddr_by_inode_cached(inode) : NULL;
 }
 
 static const struct {
 	const char *const name;
-	bool (*const print)(int, unsigned long);
+	const char * (*const get)(int, unsigned long);
 } protocols[] = {
-	[SOCK_PROTO_UNIX] = { "UNIX", unix_print },
-	[SOCK_PROTO_TCP] = { "TCP", tcp_v4_print },
-	[SOCK_PROTO_UDP] = { "UDP", udp_v4_print },
-	[SOCK_PROTO_TCPv6] = { "TCPv6", tcp_v6_print },
-	[SOCK_PROTO_UDPv6] = { "UDPv6", udp_v6_print },
-	[SOCK_PROTO_NETLINK] = { "NETLINK", netlink_print }
+	[SOCK_PROTO_UNIX] = { "UNIX", unix_get },
+	[SOCK_PROTO_TCP] = { "TCP", tcp_v4_get },
+	[SOCK_PROTO_UDP] = { "UDP", udp_v4_get },
+	[SOCK_PROTO_TCPv6] = { "TCPv6", tcp_v6_get },
+	[SOCK_PROTO_UDPv6] = { "UDPv6", udp_v6_get },
+	[SOCK_PROTO_NETLINK] = { "NETLINK", netlink_get }
 };
 
 enum sock_proto
@@ -462,39 +471,179 @@
 	return SOCK_PROTO_UNKNOWN;
 }
 
-/* Given an inode number of a socket, print out the details
- * of the ip address and port. */
-
-bool
-print_sockaddr_by_inode(const unsigned long inode, const enum sock_proto proto)
+static const char *
+get_sockaddr_by_inode_uncached(const unsigned long inode,
+			       const enum sock_proto proto)
 {
 	if ((unsigned int) proto >= ARRAY_SIZE(protocols) ||
-	    (proto != SOCK_PROTO_UNKNOWN && !protocols[proto].print))
-		return false;
+	    (proto != SOCK_PROTO_UNKNOWN && !protocols[proto].get))
+		return NULL;
 
 	const int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
 	if (fd < 0)
-		return false;
-	bool r = false;
+		return NULL;
+	const char *details = NULL;
 
 	if (proto != SOCK_PROTO_UNKNOWN) {
-		r = protocols[proto].print(fd, inode);
-		if (!r) {
-			tprintf("%s:[%lu]", protocols[proto].name, inode);
-			r = true;
-		}
+		details = protocols[proto].get(fd, inode);
 	} else {
 		unsigned int i;
 		for (i = (unsigned int) SOCK_PROTO_UNKNOWN + 1;
 		     i < ARRAY_SIZE(protocols); ++i) {
-			if (!protocols[i].print)
+			if (!protocols[i].get)
 				continue;
-			r = protocols[i].print(fd, inode);
-			if (r)
+			details = protocols[i].get(fd, inode);
+			if (details)
 				break;
 		}
 	}
 
 	close(fd);
-	return r;
+	return details;
 }
+
+static bool
+print_sockaddr_by_inode_uncached(const unsigned long inode,
+				 const enum sock_proto proto)
+{
+	const char *details = get_sockaddr_by_inode_uncached(inode, proto);
+
+	if (details) {
+		tprints(details);
+		return true;
+	}
+
+	if ((unsigned int) proto < ARRAY_SIZE(protocols) &&
+	    protocols[proto].name) {
+		tprintf("%s:[%lu]", protocols[proto].name, inode);
+		return true;
+	}
+
+	return false;
+}
+
+/* Given an inode number of a socket, return its protocol details.  */
+const char *
+get_sockaddr_by_inode(struct tcb *const tcp, const int fd,
+		      const unsigned long inode)
+{
+	const char *details = get_sockaddr_by_inode_cached(inode);
+	return details ? details :
+		get_sockaddr_by_inode_uncached(inode, getfdproto(tcp, fd));
+}
+
+/* Given an inode number of a socket, print out its protocol details.  */
+bool
+print_sockaddr_by_inode(struct tcb *const tcp, const int fd,
+			const unsigned long inode)
+{
+	return print_sockaddr_by_inode_cached(inode) ? true :
+		print_sockaddr_by_inode_uncached(inode, getfdproto(tcp, fd));
+}
+
+#ifdef HAVE_LINUX_GENETLINK_H
+/*
+ * Managing the cache for decoding communications of Netlink GENERIC protocol
+ *
+ * As name shown Netlink GENERIC protocol is generic protocol. The
+ * numbers of msg types used in the protocol are not defined
+ * statically. Kernel defines them on demand.  So the xlat converted
+ * from header files doesn't help for decoding the protocol. Following
+ * codes are building xlat(dyxlat) at runtime.
+ */
+static bool
+genl_send_dump_families(const int fd)
+{
+	struct {
+		const struct nlmsghdr nlh;
+		struct genlmsghdr gnlh;
+	} req = {
+		.nlh = {
+			.nlmsg_len = sizeof(req),
+			.nlmsg_type = GENL_ID_CTRL,
+			.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+		},
+		.gnlh = {
+			.cmd = CTRL_CMD_GETFAMILY,
+		}
+	};
+	return send_query(fd, &req, sizeof(req));
+}
+
+static int
+genl_parse_families_response(const void *const data,
+			     const int data_len, const unsigned long inode,
+			     void *opaque_data)
+{
+	struct dyxlat *const dyxlat = opaque_data;
+	const struct genlmsghdr *const gnlh = data;
+	struct rtattr *attr;
+	int rta_len = data_len - NLMSG_LENGTH(sizeof(*gnlh));
+
+	char *name = NULL;
+	unsigned int name_len = 0;
+	uint16_t *id = NULL;
+
+	if (rta_len < 0)
+		return -1;
+	if (gnlh->cmd != CTRL_CMD_NEWFAMILY)
+		return -1;
+	if (gnlh->version != 2)
+		return -1;
+
+	for (attr = (struct rtattr *) (gnlh + 1);
+	     RTA_OK(attr, rta_len);
+	     attr = RTA_NEXT(attr, rta_len)) {
+		switch (attr->rta_type) {
+		case CTRL_ATTR_FAMILY_NAME:
+			if (!name) {
+				name = RTA_DATA(attr);
+				name_len = RTA_PAYLOAD(attr);
+			}
+			break;
+		case CTRL_ATTR_FAMILY_ID:
+			if (!id && RTA_PAYLOAD(attr) == sizeof(*id))
+				id = RTA_DATA(attr);
+			break;
+		}
+
+		if (name && id) {
+			dyxlat_add_pair(dyxlat, *id, name, name_len);
+			name = NULL;
+			id = NULL;
+		}
+	}
+
+	return 0;
+}
+
+const struct xlat *
+genl_families_xlat(void)
+{
+	static struct dyxlat *dyxlat;
+
+	if (!dyxlat) {
+		dyxlat = dyxlat_alloc(32);
+
+		int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+		if (fd < 0)
+			goto out;
+
+		if (genl_send_dump_families(fd))
+			receive_responses(fd, 0, GENL_ID_CTRL,
+					  genl_parse_families_response, dyxlat);
+		close(fd);
+	}
+
+out:
+	return dyxlat_get(dyxlat);
+}
+
+#else /* !HAVE_LINUX_GENETLINK_H */
+
+const struct xlat *
+genl_families_xlat(void)
+{
+	return NULL;
+}
+#endif