Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Jun 2009 03:59:00 +0000 (UTC)
From:      Stef Walter <stef-list@memberwebs.com>
To:        "freebsd-net@FreeBSD.org" <freebsd-net@freebsd.org>
Subject:   32 bit compatibility for getifaddrs()
Message-ID:  <20090614035859.A057517056D@mx.npubs.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------080508060506040100070903
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

I've started running 64-bit FreeBSD (version 7.2) in production. I have
a lot of old 6.3 32-bit jails I need to run as is for now.

One problem I ran into is 32-bit getifaddrs() would crash accessing a
64-bit kernel via the sysctl NET_RT_IFLIST method.

Attached is a patch that adds 32-bit compatibility to the rtsock.c route
messages.

Who would I work with to get this (or something like it) committed?

Cheers,

Stef

--------------080508060506040100070903
Content-Type: text/x-diff;
 name="getifaddrs-rtsock-compat32.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="getifaddrs-rtsock-compat32.patch"

--- sys/net/rtsock.c.orig	2009-06-13 19:51:29.000000000 +0000
+++ sys/net/rtsock.c	2009-06-13 20:44:35.000000000 +0000
@@ -1199,6 +1199,251 @@
 	netisr_queue(NETISR_ROUTE, m);	/* mbuf is free'd on failure. */
 }
 
