📄 ioctl.c
字号:
/*
*
* BSD sockets functionality for Waterloo TCP/IP
*
* Version
*
* 0.5 : Dec 18, 1997 : G. Vanem - created
*/
#define BSD /* in order to include SIOxx macros in <sys/ioctl.h> */
#include "socket.h"
#include "pcdbug.h"
#include "pcmulti.h"
#if defined(USE_BSD_FUNC)
static int file_ioctrl (Socket *socket, long cmd, char *argp);
static int iface_ioctrl (Socket *socket, long cmd, char *argp);
static int arp_ioctrl (Socket *socket, long cmd, char *argp);
static int waterm_ioctrl(Socket *socket, long cmd, char *argp);
#define NO_CMD(cmd) \
SOCK_DEBUGF ((socket, ", unsupported cmd %d, group %c", \
(int)((cmd) & IOCPARM_MASK), (char)IOCGROUP(cmd)))
#ifdef USE_DEBUG
static const char *get_ioctl_cmd (long cmd);
#endif
#define NUM_IFACES 1
int ioctlsocket (int s, long cmd, char *argp)
{
Socket *socket = _socklist_find (s);
SOCK_PROLOGUE (socket, "\nioctlsocket:%d", s);
#ifdef USE_DEBUG
_sock_debugf (socket, ", %s", get_ioctl_cmd(cmd));
#endif
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_ERR (ESOCKTNOSUPPORT);
}
return (-1);
}
/*
* IO-control for "file" handles (i.e. stream/datagram sockets)
*/
static int file_ioctrl (Socket *socket, long cmd, char *argp)
{
int len;
VERIFY_RW (argp, sizeof(*argp));
switch ((DWORD)cmd)
{
case FIONREAD:
if (socket->so_type != SOCK_DGRAM &&
socket->so_type != SOCK_STREAM)
{
SOCK_ERR (EBADF);
return (-1);
}
if (socket->so_state & SS_PRIV) /* must be SOCK_DGRAM */
len = sock_recv_used (socket->udp_sock);
else len = sock_rbused ((sock_type*)socket->tcp_sock);
SOCK_DEBUGF ((socket, " %d", len));
if (len >= 0)
*(u_long*)argp = len;
break;
case FIONBIO: /* set nonblocking I/O on/off */
if (socket->so_type != SOCK_STREAM)
{
SOCK_ERR (EBADF);
return (-1);
}
if (*argp)
socket->so_state |= SS_NBIO;
else socket->so_state &= ~SS_NBIO;
SOCK_DEBUGF ((socket, " %d", (socket->so_state & SS_NBIO) ? 1 : 0));
break;
default:
NO_CMD (cmd);
SOCK_ERR (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 tok_ifname [IFNAMSIZ] = "tr0";
static char fddi_ifname[IFNAMSIZ] = "fddi0";
static char ppp_ifname [IFNAMSIZ] = "ppp0";
static char slp_ifname [IFNAMSIZ] = "slp0";
static void get_ifname (char *if_name)
{
switch (_pktdevclass)
{
case PD_ETHER:
strcpy (if_name, eth_ifname);
break;
case PD_TOKEN:
strcpy (if_name, tok_ifname);
break;
case PD_FDDI:
strcpy (if_name, fddi_ifname);
break;
case PD_SLIP:
strcpy (if_name, slp_ifname);
break;
case PD_PPP:
strcpy (if_name, ppp_ifname);
break;
default:
strcpy (if_name, "??");
break;
}
}
#ifdef NOT_USED_YET
/*
* Set a new name for this interface.
*/
static void set_ifname (char *if_name)
{
switch (_pktdevclass)
{
case PD_ETHER:
strcpy (eth_ifname, if_name);
break;
case PD_TOKEN:
strcpy (tok_ifname, if_name);
break;
case PD_SLIP:
strcpy (slp_ifname, if_name);
break;
case PD_PPP:
strcpy (ppp_ifname, if_name);
break;
default:
break;
}
}
static struct ifnet *eth_ifnet (void)
{
static struct ifnet net;
/* to-do: fill info */
return (&net);
}
static struct ifnet *tok_ifnet (void)
{
static struct ifnet net;
/* to-do: fill info */
return (&net);
}
#endif
/*
* Handler for interface request get/set commands
*/
static int iface_ioctrl (Socket *socket, long cmd, char *argp)
{
struct ifreq *ifr = (struct ifreq *) argp;
struct ifconf *ifc = (struct ifconf*) argp;
eth_address *eth;
VERIFY_RW (argp, sizeof(*ifr));
switch ((DWORD)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)
{
struct sockaddr_in *sin = (struct sockaddr_in*) &ifr->ifr_addr;
sin->sin_addr.s_addr = htonl (my_ip_addr);
break;
}
#ifdef USE_INET6
if (ifr->ifr_addr.sa_family == AF_INET6)
{
struct sockaddr_in6 *sin = (struct sockaddr_in6*) &ifr->ifr_addr;
memcpy (&sin->sin6_addr, my_ip6_addr, sizeof(sin->sin6_addr));
break;
}
#endif
if (_pktdevclass == PD_TOKEN || /* otherwise return MAC addr? */
_pktdevclass == PD_ETHER ||
_pktdevclass == PD_FDDI)
memcpy (&ifr->ifr_addr.sa_data, &_eth_addr, sizeof(_eth_addr));
else memset (&ifr->ifr_addr.sa_data, 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)
{
struct sockaddr_in *sin = (struct sockaddr_in*) &ifr->ifr_addr;
my_ip_addr = ntohl (sin->sin_addr.s_addr);
break;
}
eth = (eth_address*) &ifr->ifr_addr.sa_data; /* ?? */
if (!_eth_set_addr(eth))
{
SOCK_ERR (EINVAL);
return (-1);
}
break;
case OSIOCGIFDSTADDR: /* get point-to-point address */
case SIOCGIFDSTADDR:
/* to-do !! */
break;
case SIOCSIFDSTADDR: /* set point-to-point address */
/* to-do !! */
break;
case SIOCSIFFLAGS: /* set ifnet flags */
/* to-do !! */
break;
case SIOCGIFFLAGS: /* get ifnet flags */
ifr->ifr_flags = 0;
if (_eth_is_init)
{
ifr->ifr_flags |= (IFF_UP | IFF_RUNNING);
if (_pktdevclass == PD_PPP ||
_pktdevclass == PD_SLIP)
ifr->ifr_flags |= IFF_POINTOPOINT;
#if defined(USE_MULTICAST)
if (_multicast_on)
ifr->ifr_flags |= IFF_MULTICAST;
#endif
}
break;
case SIOCGIFBRDADDR: /* get broadcast address */
case OSIOCGIFBRDADDR:
/* ifr->ifr_broadaddr.sa_family = ?? */
memset (&ifr->ifr_broadaddr.sa_data, 0, sizeof(ifr->ifr_addr.sa_data));
memcpy (&ifr->ifr_broadaddr.sa_data, &_eth_brdcast, sizeof(_eth_brdcast));
get_ifname (ifr->ifr_name);
break;
case SIOCSIFBRDADDR: /* set broadcast address */
memcpy (&_eth_brdcast, &ifr->ifr_broadaddr.sa_data, sizeof(_eth_brdcast));
break;
case SIOCGIFMETRIC: /* get interface meteric */
ifr->ifr_metric = 1;
get_ifname (ifr->ifr_name);
break;
case SIOCSIFMETRIC: /* set interface meteric */
/* to-do !! */
break;
case SIOCDIFADDR: /* delete interface addr */
if (ifr->ifr_addr.sa_family == AF_INET)
{
my_ip_addr = 0;
break;
}
/* to-do !! */
break;
case SIOCAIFADDR: /* add/change interface alias */
/* to-do !! */
break;
case SIOCGIFNETMASK: /* get interface net-mask */
case OSIOCGIFNETMASK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -