⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioctl.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *
 *   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 + -