+#ifdef SCTL_MASK32
+
+/* 32-bit structure definitions */
+struct timeval32 {
+	int32_t tv_sec;
+	int32_t tv_usec;
+};
+
+struct if_data32 {
+	u_int8_t   ifi_type;
+	u_int8_t   ifi_physical;
+	u_int8_t   ifi_addrlen;
+	u_int8_t   ifi_hdrlen;
+	u_int8_t   ifi_link_state; 
+	u_int8_t   ifi_recvquota;
+	u_int8_t   ifi_xmitquota;
+	u_int8_t   ifi_datalen;
+	u_int32_t  ifi_mtu;
+	u_int32_t  ifi_metric;
+	u_int32_t  ifi_baudrate;
+	u_int32_t  ifi_ipackets;
+	u_int32_t  ifi_ierrors;
+	u_int32_t  ifi_opackets;
+	u_int32_t  ifi_oerrors;
+	u_int32_t  ifi_collisions;
+	u_int32_t  ifi_ibytes;
+	u_int32_t  ifi_obytes;
+	u_int32_t  ifi_imcasts;
+	u_int32_t  ifi_omcasts;
+	u_int32_t  ifi_iqdrops;
+	u_int32_t  ifi_noproto;
+	u_int32_t  ifi_hwassist;
+	int32_t    ifi_epoch;
+	struct timeval32 ifi_lastchange;
+};
+
+struct rt_metrics32 {
+	u_int32_t  rmx_locks;
+	u_int32_t  rmx_mtu;
+	u_int32_t  rmx_hopcount;
+	u_int32_t  rmx_expire;
+	u_int32_t  rmx_recvpipe;
+	u_int32_t  rmx_sendpipe;
+	u_int32_t  rmx_ssthresh;
+	u_int32_t  rmx_rtt;
+	u_int32_t  rmx_rttvar;
+	u_int32_t  rmx_pksent;
+	u_int32_t  rmx_filler[4];
+};
+
+struct rt_msghdr32 {
+	u_int16_t rtm_msglen;
+	u_int8_t  rtm_version;
+	u_int8_t  rtm_type;
+	u_int16_t rtm_index;
+	int32_t   rtm_flags;
+	int32_t   rtm_addrs;
+	int32_t   rtm_pid;
+	int32_t   rtm_seq;
+	int32_t   rtm_errno;
+	int32_t   rtm_fmask;
+	u_int32_t rtm_inits;
+	struct rt_metrics32 rtm_rmx;
+};
+
+struct if_msghdr32 {
+	u_int16_t ifm_msglen;
+	u_int8_t  ifm_version;
+	u_int8_t  ifm_type;
+	int32_t   ifm_addrs;
+	int32_t   ifm_flags;
+	u_int16_t ifm_index;
+	struct if_data32 ifm_data;
+};
+
+struct ifa_msghdr32 {
+	u_int16_t ifam_msglen;
+	u_int8_t  ifam_version;
+	u_int8_t  ifam_type;
+	int32_t   ifam_addrs;
+	int32_t   ifam_flags;
+	u_int16_t ifam_index;
+	int32_t   ifam_metric;
+};
+
+struct ifma_msghdr32 {
+	u_int16_t ifmam_msglen;
+	u_int8_t  ifmam_version;
+	u_int8_t  ifmam_type;
+	int32_t   ifmam_addrs;
+	int32_t   ifmam_flags;
+	u_int16_t ifmam_index;
+};
+
+struct if_announcemsghdr32 {
+	u_int16_t ifan_msglen;
+	u_int8_t  ifan_version;
+	u_int8_t  ifan_type;
+	u_int16_t ifan_index;
+	char      ifan_name[IFNAMSIZ];
+	u_int16_t ifan_what;
+};
+
+#endif
+
+/*
+ * Output route message to sysctl for 64 or 32-bit 
+ */
+static int
+rt_sysctl_out(struct sysctl_req *req, const void *data, size_t len)
+{
+	const struct rt_msghdr *rtm = data;
+	int error;
+
+#ifdef SCTL_MASK32
+	if (req->flags & SCTL_MASK32) {
+		switch (rtm->rtm_type) {
+		case RTM_IFINFO:
+		{
+			const struct if_msghdr *ifm = data;
+			struct if_msghdr32 ifm32;
+			data = ((const u_char*)data) + sizeof (*ifm);
+			len -= sizeof (*ifm);
+			ifm32.ifm_msglen = sizeof (ifm32) + len;
+			ifm32.ifm_version = ifm->ifm_version;
+			ifm32.ifm_type = ifm->ifm_type;
+			ifm32.ifm_addrs = ifm->ifm_addrs;
+			ifm32.ifm_flags = ifm->ifm_flags;
+			ifm32.ifm_index = ifm->ifm_index;
+			ifm32.ifm_data.ifi_type = ifm->ifm_data.ifi_type;
+			ifm32.ifm_data.ifi_physical = ifm->ifm_data.ifi_physical;
+			ifm32.ifm_data.ifi_addrlen = ifm->ifm_data.ifi_addrlen;
+			ifm32.ifm_data.ifi_hdrlen = ifm->ifm_data.ifi_hdrlen;
+			ifm32.ifm_data.ifi_link_state = ifm->ifm_data.ifi_link_state;
+			ifm32.ifm_data.ifi_recvquota = 0;
+			ifm32.ifm_data.ifi_xmitquota = 0;
+			ifm32.ifm_data.ifi_datalen = ifm->ifm_data.ifi_datalen;
+			ifm32.ifm_data.ifi_mtu = ifm->ifm_data.ifi_mtu;
+			ifm32.ifm_data.ifi_metric = ifm->ifm_data.ifi_metric;
+			ifm32.ifm_data.ifi_baudrate = ifm->ifm_data.ifi_baudrate;
+			ifm32.ifm_data.ifi_ipackets = ifm->ifm_data.ifi_ipackets;
+			ifm32.ifm_data.ifi_ierrors = ifm->ifm_data.ifi_ierrors;
+			ifm32.ifm_data.ifi_opackets = ifm->ifm_data.ifi_opackets;
+			ifm32.ifm_data.ifi_oerrors = ifm->ifm_data.ifi_oerrors;
+			ifm32.ifm_data.ifi_collisions = ifm->ifm_data.ifi_collisions;
+			ifm32.ifm_data.ifi_ibytes = ifm->ifm_data.ifi_ibytes;
+			ifm32.ifm_data.ifi_obytes = ifm->ifm_data.ifi_obytes;
+			ifm32.ifm_data.ifi_imcasts = ifm->ifm_data.ifi_imcasts;
+			ifm32.ifm_data.ifi_omcasts = ifm->ifm_data.ifi_omcasts;
+			ifm32.ifm_data.ifi_iqdrops = ifm->ifm_data.ifi_iqdrops;
+			ifm32.ifm_data.ifi_noproto = ifm->ifm_data.ifi_noproto;
+			ifm32.ifm_data.ifi_hwassist = ifm->ifm_data.ifi_hwassist;
+			ifm32.ifm_data.ifi_epoch = ifm->ifm_data.ifi_epoch;
+			ifm32.ifm_data.ifi_lastchange.tv_sec = ifm->ifm_data.ifi_lastchange.tv_sec;
+			ifm32.ifm_data.ifi_lastchange.tv_usec = ifm->ifm_data.ifi_lastchange.tv_usec;
+			error = SYSCTL_OUT(req, &ifm32, sizeof (ifm32));
+			break;
+		}
+		case RTM_NEWADDR:
+		case RTM_DELADDR:
+		{
+			const struct ifa_msghdr *ifam = data;
+			struct ifa_msghdr32 ifam32;
+			data = ((const u_char*)data) + sizeof (*ifam);
+			len -= sizeof (*ifam);
+			ifam32.ifam_msglen = sizeof (ifam32) + len;
+			ifam32.ifam_version = ifam->ifam_version;
+			ifam32.ifam_type = ifam->ifam_type;
+			ifam32.ifam_addrs = ifam->ifam_addrs;
+			ifam32.ifam_flags = ifam->ifam_flags;
+			ifam32.ifam_index = ifam->ifam_index;
+			ifam32.ifam_metric = ifam->ifam_metric;
+			error = SYSCTL_OUT(req, &ifam32, sizeof (ifam32));
+			break;
+		}
+		case RTM_NEWMADDR:
+		case RTM_DELMADDR:
+		{
+			const struct ifma_msghdr *ifmam = data;
+			struct ifma_msghdr32 ifmam32;
+			data = ((const u_char*)data) + sizeof (*ifmam);
+			len -= sizeof (*ifmam);
+			ifmam32.ifmam_msglen = sizeof (ifmam32) + len;
+			ifmam32.ifmam_version = ifmam->ifmam_version;
+			ifmam32.ifmam_type = ifmam->ifmam_type;
+			ifmam32.ifmam_addrs = ifmam->ifmam_addrs;
+			ifmam32.ifmam_flags = ifmam->ifmam_flags;
+			ifmam32.ifmam_index = ifmam->ifmam_index;
+			error = SYSCTL_OUT(req, &ifmam32, sizeof (ifmam32));
+			break;	
+		}
+		case RTM_IFANNOUNCE:
+		{
+			const struct if_announcemsghdr *ifan = data;
+			struct if_announcemsghdr32 ifan32;
+			data = ((const u_char*)data) + sizeof (*ifan);
+			len -= sizeof (*ifan);
+			ifan32.ifan_msglen = sizeof (ifan32) + len;
+			ifan32.ifan_version = ifan->ifan_version;
+			ifan32.ifan_type = ifan->ifan_type;
+			ifan32.ifan_index = ifan->ifan_index;
+			bcopy(&ifan->ifan_name, &ifan32.ifan_name, sizeof (ifan32.ifan_name));
+			ifan32.ifan_what = ifan->ifan_what;		
+			error = SYSCTL_OUT(req, &ifan32, sizeof (ifan32));
+			break;
+		}
+		default:
+		{
+			struct rt_msghdr32 rtm32;
+			data = ((const u_char*)data) + sizeof (*rtm);
+			len -= sizeof (*rtm);
+			rtm32.rtm_msglen = sizeof (rtm32) + len;
+			rtm32.rtm_version = rtm->rtm_version;
+			rtm32.rtm_type = rtm->rtm_type;
+			rtm32.rtm_index = rtm->rtm_index;
+			rtm32.rtm_flags = rtm->rtm_flags;
+			rtm32.rtm_addrs = rtm->rtm_addrs;
+			rtm32.rtm_pid = rtm->rtm_pid;
+			rtm32.rtm_seq = rtm->rtm_seq;
+			rtm32.rtm_errno = rtm->rtm_errno;
+			rtm32.rtm_use = rtm->rtm_use;
+			rtm32.rtm_inits = rtm->rtm_inits;
+			rtm32.rtm_rmx.rmx_locks = rtm->rtm_rmx.rmx_locks;
+			rtm32.rtm_rmx.rmx_mtu = rtm->rtm_rmx.rmx_mtu;
+			rtm32.rtm_rmx.rmx_hopcount = rtm->rtm_rmx.rmx_hopcount;
+			rtm32.rtm_rmx.rmx_expire = rtm->rtm_rmx.rmx_expire;
+			rtm32.rtm_rmx.rmx_recvpipe = rtm->rtm_rmx.rmx_recvpipe;
+			rtm32.rtm_rmx.rmx_sendpipe = rtm->rtm_rmx.rmx_sendpipe;
+			rtm32.rtm_rmx.rmx_ssthresh = rtm->rtm_rmx.rmx_ssthresh;
+			rtm32.rtm_rmx.rmx_rtt = rtm->rtm_rmx.rmx_rtt;
+			rtm32.rtm_rmx.rmx_rttvar = rtm->rtm_rmx.rmx_rttvar;
+			rtm32.rtm_rmx.rmx_pksent = rtm->rtm_rmx.rmx_pksent;
+			error = SYSCTL_OUT(req, &rtm32, sizeof (rtm32));
+			break;
+		}
+		}
+
+		if (error)
+			return error;			
+	} 
+#endif /* SCTL_MASK32 */ 
+	error = SYSCTL_OUT(req, data, len);
+	return error;
+}
+
 /*
  * This is used in dumping the kernel table via sysctl().
  */
