Mail Archives: cygwin-developers/1998/11/13/14:30:06
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 -