ifr-related hunks: fix unaligned access on strict-alignment 64-bit

first+last hunks: handle usb serial devices via ucomnames

Index: conserver/cutil.c
--- conserver/cutil.c.orig
+++ conserver/cutil.c
@@ -5,6 +5,7 @@
  */
 
 #include <compat.h>
+#include <sys/sysctl.h>
 
 #include <cutil.h>
 #include <version.h>
@@ -1852,7 +1853,7 @@ ProbeInterfaces(in_addr_t bindAddr)
 {
 # ifdef SIOCGIFCONF
     struct ifconf ifc;
-    struct ifreq *ifr;
+    struct ifreq ifr;
 #  ifdef SIOCGIFFLAGS
     struct ifreq ifrcopy;
 #  endif
@@ -1921,7 +1922,7 @@ ProbeInterfaces(in_addr_t bindAddr)
      * than loop through looking for valid interfaces that are up
      * twice, huh?
      */
-    count = ifc.ifc_len / sizeof(*ifr);
+    count = ifc.ifc_len / sizeof(ifr);
     CONDDEBUG((1, "ProbeInterfaces(): ifc_len==%d max_count==%d",
 	       ifc.ifc_len, count));
 
@@ -1940,21 +1941,21 @@ ProbeInterfaces(in_addr_t bindAddr)
 
     for (m = r = 0; r < ifc.ifc_len;) {
 	struct sockaddr *sa;
-	ifr = (struct ifreq *)&ifc.ifc_buf[r];
-	sa = (struct sockaddr *)&ifr->ifr_addr;
+	memcpy(&ifr, &ifc.ifc_buf[r], sizeof(ifr));
+	sa = (struct sockaddr *)&ifr.ifr_addr;
 	/* don't use less than a ifreq sized chunk */
-	if ((ifc.ifc_len - r) < sizeof(*ifr))
+	if ((ifc.ifc_len - r) < sizeof(ifr))
 	    break;
 #  ifdef HAVE_SA_LEN
 #   ifdef __FreeBSD__
-	if (sa->sa_len > sizeof(ifr->ifr_addr))
+	if (sa->sa_len > sizeof(ifr.ifr_addr))
 #   else
-	if (sa->sa_len > sizeof(ifr->ifr_ifru))
+	if (sa->sa_len > sizeof(ifr.ifr_ifru))
 #   endif
-	    r += sizeof(ifr->ifr_name) + sa->sa_len;
+	    r += sizeof(ifr.ifr_name) + sa->sa_len;
 	else
 #  endif
-	    r += sizeof(*ifr);
+	    r += sizeof(ifr);
 
 	if (sa->sa_family == AF_INET) {
 	    struct sockaddr_in *sin = (struct sockaddr_in *)sa;
@@ -1975,14 +1976,14 @@ ProbeInterfaces(in_addr_t bindAddr)
 
 #  ifdef SIOCGIFFLAGS
 	    /* make sure the interface is up */
-	    ifrcopy = *ifr;
+	    memcpy(&ifrcopy, &ifr, sizeof(ifrcopy));
 	    if ((ioctl(sock, SIOCGIFFLAGS, &ifrcopy) == 0) &&
 		((ifrcopy.ifr_flags & IFF_UP) == 0))
 		continue;
 #  endif
 
 	    CONDDEBUG((1, "ProbeInterfaces(): name=%s addr=%s",
-		       ifr->ifr_name, inet_ntoa(sin->sin_addr)));
+		       ifr.ifr_name, inet_ntoa(sin->sin_addr)));
 
 #  if HAVE_MEMCPY
 	    memcpy(&myAddrs[m], &(sin->sin_addr), sizeof(struct in_addr));
@@ -1991,7 +1992,7 @@ ProbeInterfaces(in_addr_t bindAddr)
 #  endif
 
 	    Verbose("interface address %s (%s)", inet_ntoa(myAddrs[m]),
-		    ifr->ifr_name);
+		    ifr.ifr_name);
 	    m++;
 	}
     }
@@ -3101,4 +3102,74 @@ Sleep(useconds_t usec)
 #else
     usleep(usec);
 #endif
+}
+
+char *
+get_ucomnames(void)
+{
+	char *names;
+	int mib[2];
+	size_t size;
+
+	mib[0] = CTL_HW;
+	mib[1] = HW_UCOMNAMES;
+	names = NULL;
+	size = 0;
+	for (;;) {
+		if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1 || size == 0)
+			Error("get_ucomnames(): hw.ucomnames");
+		if ((names = realloc(names, size)) == NULL)
+			Error("get_ucomnames(): realloc(%zu)", size);
+		if (sysctl(mib, 2, names, &size, NULL, 0) != -1)
+			break;
+		if (errno != ENOMEM)
+			Error("get_ucomnames(): hw.ucomnames");
+	}
+	return names;
+}
+
+char *
+find_ucom(const char *usbid, const char *names)
+{
+	const char *errstr;
+	const char *U;
+	char *cua, *id, *ucom, *namescopy, *n;
+	uint32_t unit;
+
+	if (names == NULL) {
+		Error("find_ucom(): names is NULL");
+		return NULL;
+	}
+	CONDDEBUG((1, "find_ucom: '%s' [%s]", usbid, names));
+	if ((namescopy = strdup(names)) == NULL) {
+		Error("find_ucom(): strdup");
+		return NULL;
+	}
+
+	/* The mapping of ucom[NN] to cuaU[C] is defined in MAKEDEV. */
+	U ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+	/* names is a comma separated list of "ucom<unit#>:<usb id>". */
+	cua = NULL;
+	n = namescopy;
+	for (ucom = strsep(&n, ","); ucom; ucom = strsep(&n, ",")) {
+		CONDDEBUG((1, "find_ucom loop: '%s'", ucom));
+		if (*ucom == '\0' || strncasecmp(ucom, "ucom", 4))
+			continue;
+		ucom += 4;
+		id = strchr(ucom, ':');
+		if (id == NULL)
+			continue;
+		*id++ = '\0';
+		if (strcasecmp(id, usbid) == 0) {
+			unit = strtonum(ucom, 0, strlen(U) - 1, &errstr);
+			if (errstr != NULL)
+				continue;
+			if (asprintf(&cua, "/dev/cuaU%c", U[unit]) == -1)
+				Error("find_ucom(): asprintf");
+			break;
+		}
+	}
+	free(namescopy);
+	return cua;
 }