@@ -1237,7 +1482,7 @@
 		rtm->rtm_index = rt->rt_ifp->if_index;
 		rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
 		rtm->rtm_addrs = info.rti_addrs;
-		error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
+		error = rt_sysctl_out(w->w_req, (caddr_t)rtm, size);
 		return (error);
 	}
 	return (error);
@@ -1268,7 +1513,7 @@
 			ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
 			ifm->ifm_data = ifp->if_data;
 			ifm->ifm_addrs = info.rti_addrs;
-			error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
+			error = rt_sysctl_out(w->w_req,(caddr_t)ifm, len);
 			if (error)
 				goto done;
 		}
@@ -1290,7 +1535,7 @@
 				ifam->ifam_flags = ifa->ifa_flags;
 				ifam->ifam_metric = ifa->ifa_metric;
 				ifam->ifam_addrs = info.rti_addrs;
-				error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+				error = rt_sysctl_out(w->w_req, w->w_tmem, len);
 				if (error)
 					goto done;
 			}
@@ -1338,7 +1583,7 @@
 				ifmam->ifmam_index = ifma->ifma_ifp->if_index;
 				ifmam->ifmam_flags = 0;
 				ifmam->ifmam_addrs = info.rti_addrs;
-				error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+				error = rt_sysctl_out(w->w_req, w->w_tmem, len);
 				if (error) {
 					IF_ADDR_UNLOCK(ifp);
 					goto done;

--------------080508060506040100070903--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090614035859.A057517056D>