Closed Lethja closed 5 months ago
But after this change, there are lots of these new warnings from clang-cl:
ioctl.c(128,10): warning: overflow converting case value to switch condition type (18446744071562356350 to 2147772030) [-Wswitch]
128 | case FIONBIO: /* set nonblocking I/O on/off */
| ^
../inc\sys/ioctl.h(77,25): note: expanded from macro 'FIONBIO'
77 | #define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
| ^
../inc\sys/ioctl.h(67,21): note: expanded from macro '_IOW'
67 | #define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
| ^
But these new warnings are for x64 only. Like here; https://ci.appveyor.com/project/gvanem/watt-32/builds/49490611/job/dlvjwucjl4xm1bpt#L72
I fixed these in: https://github.com/gvanem/Watt-32/commit/e3d473ffca030ba643b2e375cc5fd340155d4b76.
I'm sorry but this PR caused a lot of warnings for most other targets. Will have to revert and create a special case for Watcom + 16-bit. Is this the best way to check for this:
/* Watcom / 16-bit targets need special handling:
*/
#if defined(__WATCOMC__) && !defined(__386__)
#define IOCPARM_MASK (long) 0x7f /* parameters must be < 128 bytes */
...
#else
#define IOCPARM_MASK 0x7f
...
#endif
The issue is because long type on some 64-bit system is 64-bit. By example | C type | 16-bit arch | 32-bit arch | 64-bit Microsoft Windows | 64-bit *NIX |
---|---|---|---|---|---|
short | 16-bit | 16-bit | 16-bit | 16-bit | 16-bit |
int | 16-bit | 32-bit | 32-bit | 32-bit | 32-bit |
long | 32-bit | 32-bit | 32-bit | 64-bit | |
long long | 64-bit | 64-bit | 64-bit | 64-bit |
that for code common for 16/32/64-bit platform for 32-bit variable you need use conditional type or use C99 int32_t type independent on platform or modify code to use long type and be independent on such type size. Open Watcom use long type with 32-bit size.
Anyway following definition is wrong and will cause a problems
#if defined(__WATCOMC__) && !defined(__386__)
#define IOCPARM_MASK (long) 0x7f /* parameters must be < 128 bytes */
...
#else
#define IOCPARM_MASK 0x7f
...
#endif
it should be
#define IOCPARM_MASK 0x7f
for every platform.
The issue is caused by other macros definition and 64-bit type size.
The macros should be corrected to work properly with all possible types or you need to add macros specialized for appropriate types.
simplest method is mask value to be in 32-bit range even if used type is 64-bit, but it depends on use, there can be signed value problem etc.
The issue is caused by other macros definition and 64-bit type size.
So what's the fix? I reverted the previous fix in https://github.com/gvanem/Watt-32/commit/e1accb26464f9b0b9a3c7f803b1ad9ba83ec3db0 to fix the original Watcom/16-bit warnings. Not sure it's correct. Have a look.
Perhaps it's best to define our own int_least32_t
equivalent that can be used throughout the codebase. This will keep the code C89 compliant yet keep the preprocessors minimal in the actual code
#if defined(__WATCOMC__) && !defined(__386__)
typedef long least_int32_t
/* Can add more #elif conditions for different compilers and targets here if required */
#else
typedef int least_int32_t
#endif
I think the cast in constant definition is source of problem. You should always minimise C casting and you should relate on standard C language automatic type conversion (type promotion). It needs much bigger revision of your code, because you mixed Windows, POSIX and ISO C types in your code. The main problem looks like 32-bit size variable because it is platform and architecture dependent. It also depend on C standard which you are using because C90 standard doesn't know int32_t type. It was introduced by C99. If you want compatibility with C90 then best solution is define your own global type for 32-bit size as conditional type. You need to properly detect compiler type mode, it means if long type size is 64-bit. It should be something as
#if COMPILER_64BIT_LPP
#define INT32TYPE int
#define UINT32TYPE unsigned int
#else
#define INT32TYPE long
#define UINT32TYPE unsigned long
#endif
and use this type where it has sense (where it is necessary) otherwise use long type.
Perhaps it's best to define our own
int_least32_t
equivalent that can be used throughout the codebase. This will keep the code C89 compliant yet keep the preprocessors minimal in the actual code#if defined(__WATCOMC__) && !defined(__386__) typedef long least_int32_t /* Can add more #elif conditions for different compilers and targets here if required */ #else typedef int least_int32_t #endif
Don't do it as watcom specific, because same problem with other compilers. Correct is detect if long type is 64-bit. Most of *NIX compilers has this mode by default, but they can be switched to Windows model then long type is 32-bit that it can not be detected by compiler only. This issue is related to 64-bit platform mainly not with 16-bit platform any way. your least_int32_t can be replaced by long type doesn't need such construct, because long type is >= 32-bit on any platform.
I tested Watcom DOS 16-bit and DOS 4G builds at e1accb26464f9b0b9a3c7f803b1ad9ba83ec3db0. All is well
All is well
So we can leave src/ioctl.c
and inc/sys/ioctl.h
like it is now?
So we can leave
src/ioctl.c
andinc/sys/ioctl.h
like it is now?
Yes while @jmalak has given the technically correct solution that would make code exactly the same across different platform builds and could allow compilers to do a tiny optimization for i486 and later architectures (including 64-bit), e1accb2 is enough to fix Watcom W135 when building for DOS 16-bit.
If we want to pursue making ioctl options explicitly 32-bit then we can make another issue later
I am not able to check build of Watt-32, but inc/sys/ioctl.h
should be returned back to following old version.
there is no reason to change it.
/*!\file sys/ioctl.h
* BSD socket I/O control.
*/
/*
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(__SYS_IOCTL_H) && !defined(__SYS_SO_IOCTL_H)
#define __SYS_IOCTL_H
/*
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
*
* Ioctl's have the command encoded in the lower word,
* and the size of any in or out parameters in the upper
* word. The high 2 bits of the upper word are used
* to encode the in/out status of the parameter; for now
* we restrict parameters to at most 128 bytes.
*/
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
#define IOCBASECMD(x) ((x) & ~IOCPARM_MASK)
#define IOCGROUP(x) (((x) >> 8) & 0xff)
#define IOCPARM_MAX 4096 /* max size of ioctl */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
#define IOC_INOUT (IOC_IN|IOC_OUT) /* 0x20000000 distinguishes new &
old ioctl's */
#define IOC_DIRMASK 0xe0000000 /* mask for IN/OUT/VOID */
#define _IO(x,y) (IOC_VOID|(x<<8)|y)
#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
/* this should be _IORW, but stdio got there first */
#define _IOWR(x,y,t) (IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
/*
* file i/o controls
*/
#define FIOCLEX _IO('f', 1) /* set close on exec on fd */
#define FIONCLEX _IO('f', 2) /* remove close on exec */
#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */
#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */
#define FIOSETOWN _IOW('f', 124, int) /* set owner (struct Task *) */
#define FIOGETOWN _IOR('f', 123, int) /* get owner (struct Task *) */
/*
* socket i/o controls
*
* SIOCSPGRP and SIOCGPGRP are identical to the FIOSETOWN and FIOGETOWN,
* respectively.
*/
#define SIOCSPGRP _IOW('s', 8, int) /* set process group */
#define SIOCGPGRP _IOR('s', 9, int) /* get process group */
/* #ifdef BSD */
#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */
#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */
#define SIOCSIFADDR _IOW('I', 12, struct ifreq) /* set ifnet address */
#define OSIOCGIFADDR _IOWR('I',13, struct ifreq) /* get ifnet address */
#define SIOCGIFADDR _IOWR('I',33, struct ifreq) /* get ifnet address */
#define SIOCSIFDSTADDR _IOW('I', 14, struct ifreq) /* set p-p address */
#define OSIOCGIFDSTADDR _IOWR('I',15, struct ifreq) /* get p-p address */
#define SIOCGIFDSTADDR _IOWR('I',34, struct ifreq) /* get p-p address */
#define SIOCSIFFLAGS _IOW('I', 16, struct ifreq) /* set ifnet flags */
#define SIOCGIFFLAGS _IOWR('I',17, struct ifreq) /* get ifnet flags */
#define OSIOCGIFBRDADDR _IOWR('I',18, struct ifreq) /* get broadcast addr */
#define SIOCGIFBRDADDR _IOWR('I',35, struct ifreq) /* get broadcast addr */
#define SIOCSIFBRDADDR _IOW('I',19, struct ifreq) /* set broadcast addr */
#define OSIOCGIFCONF _IOWR('I',20, struct ifconf) /* get ifnet list */
#define SIOCGIFCONF _IOWR('I',36, struct ifconf) /* get ifnet list */
#define OSIOCGIFNETMASK _IOWR('I',21, struct ifreq) /* get net addr mask */
#define SIOCGIFNETMASK _IOWR('I',37, struct ifreq) /* get net addr mask */
#define SIOCSIFNETMASK _IOW('I',22, struct ifreq) /* set net addr mask */
#define SIOCGIFMETRIC _IOWR('I',23, struct ifreq) /* get IF metric */
#define SIOCSIFMETRIC _IOW('I',24, struct ifreq) /* set IF metric */
#define SIOCDIFADDR _IOW('I',25, struct ifreq) /* delete IF addr */
#define SIOCAIFADDR _IOW('I',26, struct ifaliasreq)/* add/chg IF alias */
#define SIOCGIFMTU _IOWR('I',27, struct ifreq) /* get IF mtu */
#define SIOCGIFHWADDR _IOWR('I',28, struct ifconf) /* get hardware addr */
#define OSIOCGIFHWADDR SIOCGIFHWADDR
#define SIOCSARP _IOW('I', 30, struct arpreq) /* set arp entry */
#define OSIOCGARP _IOWR('I',31, struct arpreq) /* get arp entry */
#define SIOCGARP _IOWR('I',38, struct arpreq) /* get arp entry */
#define SIOCDARP _IOW('I', 32, struct arpreq) /* delete arp entry */
/* #endif */ /* BSD */
/* MS-DOS */
#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */
#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */
#endif /* !__SYS_IOCTL_H */
/* Since this file shadows the normal djgpp <sys/ioctl.h>, we include
* that last.
*/
#if defined(__DJGPP__)
#include_next <sys/ioctl.h> /* ioctl() */
#endif
and src/ioctl.c to something like follows, but there are several strange constructs.
struct search_list {
DWORD type;
const char *name;
};
instead of
struct search_list {
long type;
const char *name;
};
because this structure is internal you can change it to use C types only. Next you can remove lot of useless casts related to this structure.
why you use Windows types for Watt-32 internal types instead of C language types.
by example DWORD
instead unsigned long
or long
C type?
any relation to some platform for Watt-32 internals cause problem with portability. if you define API for Windows then it is specific for Windows and cannot be used for other platform then you define only public API for such single platform with platform specific types but internaly you should use your own types which is portable.
/*!\file ioctl.c
* BSD ioctlsocket().
*/
/* BSD sockets functionality for Watt-32 TCP/IP
*
* Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Gisle Vanem
* Bergen, Norway.
*
* THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Version
*
* 0.5 : Dec 18, 1997 : G. Vanem - created
*/
#define BSD /* in order to include SIOxx macros in <sys/ioctl.h> */
#include "socket.h"
#if defined(USE_BSD_API)
static int file_ioctrl (Socket *socket, long cmd, void *argp);
static int iface_ioctrl (Socket *socket, long cmd, void *argp);
static int arp_ioctrl (Socket *socket, long cmd, void *argp);
static int waterm_ioctrl(Socket *socket, long cmd, void *argp);
#define NO_CMD(cmd) SOCK_DEBUGF ((", unsupported cmd %d, group %c", \
(int)((cmd) & IOCPARM_MASK), \
(char)IOCGROUP(cmd)))
#ifdef USE_DEBUG
static const char *get_ioctl_cmd (long cmd);
#endif
#ifndef NUM_IFACES
#define NUM_IFACES 1
#endif
#ifndef ARPHRD_FDDI
#define ARPHRD_FDDI 10
#endif
int W32_CALL ioctlsocket (int s, long cmd, void *argp)
{
Socket *socket = _socklist_find (s);
SOCK_PROLOGUE (socket, "\nioctlsocket:%d", s);
SOCK_DEBUGF ((", %s", get_ioctl_cmd(cmd)));
switch (IOCGROUP(cmd))
{
case 'f':
return file_ioctrl (socket, cmd, argp);
case 'I':
return iface_ioctrl (socket, cmd, argp);
case 's':
return waterm_ioctrl (socket, cmd, argp);
default:
NO_CMD (cmd);
SOCK_ERRNO (ESOCKTNOSUPPORT);
}
return (-1);
}
/*
* IO-control for "file" handles (i.e. stream/datagram sockets)
*/
static int file_ioctrl (Socket *socket, long cmd, void *argp)
{
int len;
switch (cmd)
{
case FIONREAD:
VERIFY_RW (argp, sizeof(u_long));
if (socket->so_type != SOCK_DGRAM &&
socket->so_type != SOCK_STREAM)
{
SOCK_ERRNO (EBADF);
return (-1);
}
if (socket->so_type == SOCK_DGRAM)
{
if (socket->so_state & SS_PRIV)
len = sock_recv_used ((sock_type*)socket->udp_sock);
else len = sock_rbused ((sock_type*)socket->udp_sock);
}
else
len = sock_rbused ((sock_type*)socket->tcp_sock);
if (len < 0)
{
SOCK_ERRNO (EBADF);
return (-1);
}
SOCK_DEBUGF ((" %d", len));
if (len >= 0)
*(u_long*)argp = len;
break;
case FIONBIO: /* set nonblocking I/O on/off */
VERIFY_RW (argp, sizeof(char));
if (*(char*)argp)
{
socket->so_state |= SS_NBIO;
socket->timeout = 0;
if (socket->tcp_sock)
socket->tcp_sock->timeout = 0;
}
else
{
socket->so_state &= ~SS_NBIO;
if (socket->tcp_sock) /* Only TCP sockets timeout on inactivety */
socket->timeout = sock_delay;
}
SOCK_DEBUGF ((" %d", (socket->so_state & SS_NBIO) ? 1 : 0));
break;
#if 0
case FIOASYNC:
case FIOCLEX:
case FIONCLEX:
case FIONREAD:
case FIOSETOWN:
case FIOGETOWN:
#endif
default:
NO_CMD (cmd);
SOCK_ERRNO (ESOCKTNOSUPPORT);
return (-1);
}
return (0);
}
/*
* Return name of this interface.
* We only support a single interface at a time.
*/
static char eth_ifname [IFNAMSIZ] = "eth0";
static char arc_ifname [IFNAMSIZ] = "arch0";
static char tok_ifname [IFNAMSIZ] = "tr0";
static char fddi_ifname[IFNAMSIZ] = "fddi0";
static char ppp_ifname [IFNAMSIZ] = "ppp0";
static char slp_ifname [IFNAMSIZ] = "slp0";
void __get_ifname (char *if_name)
{
switch (_pktdevclass)
{
case PDCLASS_ETHER:
strcpy (if_name, eth_ifname);
break;
case PDCLASS_TOKEN:
strcpy (if_name, tok_ifname);
break;
case PDCLASS_FDDI:
strcpy (if_name, fddi_ifname);
break;
case PDCLASS_ARCNET:
strcpy (if_name, arc_ifname);
break;
case PDCLASS_SLIP:
strcpy (if_name, slp_ifname);
break;
case PDCLASS_PPP:
strcpy (if_name, ppp_ifname);
break;
default:
strcpy (if_name, "??");
break;
}
}
#ifdef NOT_USED_YET
/*
* Set a new name for this interface.
*/
void __set_ifname (const char *if_name)
{
switch (_pktdevclass)
{
case PDCLASS_ETHER:
strcpy (eth_ifname, if_name);
break;
case PDCLASS_TOKEN:
strcpy (tok_ifname, if_name);
break;
case PDCLASS_FDDI:
strcpy (fddi_name, if_ifname);
break;
case PDCLASS_ARCNET:
strcpy (arc_name, if_ifname);
break;
case PDCLASS_SLIP:
strcpy (slp_ifname, if_name);
break;
case PDCLASS_PPP:
strcpy (ppp_ifname, if_name);
break;
default:
break;
}
}
static struct ifnet *eth_ifnet (void)
{
static struct ifnet net;
/** \todo fill info */
return (&net);
}
static struct ifnet *tok_ifnet (void)
{
static struct ifnet net;
/** \todo fill info */
return (&net);
}
#endif
/*
* Ensure we do not 'memcpy()' too much from a '_eth_addr' which is only 6 bytes.
* The size of 'ifr_hwaddr.sa_data[]' could be 16.
*
* With gcc 7.x, a warning for:
* memcpy (&ifr->ifr_hwaddr.sa_data[0], &_eth_addr,
* sizeof(ifr->ifr_hwaddr.sa_data));
*
* was issued:
* ioctl.c:466:17: warning: 'memcpy' forming offset [7, 14] is out of the bounds [0, 6] of object
* '_eth_addr' with type 'eth_address' {aka 'unsigned char[6]'} [-Warray-bounds]
*/
#define FILL_hwaddr_sa_data(data, eth) \
memset (& data, '\0', sizeof(data)); \
memcpy (& data, & eth, sizeof(eth))
/*
* Handler for interface request get/set commands
*/
static int iface_ioctrl (Socket *socket, long cmd, void *argp)
{
struct ifreq *ifr = (struct ifreq *) argp;
struct ifconf *ifc = (struct ifconf*) argp;
struct sockaddr_in *sin;
#if defined(USE_IPV6)
struct sockaddr_in6 *sin6;
#endif
const eth_address *eth;
int len, i;
VERIFY_RW (argp, sizeof(*ifr));
switch (cmd)
{
case SIOCSARP:
case SIOCGARP:
case SIOCDARP:
return arp_ioctrl (socket, cmd, argp);
case SIOCGIFADDR: /* get interface address */
case OSIOCGIFADDR:
__get_ifname (ifr->ifr_name);
if (ifr->ifr_addr.sa_family == AF_INET)
{
sin = (struct sockaddr_in*) &ifr->ifr_addr;
sin->sin_addr.s_addr = htonl (my_ip_addr);
break;
}
#if defined(USE_IPV6)
if (ifr->ifr_addr.sa_family == AF_INET6)
{
sin6 = (struct sockaddr_in6*) &ifr->ifr_addr;
memcpy (&sin6->sin6_addr, &in6addr_my_ip, sizeof(sin6->sin6_addr));
break;
}
#endif
if (_pktdevclass == PDCLASS_TOKEN || /* otherwise return MAC addr? */
_pktdevclass == PDCLASS_ETHER ||
_pktdevclass == PDCLASS_ARCNET ||
_pktdevclass == PDCLASS_FDDI)
memcpy (&ifr->ifr_addr.sa_data[0], &_eth_addr, sizeof(_eth_addr));
else memset (&ifr->ifr_addr.sa_data[0], '\0', sizeof(ifr->ifr_addr.sa_data));
break;
case SIOCGIFMTU: /* get interface MTU */
ifr->ifr_mtu = _mtu;
break;
#if 0
case SIOCGIFNAME: /* get interface name */
break;
#endif
case SIOCSIFADDR: /* set interface address */
if (ifr->ifr_addr.sa_family == AF_INET)
{
sin = (struct sockaddr_in*) &ifr->ifr_addr;
my_ip_addr = ntohl (sin->sin_addr.s_addr);
break;
}
#if defined(USE_IPV6)
if (ifr->ifr_addr.sa_family == AF_INET6)
{
sin6 = (struct sockaddr_in6*) &ifr->ifr_addr;
memcpy ((void*)&in6addr_my_ip, &sin6->sin6_addr, sizeof(in6addr_my_ip));
break;
}
#endif
eth = (const eth_address*) ifr->ifr_addr.sa_data; /* ?? */
if (!_eth_set_addr(eth))
{
SOCK_ERRNO (EINVAL);
return (-1);
}
break;
case OSIOCGIFDSTADDR:
case SIOCGIFDSTADDR:
/** \todo Get point-to-point address */
break;
case SIOCSIFDSTADDR:
/** \todo Set point-to-point address */
break;
case SIOCSIFFLAGS: /* set iface flags */
/* Allow other socket types to do this?
*/
if (socket->so_type == SOCK_PACKET)
{
BOOL rc;
if (ifr->ifr_flags & IFF_PROMISC)
rc = _sock_set_promisc_rx_mode();
else if (ifr->ifr_flags & IFF_ALLMULTI)
rc = _sock_set_mcast_rx_mode();
else rc = _sock_set_normal_rx_mode (socket);
if (!rc)
{
SOCK_ERRNO (ENETDOWN);
return (-1);
}
}
break;
case SIOCGIFFLAGS: /* get iface flags */
ifr->ifr_flags = 0;
if (_eth_is_init)
{
ifr->ifr_flags |= (IFF_UP | IFF_RUNNING);
if (_pkt_rxmode == RXMODE_PROMISCOUS)
ifr->ifr_flags |= IFF_PROMISC;
if (_pkt_rxmode >= RXMODE_MULTICAST2)
ifr->ifr_flags |= IFF_ALLMULTI;
if (_pktdevclass == PDCLASS_PPP ||
_pktdevclass == PDCLASS_SLIP ||
_pktdevclass == PDCLASS_AX25)
ifr->ifr_flags |= IFF_POINTOPOINT;
else ifr->ifr_flags |= IFF_BROADCAST; /* ARCNET broadcast? */
#if defined(USE_MULTICAST)
if (_multicast_on)
ifr->ifr_flags |= IFF_MULTICAST;
#endif
}
break;
case SIOCGIFBRDADDR: /* get IP broadcast address */
case OSIOCGIFBRDADDR:
sin = (struct sockaddr_in*) &ifr->ifr_broadaddr;
sin->sin_addr.s_addr = htonl (my_ip_addr | ~sin_mask);
sin->sin_family = AF_INET;
__get_ifname (ifr->ifr_name);
break;
case SIOCSIFBRDADDR: /* set IP broadcast address */
break;
case SIOCGIFMETRIC: /* get interface metric */
ifr->ifr_metric = 1;
__get_ifname (ifr->ifr_name);
break;
case SIOCSIFMETRIC:
/** \todo Set interface metric */
break;
case SIOCDIFADDR: /* delete interface addr */
#if defined(USE_IPV6)
if (ifr->ifr_addr.sa_family == AF_INET6)
{
memset ((void*)&in6addr_my_ip, 0, sizeof(in6addr_my_ip));
break;
}
#endif
if (ifr->ifr_addr.sa_family == AF_INET)
{
my_ip_addr = 0;
break;
}
/** \todo Handle deleting interface address */
break;
case SIOCAIFADDR:
/** \todo Handle add/change interface alias */
break;
case SIOCGIFNETMASK: /* get interface net-mask */
case OSIOCGIFNETMASK:
sin = (struct sockaddr_in*) &ifr->ifr_addr;
sin->sin_addr.s_addr = htonl (sin_mask);
sin->sin_family = AF_INET;
__get_ifname (ifr->ifr_name);
break;
case SIOCSIFNETMASK: /* set interface net-mask */
sin = (struct sockaddr_in*) &ifr->ifr_addr;
sin_mask = ntohl (sin->sin_addr.s_addr);
break;
case SIOCGIFCONF: /* get interfaces config */
case OSIOCGIFCONF:
len = ifc->ifc_len = min (ifc->ifc_len, NUM_IFACES*SIZEOF(*ifr));
ifc = (struct ifconf*) ifc->ifc_buf; /* user's buffer */
VERIFY_RW (ifc, len);
i = 0;
for (ifr = (struct ifreq*)ifc; i < len; ifr++, i += sizeof(*ifr))
{
__get_ifname (ifr->ifr_name);
sin = (struct sockaddr_in*) &ifr->ifr_addr;
sin->sin_addr.s_addr = htonl (my_ip_addr);
sin->sin_family = AF_INET;
}
break;
case SIOCGIFHWADDR:
switch (_pktdevclass)
{
case PDCLASS_ETHER:
ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER;
FILL_hwaddr_sa_data (ifr->ifr_hwaddr.sa_data, _eth_addr);
break;
case PDCLASS_TOKEN:
ifr->ifr_hwaddr.sa_family = ARPHRD_TOKEN;
FILL_hwaddr_sa_data (ifr->ifr_hwaddr.sa_data, _eth_addr);
break;
case PDCLASS_FDDI:
ifr->ifr_hwaddr.sa_family = ARPHRD_FDDI;
FILL_hwaddr_sa_data (ifr->ifr_hwaddr.sa_data, _eth_addr);
break;
case PDCLASS_ARCNET:
ifr->ifr_hwaddr.sa_family = ARPHRD_ARCNET;
ifr->ifr_hwaddr.sa_data[0] = _eth_addr[0];
break;
case PDCLASS_SLIP:
case PDCLASS_PPP:
ifr->ifr_hwaddr.sa_family = 0;
memset (ifr->ifr_hwaddr.sa_data, '\0',
sizeof(ifr->ifr_hwaddr.sa_data));
break;
default:
return (-1);
}
break;
default:
NO_CMD (cmd);
SOCK_ERRNO (ESOCKTNOSUPPORT);
return (-1);
}
ARGSUSED (len);
return (0);
}
/*
* Handler for buffer hi/lo watermark and urgent data (OOB)
*/
static int waterm_ioctrl (Socket *socket, long cmd, void *argp)
{
switch (cmd)
{
case SIOCSHIWAT:
/** \todo set high watermark */
break;
case SIOCGHIWAT:
/** \todo get high watermark */
break;
case SIOCSLOWAT:
/** \todo set low watermark */
break;
case SIOCGLOWAT:
/** \todo get low watermark */
break;
case SIOCATMARK:
/** \todo OOB data available? */
break;
default:
NO_CMD (cmd);
SOCK_ERRNO (ESOCKTNOSUPPORT);
return (-1);
}
ARGSUSED (socket);
ARGSUSED (argp);
return (0);
}
/*
* Handler for ARP-cache interface commands
*/
static int arp_ioctrl (Socket *socket, long cmd, void *argp)
{
struct arpreq *arp = (struct arpreq*) argp;
eth_address *eth;
DWORD ip;
switch (cmd)
{
case SIOCSARP: /* add given IP/MAC-addr pair to ARP cache */
ip = intel (*(DWORD*)arp->arp_pa.sa_data);
eth = (eth_address*) arp->arp_ha.sa_data;
if (!_arp_cache_add (ip, (const eth_address*)eth, FALSE))
{
SOCK_ERRNO (EINVAL);
return (-1);
}
break;
case SIOCGARP: /* return ARP entry for given ip */
case OSIOCGARP:
ip = intel (*(DWORD*)arp->arp_pa.sa_data);
eth = (eth_address*) arp->arp_ha.sa_data;
if (_arp_lookup_fixed (ip, eth))
{
arp->arp_flags |= (ATF_INUSE | ATF_COM | ATF_PERM); /* fixed addr */
}
else if (_arp_lookup (ip, eth))
{
arp->arp_flags |= (ATF_INUSE | ATF_COM); /* dynamic addr */
}
else
{
arp->arp_flags = 0;
SOCK_ERRNO (ENOENT);
return (-1);
}
break;
case SIOCDARP: /* delete ARP-entry for given ip */
ip = intel (*(DWORD*)arp->arp_pa.sa_data);
if (!_arp_cache_del(ip))
{
SOCK_ERRNO (ENOENT);
return (-1);
}
break;
default:
NO_CMD (cmd);
SOCK_ERRNO (ESOCKTNOSUPPORT);
return (-1);
}
ARGSUSED (socket);
return (0);
}
/*
* Return string for ioctlsocket() command
*/
#if defined(USE_DEBUG)
static const struct search_list commands[] = {
{ FIOCLEX, "FIOCLEX" },
{ FIONCLEX, "FIONCLEX" },
{ FIONREAD, "FIONREAD" },
{ FIONBIO, "FIONBIO" },
{ FIOASYNC, "FIOASYNC" },
{ FIOSETOWN, "FIOSETOWN" },
{ FIOGETOWN, "FIOGETOWN" },
{ SIOCSPGRP, "SIOCSPGRP" },
{ SIOCGPGRP, "SIOCGPGRP" },
{ SIOCADDRT, "SIOCADDRT" },
{ SIOCDELRT, "SIOCDELRT" },
{ SIOCSIFADDR, "SIOCSIFADDR" },
{ OSIOCGIFADDR, "OSIOCGIFADDR" },
{ SIOCGIFADDR, "SIOCGIFADDR" },
{ SIOCSIFDSTADDR, "SIOCSIFDSTADDR" },
{ OSIOCGIFDSTADDR, "OSIOCGIFDSTADDR" },
{ SIOCGIFDSTADDR, "SIOCGIFDSTADDR" },
{ SIOCSIFFLAGS, "SIOCSIFFLAGS" },
{ SIOCGIFFLAGS, "SIOCGIFFLAGS" },
{ OSIOCGIFBRDADDR, "OSIOCGIFBRDADDR" },
{ SIOCGIFBRDADDR, "SIOCGIFBRDADDR" },
{ SIOCSIFBRDADDR, "SIOCSIFBRDADDR" },
{ OSIOCGIFCONF, "OSIOCGIFCONF" },
{ SIOCGIFCONF, "SIOCGIFCONF" },
{ OSIOCGIFNETMASK, "OSIOCGIFNETMASK" },
{ SIOCGIFNETMASK, "SIOCGIFNETMASK" },
{ SIOCSIFNETMASK, "SIOCSIFNETMASK" },
{ SIOCGIFMETRIC, "SIOCGIFMETRIC" },
{ SIOCSIFMETRIC, "SIOCSIFMETRIC" },
{ SIOCDIFADDR, "SIOCDIFADDR" },
{ SIOCAIFADDR, "SIOCAIFADDR" },
{ SIOCGIFMTU, "SIOCGIFMTU" },
{ SIOCSARP, "SIOCSARP" },
{ OSIOCGARP, "OSIOCGARP" },
{ SIOCGARP, "SIOCGARP" },
{ SIOCDARP, "SIOCDARP" },
{ SIOCSHIWAT, "SIOCSHIWAT" },
{ SIOCGHIWAT, "SIOCGHIWAT" },
{ SIOCSLOWAT, "SIOCSLOWAT" },
{ SIOCGLOWAT, "SIOCGLOWAT" },
{ SIOCATMARK, "SIOCATMARK" },
{ SIOCGIFHWADDR, "SIOCGIFHWADDR" }
};
static const char *get_ioctl_cmd (long cmd)
{
static char buf [50];
switch (IOCGROUP(cmd))
{
case 'f':
strcpy (buf, "file cmd: ");
break;
case 'I':
strcpy (buf, "iface cmd: ");
break;
case 's':
strcpy (buf, "waterm cmd: ");
break;
default:
return ("??unknown");
}
strcat (buf, list_lookup(cmd, commands, DIM(commands)));
return (buf);
}
#endif /* USE_DEBUG */
#endif /* USE_BSD_API */
/*
* A small test program for above functions.
*/
#if defined(TEST_PROG)
#if !defined(USE_BSD_API)
int main (void)
{
puts ("This program needs '#define USE_BSD_API'");
return (1);
}
#else /* rest of file */
#undef assert
#define assert(x) ((x) ? (void)0 : __assert_fail(__LINE__))
void __assert_fail (unsigned line)
{
fprintf (stderr, "\nAssert failed at line %d, errno = %d (%s)\n",
line, errno, strerror(errno));
exit (-1);
}
const char *eth_addr_string (struct ether_addr *eth)
{
static char buf [20];
sprintf (buf, "%02X:%02X:%02X:%02X:%02X:%02X",
eth->ether_addr_octet[0],
eth->ether_addr_octet[1],
eth->ether_addr_octet[2],
eth->ether_addr_octet[3],
eth->ether_addr_octet[4],
eth->ether_addr_octet[5]);
return (buf);
}
const char *if_flags_string (unsigned short flags)
{
static char buf [200];
buf[0] = '\0';
if (flags & IFF_UP)
strcat (buf, "up,");
if (flags & IFF_BROADCAST)
strcat (buf, "broadcast,");
if (flags & IFF_DEBUG)
strcat (buf, "debug,");
if (flags & IFF_LOOPBACK)
strcat (buf, "loopback,");
if (flags & IFF_POINTOPOINT)
strcat (buf, "p-to-p,");
if (flags & IFF_NOTRAILERS)
strcat (buf, "no-trail,");
if (flags & IFF_RUNNING)
strcat (buf, "running,");
if (flags & IFF_NOARP)
strcat (buf, "no-arp,");
if (flags & IFF_PROMISC)
strcat (buf, "promisc,");
if (flags & IFF_ALLMULTI)
strcat (buf, "all-multi,");
if (flags & IFF_OACTIVE)
strcat (buf, "out-act,");
if (flags & IFF_SIMPLEX)
strcat (buf, "simplex,");
if (flags & IFF_LINK0)
strcat (buf, "link0,");
if (flags & IFF_LINK1)
strcat (buf, "link1,");
if (flags & IFF_LINK2)
strcat (buf, "link2,");
if (flags & IFF_MULTICAST)
strcat (buf, "mcast,");
if (buf[0])
buf [strlen(buf)-1] = '\0';
return (buf);
}
int main (void)
{
struct ifreq ifr;
struct sockaddr_in *sin;
int sock, on = 1;
dbug_init();
sock = socket (AF_INET, SOCK_DGRAM, 0);
assert (sock > 0);
assert (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &on,sizeof(on)) == 0);
ifr.ifr_addr.sa_family = AF_UNSPEC; /* get MAC-address */
assert (ioctlsocket (sock, SIOCGIFADDR, (char*)&ifr) == 0);
printf ("Interface `%s':\n\t ether-addr: %s\n",
ifr.ifr_name,
eth_addr_string ((struct ether_addr*)&ifr.ifr_hwaddr.sa_data));
assert (ioctlsocket (sock, SIOCGIFBRDADDR, (char*)&ifr) == 0);
sin = (struct sockaddr_in*) &ifr.ifr_broadaddr;
printf ("\t bcast-addr: %s\n", inet_ntoa (sin->sin_addr));
ifr.ifr_addr.sa_family = AF_INET;
assert (ioctlsocket (sock, SIOCGIFADDR, (char*)&ifr) == 0);
sin = (struct sockaddr_in*) &ifr.ifr_addr;
printf ("\t inet-addr: %s\n", inet_ntoa (sin->sin_addr));
assert (ioctlsocket (sock, SIOCGIFNETMASK, (char*)&ifr) == 0);
sin = (struct sockaddr_in*) &ifr.ifr_addr;
printf ("\t net-mask : %s\n", inet_ntoa (sin->sin_addr));
assert (ioctlsocket (sock, SIOCGIFMTU, (char*)&ifr) == 0);
printf ("\t MTU : %u\n",ifr.ifr_mtu);
assert (ioctlsocket (sock, SIOCGIFFLAGS, (char*)&ifr) == 0);
printf ("\t Flags : 0x%04X: %s\n",
ifr.ifr_flags, if_flags_string(ifr.ifr_flags));
assert (close_s(sock) >= 0);
return (0);
}
#endif /* USE_BSD_API */
#endif /* TEST_PROG */
why you use Windows types for Watt-32 internal types instead of C language types. by example DWORD instead unsigned long or long C type?
Many projects use BYTE
and WORD
internally. E.g. FatFs for embedded systems. No relation to Windows.
why you use Windows types for Watt-32 internal types instead of C language types. by example DWORD instead unsigned long or long C type?
Many projects use
BYTE
andWORD
internally. E.g. FatFs for embedded systems. No relation to Windows.
Such projects are operating system independent and do not use any operating system header files and thus these types are in global namespace. But if you include such a project in some OS-specific application, you may have the same problem. Once you support multiple operating systems (like Watt-32) and need to include any OS header file, you have a problem with such types. So it's better to use your own namespace for example prefixed with W32_... for Watt-32 and not mix your code with these OS specific types. Such Watt-32 types do not conflict with any types of any OS, and if you need to, you can simply map between Watt-32 types and OS specific types without problems. I think main rule should be to use of C standard type where possible.
This pull request fixed #112