PATCH: Fix and simplify get_netid()

Jules Colding <[email protected]> Sat, 21 Jun 2008 21:29:03 +0200
Newsgroups gmane.comp.gnome.orbit.general
Message-ID <[email protected]>
Hi,

The linc2/src/linc-protocols.c:get_netid() function produced nonsense  
values for ORBNetID="ipaddr" on Mac OS X Leopard. Please see:

    http://bugzilla.gnome.org/show_bug.cgi?id=539510


The patch below fixes this and makes for a simpler get_netid() bu  
introducing a new helper function. The patch has been tested on  
Leopard and Ubuntu Gutsy. "make check" is also happy on both  
platforms. Please forgive me if the patch below is whitespace-messed- 
up. My current mailer isn't too happy about inserted text...

May I commit? Comments?

Best regards,
   jules




Index: linc2/ChangeLog
===================================================================
--- linc2/ChangeLog	(revision 2073)
+++ linc2/ChangeLog	(working copy)
@@ -1,3 +1,13 @@
+2008-06-21  Jules Colding  <[email protected]>
+
+	* src/linc-protocols.c (get_netid): This function
+	failed on Mac OS X for (ORBNetID == "ipaddr"). It is
+	now fixed and simplified greatly by the use of the new
+	function get_first_non_local_ipaddr().
+	(get_first_non_local_ipaddr):  This function will
+	correctly deduce the first non-loopback interface
+	on the host.
+
  ============================== 2.14.13 ===========================

  2008-05-25  Tor Lillqvist  <[email protected]>
Index: linc2/src/linc-protocols.c
===================================================================
--- linc2/src/linc-protocols.c	(revision 2073)
+++ linc2/src/linc-protocols.c	(working copy)
@@ -145,7 +145,49 @@
  #endif
  #define DEFAULT_LINC2_IFNUM (32)

+#ifndef G_OS_WIN32
  static char *
+get_first_non_local_ipaddr(char *buf,
+			   size_t len)
+{
+	int sock;
+	const char *retv;
+	struct if_nameindex *ifname_idx_array;
+	struct if_nameindex *ifname_idx;
+	struct ifreq ifr;
+	struct sockaddr_in sin;
+
+	*buf = '\0';
+
+	sock = socket(AF_INET, SOCK_DGRAM, 0);
+	if (-1 == sock)
+		return;
+
+	ifname_idx_array = if_nameindex();
+	for (ifname_idx = ifname_idx_array; ifname_idx && ifname_idx- 
 >if_name && ifname_idx->if_name[0]; ifname_idx++) {
+		strncpy(ifr.ifr_name, ifname_idx->if_name, IFNAMSIZ);
+		if (!ioctl(sock, SIOCGIFADDR, &ifr)) {
+			memcpy(&sin, &(ifr.ifr_addr), sizeof(struct sockaddr_in));
+			retv = (const char*)inet_ntoa(sin.sin_addr);
+			retv = strcmp("127.0.0.1", retv) ? retv : NULL;
+			if (retv) {
+				strncpy(buf, (const char*)inet_ntoa(sin.sin_addr), len);
+				break;
+			}
+		}
+	}
+
+	if (ifname_idx_array)
+		if_freenameindex(ifname_idx_array);
+
+	if (-1 != sock)
+		close(sock);
+
+	return buf;
+}
+#endif
+
+static char *
  get_netid(LinkNetIdType which,
  	  char *buf,
  	  size_t len)
@@ -161,58 +203,13 @@
  	if ((LINK_NET_ID_IS_IPADDR == which)
  	    || (LINK_NET_ID_IS_CUSTOM == which)) {
  #ifndef G_OS_WIN32
-		struct sockaddr_in *adr = NULL;
-		struct ifreq *my_ifreqs = NULL;
-		struct ifconf my_ifconf = { 0 };
-		int sock = -1;
-		int num = 0;
-		int i = 0;
+		if (fixed_host_net_id)
+			strncpy(buf, fixed_host_net_id, len);
+		else
+			get_first_non_local_ipaddr(buf, len);
+		if ('\0' == *buf)
+			strncpy(buf, "127.0.0.1", len);

-		sock = socket(AF_INET,SOCK_DGRAM,0);
-		if (-1 == sock)
-			goto out;
-#ifdef SIOCGIFNUM
-		i = ioctl(sock, SIOCGIFNUM, &num);
-		if ((0 > i) || !num) {
-			close(sock);
-			goto out;
-		}
-#else
-		num = DEFAULT_LINC2_IFNUM;
-#endif
-		my_ifconf.ifc_len = sizeof(struct ifreq) * num;
-		my_ifconf.ifc_req = (struct ifreq*)malloc(my_ifconf.ifc_len);
-		if (!my_ifconf.ifc_req) {
-			close(sock);
-			goto out;
-		}
-		if (ioctl(sock,SIOCGIFCONF,&my_ifconf) < 0) {
-			close(sock);
-			free(my_ifconf.ifc_req);
-			goto out;
-		}
-		close(sock);
-
-		my_ifreqs = my_ifconf.ifc_req;
- 		for (i = 0; i < num; i++) {
-			adr = (struct sockaddr_in *)&my_ifreqs[i].ifr_ifru.ifru_addr;
-			if (fixed_host_net_id) {
-				if (!strcmp(fixed_host_net_id, inet_ntoa(adr->sin_addr)))
-					break;
-			} else {
-				if (strcmp("127.0.0.1", inet_ntoa(adr->sin_addr)))
-					break;
-			}
-			if (!strcmp("0.0.0.0", inet_ntoa(adr->sin_addr))) {
-				if (i)
-					adr = (struct sockaddr_in *)&my_ifreqs[--i].ifr_ifru.ifru_addr;
-				break;
-			}
-		}
-		strncpy(buf, (const char*)inet_ntoa(adr->sin_addr), len);
-		free(my_ifconf.ifc_req);
-
-		/* will be 127.0.0.1 anyway, if no other address is defined... */
  		return buf;
  #else
  		SOCKET sock;