www.delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/1998/11/13/14:30:06

From: corinna DOT vinschen AT cityweb DOT de (Corinna Vinschen)
Subject: B20 patch: extended socket::ioctl functionality
13 Nov 1998 14:30:06 -0800 :
Message-ID: <364CA894.D47F81C9.cygnus.cygwin32.developers@cityweb.de>
Mime-Version: 1.0
To: cygwin32-developers AT cygnus DOT com

This is a multi-part message in MIME format.
--------------7201EB56BC7E17190054A4E1
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi,

the following patch (relativ to winsup-981111) is a bit larger.
It corrects the ifconfig handling and reads the configuration
from registry. The Win95 part isn't tested yet, I don't use Win95.

The ioctl commands SIOCGIFADDR, SIOCGIFBRDADDR and SIOCGIFNETMASK
are now supported.

The function `get_if_flags()' now sets the flags IFF_UP and
IFF_RUNNING only, if the interface is really up.

Regards,
Corinna


ChangeLog:
----------
Sun Oct  4 23:58:00 1998  Corinna Vinschen <corinna DOT vinschen AT cityweb DOT de>

	* net.cc (get_if_flags): Checks for a down interface now.

Tue Sep  1 20:23:00 1998  Corinna Vinschen <corinna DOT vinschen AT cityweb DOT de>

        * net.cc (get_win95_ifconf): Checks now the registry entries
        for win95 as described by Tim Newsham (UNTESTED!).

        * net.cc (fhandler_socket::ioctl): Supports now the ioctl()
        commands SIOCGIFBRDADDR and SIOCGIFNETMASK for Win95, too.

Sun Aug 16  9:45:00 1998  Corinna Vinschen <corinna DOT vinschen AT cityweb DOT de>
Since Sat Aug  8 1998

        * include/asm/socket.h: Added defines for ioctl() calls
        SIOCGIFADDR, SIOCGIFBRDADDR and SIOCGIFNETMASK.

        * net.cc (get_winnt_ifconf): Checks now the registry entries
        instead of calling the poor function get_win95_ifconf(). Added
        parameter 'int what' for support of new ioctl() calls.

        * net.cc (fhandler_socket::ioctl): Supports now the ioctl()
        commands SIOCGIFADDR and only for WinNT SIOCGIFBRDADDR and
        SIOCGIFNETMASK.
--------------7201EB56BC7E17190054A4E1
Content-Type: text/plain; charset=us-ascii; name="socket.h-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="socket.h-patch"

--- include/asm/socket.h.orig	Fri Nov 13 20:33:41 1998
+++ include/asm/socket.h	Fri Nov 13 20:34:29 1998
@@ -25,6 +25,9 @@
 /* Needed for if queries */
 #define SIOCGIFCONF  _IOW('s', 100, struct ifconf) /* get if list */
 #define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */
+#define SIOCGIFADDR  _IOW('s', 102, struct ifreq) /* Get if addr */
+#define SIOCGIFBRDADDR  _IOW('s', 103, struct ifreq) /* Get if broadcastaddr */
+#define SIOCGIFNETMASK  _IOW('s', 104, struct ifreq) /* Get if netmask */
 
 #define SOL_SOCKET      0xffff          /* options for socket level */
 

--------------7201EB56BC7E17190054A4E1
Content-Type: text/plain; charset=us-ascii; name="net.cc-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="net.cc-patch"

--- net.cc.orig	Fri Nov 13 20:02:43 1998
+++ net.cc	Fri Nov 13 22:44:00 1998
@@ -1090,12 +1090,28 @@ getdomainname (char *domain, int len)
  * It is unlikely Win95 will ever have more than one netcard, so
  * just do a gethostbyname.  If this succeeds, then we have this
  * interface plus a loopback.
+ *
+ * New version: Now reads all Entries
+ * "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Class\NetTrans\*"
+ * from Registry and uses all entries, which have legal values
+ * "IPAddress" and "IPMask".
  */
 static int
-get_win95_ifconf (struct ifconf *ifc)
+get_win95_ifconf (struct ifconf *ifc, int what)
 {
-  /* Assume machinename will fit in 255 bytes, we will fail if not.*/
-  char name[256];
+  HKEY key, subkey;
+  FILETIME update;
+  LONG res;
+  DWORD type, size;
+  unsigned long lip, lnp;
+  char ifname[256], ip[256], np[256];
+  int cnt = 1;
+  struct sockaddr_in *sa;
+  struct ifreq *ifr = ifc->ifc_req; /* Union maps buffer to correct struct */
+  char eth[2];
+
+  eth[0] = '/';
+  eth[1] = '\0';
 
   /* Ensure we have space for two struct ifreqs, fail if not. */
   if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
@@ -1104,41 +1120,95 @@ get_win95_ifconf (struct ifconf *ifc)
       return -1;
     }
 
-  if (gethostname (name, sizeof (name)) == SOCKET_ERROR)
-    {
-      set_winsock_errno ();
-      return -1;
-    }
-  /* Now do the gethostbyname call */
-  struct hostent *he = (*i_gethostbyname) (name);
-  if (he == 0)
-    {
-      set_winsock_errno ();
-      return -1;
-    }
-
-  struct sockaddr_in *sa;
-  struct ifreq *ifr = ifc->ifc_req; /* Union maps buffer to correct struct */
   /* Set up interface lo0 first */
-  ifr++;
   strcpy (ifr->ifr_name, "lo0");
-  memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
-  sa = (struct sockaddr_in *) &ifr->ifr_addr;
+  memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
+  switch (what)
+    {
+      case SIOCGIFCONF:
+      case SIOCGIFADDR:
+        sa = (struct sockaddr_in *) &ifr->ifr_addr;
+        sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+        break;
+      case SIOCGIFBRDADDR:
+        lip = htonl(INADDR_LOOPBACK);
+        lnp = cygwin_inet_addr ("255.0.0.0");
+        sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+        sa->sin_addr.s_addr = lip & lnp | ~lnp;
+        break;
+      case SIOCGIFNETMASK:
+        sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+        sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
+        break;
+      default:
+        set_errno (EINVAL);
+	return -1;
+    }
   sa->sin_family = AF_INET;
   sa->sin_port = 0;
-  sa->sin_addr.s_addr = INADDR_LOOPBACK;
 
-  /* Increment and set up the eth0 struct */
-  strcpy (ifr->ifr_name, "eth0");
-  memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
-  sa = (struct sockaddr_in *)&ifr->ifr_addr;
-  sa->sin_family = AF_INET;
-  sa->sin_port = 0;
-  sa->sin_addr = *(struct in_addr *) he->h_addr;
+  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+                    "SYSTEM\\"
+                    "CurrentControlSet\\"
+                    "Services\\"
+                    "Class\\"
+                    "NetTrans",
+                    0, KEY_READ, &key) == ERROR_SUCCESS)
+    {
+      for (int i = 0;
+           (res = RegEnumKeyEx (key, i, ifname,
+                                (size = sizeof ifname, &size),
+                                0, 0, 0, &update)) != ERROR_NO_MORE_ITEMS;
+           ++i)
+        {
+          if (res != ERROR_SUCCESS
+              || RegOpenKeyEx (key, ifname, 0,
+                               KEY_READ, &subkey) != ERROR_SUCCESS)
+            continue;
+          if (RegQueryValueEx (subkey, "IPAddress", 0,
+                               &type, (unsigned char *) ip,
+                               (size = sizeof ip, &size)) == ERROR_SUCCESS
+              || RegQueryValueEx (subkey, "IPMask", 0,
+                                  &type, (unsigned char *) np,
+                                  (size = sizeof np, &size)) == ERROR_SUCCESS)
+            {
+              if ((caddr_t)++ifr > ifc->ifc_buf
+                                  + ifc->ifc_len
+                                  - sizeof(struct ifreq))
+               break;
+             ++*eth;
+             strcpy (ifr->ifr_name, "eth");
+             strcat (ifr->ifr_name, eth);
+             switch (what)
+               {
+                 case SIOCGIFCONF:
+                 case SIOCGIFADDR:
+                   sa = (struct sockaddr_in *) &ifr->ifr_addr;
+                   sa->sin_addr.s_addr = cygwin_inet_addr (ip);
+                   break;
+                 case SIOCGIFBRDADDR:
+                   lip = cygwin_inet_addr (ip);
+                   lnp = cygwin_inet_addr (np);
+                   sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+                   sa->sin_addr.s_addr = lip & lnp | ~lnp;
+                   break;
+                 case SIOCGIFNETMASK:
+                   sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+                   sa->sin_addr.s_addr = cygwin_inet_addr (np);
+                   break;
+               }
+             sa->sin_family = AF_INET;
+             sa->sin_port = 0;
+             ++cnt;
+           }
+         RegCloseKey (subkey);
+       }
+   }
 
-  /* Set the correct length */
-  ifc->ifc_len = 2 * sizeof (struct ifreq);
-  return 0;
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+
+ return 0;
 }
 
 /* Cygwin internal */
@@ -1157,30 +1227,219 @@ get_win95_ifconf (struct ifconf *ifc)
  * likely than 95 to be multi-homed.
  *
  * For now, though, just punt and do the same as on 95.
+ *
+ * No! Fixed now!
  */
 static int
-get_winnt_ifconf (struct ifconf *ifc)
+get_winnt_ifconf (struct ifconf *ifc, int what)
 {
-  return get_win95_ifconf (ifc);
+  HKEY key;
+  DWORD type, size;
+  unsigned long lip, lnp;
+  int cnt = 1;
+  char *binding = (char *) 0;
+  struct sockaddr_in *sa;
+  struct ifreq *ifr = ifc->ifc_req; /* Union maps buffer to correct struct */
+
+  /* Ensure we have space for two struct ifreqs, fail if not. */
+  if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
+    {
+      set_errno (EFAULT);
+      return -1;
+    }
+
+  /* Set up interface lo0 first */
+  strcpy (ifr->ifr_name, "lo0");
+  memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
+  switch (what)
+    {
+      case SIOCGIFCONF:
+      case SIOCGIFADDR:
+        sa = (struct sockaddr_in *) &ifr->ifr_addr;
+        sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+        break;
+      case SIOCGIFBRDADDR:
+        lip = htonl (INADDR_LOOPBACK);
+        lnp = cygwin_inet_addr ("255.0.0.0");
+        sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+        sa->sin_addr.s_addr = lip & lnp | ~lnp;
+        break;
+      case SIOCGIFNETMASK:
+        sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+        sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
+        break;
+      default:
+        set_errno (EINVAL);
+	return -1;
+    }
+  sa->sin_family = AF_INET;
+  sa->sin_port = 0;
+
+  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+                    "SYSTEM\\"
+                    "CurrentControlSet\\"
+                    "Services\\"
+                    "Tcpip\\"
+                    "Linkage",
+                    0, KEY_READ, &key) == ERROR_SUCCESS)
+    {
+      if (RegQueryValueEx (key, "Bind",
+                           NULL, &type,
+                           NULL, &size) == ERROR_SUCCESS)
+        {
+          binding = new char [ size ];
+          if (RegQueryValueEx (key, "Bind",
+                               NULL, &type,
+                               (unsigned char *) binding,
+                               &size) != ERROR_SUCCESS)
+            {
+              delete [] binding;
+              binding = (char *) 0;
+            }
+        }
+      RegCloseKey (key);
+    }
+  if (binding)
+    {
+      char *bp, eth[2];
+      char cardkey[256], ipaddress[256], netmask[256];
+
+      eth[0] = '/';
+      eth[1] = '\0';
+      for (bp = binding; *bp; bp += strlen(bp) + 1)
+        {
+          bp += strlen ("\\Device\\");
+          strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
+          strcat (cardkey, bp);
+          strcat (cardkey, "\\Parameters\\Tcpip");
+          if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
+                            0, KEY_READ, &key) != ERROR_SUCCESS)
+            continue;
+          if (RegQueryValueEx (key, "IPAddress",
+                               NULL, &type,
+                               (unsigned char *) &ipaddress,
+                               (size = 256, &size)) == ERROR_SUCCESS
+              && RegQueryValueEx (key, "SubnetMask",
+                                  NULL, &type,
+                                  (unsigned char *) &netmask,
+                                  (size = 256, &size)) == ERROR_SUCCESS)
+            {
+              char *ip, *np;
+              char sub[2];
+              char dhcpaddress[256], dhcpnetmask[256];
+
+              sub[0] = '/';
+              sub[1] = '\0';
+              if (strncmp (bp, "NdisWan", 7))
+                ++*eth;
+              for (ip = ipaddress, np = netmask;
+                   *ip && *np;
+                   ip += strlen (ip) + 1, np += strlen (np) + 1)
+                {
+                  if ((caddr_t) ++ifr > ifc->ifc_buf
+                                        + ifc->ifc_len
+                                        - sizeof (struct ifreq))
+                    break;
+
+                  if (! strncmp(bp, "NdisWan", 7))
+                    {
+                      strcpy (ifr->ifr_name, "ppp");
+                      strcat (ifr->ifr_name, bp + 7);
+                    }
+                  else
+                    {
+                      strcpy (ifr->ifr_name, "eth");
+                      strcat (ifr->ifr_name, eth);
+                    }
+                  ++*sub;
+                  if (*sub >= '1')
+                    strcat (ifr->ifr_name, sub);
+                  memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
+                  if (cygwin_inet_addr (ip) == 0L
+                      && RegQueryValueEx (key, "DhcpIPAddress",
+                                          NULL, &type,
+                                          (unsigned char *) &dhcpaddress,
+                                          (size = 256, &size))
+                         == ERROR_SUCCESS
+                      && RegQueryValueEx (key, "DhcpSubnetMask",
+                                          NULL, &type,
+                                          (unsigned char *) &dhcpnetmask,
+                                          (size = 256, &size))
+                         == ERROR_SUCCESS)
+                    {
+                      switch (what)
+                        {
+                          case SIOCGIFCONF:
+                          case SIOCGIFADDR:
+                            sa = (struct sockaddr_in *) &ifr->ifr_addr;
+                            sa->sin_addr.s_addr =
+                                    cygwin_inet_addr (dhcpaddress);
+                            break;
+                          case SIOCGIFBRDADDR:
+                            lip = cygwin_inet_addr (dhcpaddress);
+                            lnp = cygwin_inet_addr (dhcpnetmask);
+                            sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+                            sa->sin_addr.s_addr = lip & lnp | ~lnp;
+                            break;
+                          case SIOCGIFNETMASK:
+                            sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+                            sa->sin_addr.s_addr =
+                                    cygwin_inet_addr (dhcpnetmask);
+                            break;
+                        }
+                    }
+                  else
+                    {
+                      switch (what)
+                        {
+                          case SIOCGIFCONF:
+                          case SIOCGIFADDR:
+                            sa = (struct sockaddr_in *) &ifr->ifr_addr;
+                            sa->sin_addr.s_addr = cygwin_inet_addr (ip);
+                            break;
+                          case SIOCGIFBRDADDR:
+                            lip = cygwin_inet_addr (ip);
+                            lnp = cygwin_inet_addr (np);
+                            sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+                            sa->sin_addr.s_addr = lip & lnp | ~lnp;
+                            break;
+                          case SIOCGIFNETMASK:
+                            sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+                            sa->sin_addr.s_addr = cygwin_inet_addr (np);
+                            break;
+                        }
+                    }
+                  sa->sin_family = AF_INET;
+                  sa->sin_port = 0;
+                  ++cnt;
+                }
+            }
+          RegCloseKey (key);
+        }
+      delete [] binding;
+    }
+
+  /* Set the correct length */
+  ifc->ifc_len = cnt * sizeof (struct ifreq);
+
+  return 0;
 }
 
 /* Cygwin internal */
 /*
  * Return the flags settings for an interface.
- * This is broken at the moment as it doesn't check
- * if the interfaces are really up or down, but can
- * Windows net interfaces really be down?  (Ignore the
- * Wan interfaces for now).
  */
 static int
 get_if_flags (struct ifreq *ifr)
 {
-  short flags = IFF_UP | IFF_NOTRAILERS | IFF_RUNNING;
+  short flags = IFF_NOTRAILERS;
   struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
-  if (sa->sin_addr.s_addr == INADDR_LOOPBACK)
-      flags |= IFF_LOOPBACK;
-  else
+  if (sa->sin_addr.s_addr == INADDR_ANY)
       flags |= IFF_BROADCAST;
+  else if (sa->sin_addr.s_addr == INADDR_LOOPBACK)
+      flags |= IFF_LOOPBACK | IFF_UP | IFF_RUNNING;
+  else
+      flags |= IFF_BROADCAST | IFF_UP | IFF_RUNNING;
   ifr->ifr_flags = flags;
   return 0;
 }
@@ -1516,9 +1775,9 @@ fhandler_socket::ioctl (unsigned int cmd
 	    return -1;
 	  }
 	if (os_being_run == winNT)
-	  res = get_winnt_ifconf (ifc);
+	  res = get_winnt_ifconf (ifc, cmd);
 	else
-	  res = get_win95_ifconf (ifc);
+	  res = get_win95_ifconf (ifc, cmd);
 	break;
       }
     case SIOCGIFFLAGS:
@@ -1531,6 +1790,60 @@ fhandler_socket::ioctl (unsigned int cmd
 	  }
 	res = get_if_flags (ifr);
 	break;
+      }
+    case SIOCGIFBRDADDR:
+    case SIOCGIFNETMASK:
+    case SIOCGIFADDR:
+      {
+        char buf[2048];
+        struct ifconf ifc;
+        ifc.ifc_len = sizeof(buf);
+        ifc.ifc_buf = buf;
+        struct ifreq *ifrp;
+
+        struct ifreq *ifr = (struct ifreq *) p;
+        if (ifr == 0)
+          {
+            debug_printf("ifr == NULL\n");
+            set_errno (EINVAL);
+            return -1;
+          }
+        if (os_being_run == winNT)
+          res = get_winnt_ifconf (&ifc, cmd);
+        else
+          res = get_win95_ifconf (&ifc, cmd);
+        if (res) {
+          debug_printf("error in get_winXX_ifconf\n");
+          break;
+        }
+        debug_printf("    name: %s\n", ifr->ifr_name);
+        for (ifrp = ifc.ifc_req;
+             (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
+             ++ifrp)
+          {
+            debug_printf("testname: %s\n", ifrp->ifr_name);
+            if (! strcmp(ifrp->ifr_name, ifr->ifr_name))
+              {
+                switch (cmd) {
+                case SIOCGIFADDR:
+                  ifr->ifr_addr = ifrp->ifr_addr;
+                  break;
+                case SIOCGIFBRDADDR:
+                  ifr->ifr_broadaddr = ifrp->ifr_broadaddr;
+                  break;
+                case SIOCGIFNETMASK:
+                  ifr->ifr_netmask = ifrp->ifr_netmask;
+                  break;
+                }
+                break;
+              }
+          }
+        if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
+          {
+            set_errno (EINVAL);
+            return -1;
+          }
+        break;
       }
     case FIOASYNC:
       {

--------------7201EB56BC7E17190054A4E1--


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019