about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/if_index.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-08-25 17:19:50 +0000
committerUlrich Drepper <drepper@redhat.com>1999-08-25 17:19:50 +0000
commit71d3bda9a7a15bf3f935ffcde8aeceefef8074f7 (patch)
tree3188ef1b1ad5a60d512813dadfc756225dda0ff4 /sysdeps/unix/sysv/linux/if_index.c
parentad65970214c9dfaa6b61b9519cb0667b376e14d9 (diff)
downloadglibc-71d3bda9a7a15bf3f935ffcde8aeceefef8074f7.tar.gz
glibc-71d3bda9a7a15bf3f935ffcde8aeceefef8074f7.tar.xz
glibc-71d3bda9a7a15bf3f935ffcde8aeceefef8074f7.zip
Update.
1999-08-25  Ulrich Drepper  <drepper@cygnus.com>

	* inet/Makefile (routines): Add getipnodebynm.
	* inet/getipnodebynm.c: New file.
	* nss/digits_dots.c: If HAVE_TYPE is define type contains the
	interface type.
	* nss/nss_files/files-XXX.c: Define EXTRA_ARGS, EXTRA_ARGS_DECL, and
	EXTRA_ARGS_VALUE is not already done.
	(internal_getent): Allow extra parameters and pass them to parse_line.
	(_nss_files_get,ENTNAME_r): Pass extra parameters to internal_getent.
	(_nss_files_get##name##_r): Likewise.
	* nss/nss_files/files-hosts.c: Define EXTRA_ARGS, EXTRA_ARGS_DECL,
	and EXTRA_ARGS_VALUE to pass flags and type to parser.
	Add getipnodebyname function.
	* nss/nss_files/files-parse.c: Define EXTRA_ARGS, EXTRA_ARGS_DECL, and
	EXTRA_ARGS_VALUE is not already done.
	(parse_line): Add EXTRA_ARGS_DECL to parameter list.
	* nss/nss_db/db-XXX.c (lookup): Allow extra parameters and pass them
	to parse_line.
	(_nss_db_get##name##_r): Pass extra parameters to lookup.
	(_nss_db_get,ENTNAME_r): Likewise.
	* sysdeps/generic/if_index.c (__protocol_available): New function.
	* sysdeps/unix/sysv/linux/if_index.c: Likewise.
Diffstat (limited to 'sysdeps/unix/sysv/linux/if_index.c')
-rw-r--r--sysdeps/unix/sysv/linux/if_index.c83
1 files changed, 81 insertions, 2 deletions
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c
index 9634aa794f..d2951c6fe1 100644
--- a/sysdeps/unix/sysv/linux/if_index.c
+++ b/sysdeps/unix/sysv/linux/if_index.c
@@ -54,9 +54,9 @@ opensock (void)
 
   if (fd == -1)
     {
-      fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
+      fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
       if (fd < 0)
-	fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
+	fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
       if (fd < 0)
 	fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
       if (fd < 0)
@@ -277,3 +277,82 @@ if_indextoname (unsigned int ifindex, char *ifname)
 # endif
 #endif
 }
+
+
+void
+internal_function
+__protocol_avaliable (int *have_inet, int *have_inet6)
+{
+  int fd = opensock ();
+  unsigned int nifs;
+  int rq_len;
+  struct ifconf ifc;
+# if __ASSUME_SIOCGIFNAME == 0
+  static int old_siocgifconf;
+# else
+#  define old_siocgifconf 0
+# endif
+# define RQ_IFS	4
+
+  /* Wirst case assumption.  */
+  *have_inet = 0;
+  *have_inet6 = 0;
+
+  if (fd == NULL)
+    /* We cannot open the socket.  No networking at all?  */
+    return;
+
+  /* We may be able to get the needed buffer size directly, rather than
+     guessing.  */
+  if (! old_siocgifconf)
+    {
+      ifc.ifc_buf = NULL;
+      ifc.ifc_len = 0;
+      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
+	{
+# if __ASSUME_SIOCGIFNAME == 0
+	  old_siocgifconf = 1;
+# endif
+	  rq_len = RQ_IFS * sizeof (struct ifreq);
+	}
+      else
+	rq_len = ifc.ifc_len;
+    }
+  else
+    rq_len = RQ_IFS * sizeof (struct ifreq);
+
+  /* Read all the interfaces out of the kernel.  */
+  do
+    {
+      ifc.ifc_buf = alloca (ifc.ifc_len = rq_len);
+      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
+	{
+	  __close (fd);
+	  return;
+	}
+      rq_len *= 2;
+    }
+  while (ifc.ifc_len == rq_len && old_siocgifconf);
+
+  nifs = ifc.ifc_len / sizeof (struct ifreq);
+
+  /* Go through all the interfaces and get the address.  */
+  while (nifs-- > 0)
+    if (__ioctl (fd, SIOCGIFADDR, &ifc.ifc_req[nifs]) >= 0)
+      {
+	/* We successfully got information about this interface.  Now
+	   test whether it is an IPv4 or IPv6 address.  */
+	if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET)
+	  *have_inet = 1;
+	else if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET6)
+	  *have_inet6 = 1;
+
+	/* Note, this is & not &&.  It works since the values are always
+	   0 or 1.  */
+	if (*have_inet & *have_inet6)
+	  /* We can stop early.  */
+	  break;
+      }
+
+  __close (fd);
+}