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

📄 sockopt.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    case TCP_NOOPT:
         *(int*)val    = (tcp->locflags & LF_NOOPT);
         *(size_t*)len = sizeof (tcp->locflags);
         break;

    default:
         SOCK_ERR (ENOPROTOOPT);
         return (-1);
  }
  return (0);
}

/*
 * set/get UDP-layer options
 */
static int set_udp_opt (udp_Socket *udp, int opt, const void *val, int len)
{
  ARGSUSED (udp);      /* no udp option support yet */
  ARGSUSED (opt);
  ARGSUSED (val);
  ARGSUSED (len);
  SOCK_ERR (ENOPROTOOPT);
  return (-1);
}


static int get_udp_opt (udp_Socket *udp, int opt, void *val, int *len)
{
  ARGSUSED (udp);    /* no udp option support yet */
  ARGSUSED (opt);
  ARGSUSED (val);
  ARGSUSED (len);
  SOCK_ERR (ENOPROTOOPT);
  return (-1);
}

/*
 * set/get IP/ICMP-layer (raw/multicast) options
 */
static int set_raw_opt (Socket *s, int opt, const void *val, int len)
{
  BOOL on = *(BOOL*)val;
#ifdef USE_MULTICAST
  struct ip_mreq *l_pMreq;
  DWORD  ip;
#endif

  switch (opt)
  {
    case IP_OPTIONS:
         if (!s->ip_opt && (s->ip_opt = SOCK_CALLOC(sizeof(*s->ip_opt))) == NULL)
         {
           SOCK_ERR (ENOMEM);
           return (-1);
         }
         if (len == 0 && s->ip_opt)
         {
           free (s->ip_opt);
           s->ip_opt     = NULL;
           s->ip_opt_len = 0;
         }
         else
         {
           s->ip_opt_len = min (len, sizeof(*s->ip_opt));
           memcpy (&s->ip_opt->ip_opts, val, s->ip_opt_len);
         }
         break;

    case IP_HDRINCL:
         if (on)
              s->inp_flags |=  INP_HDRINCL;
         else s->inp_flags &= ~INP_HDRINCL;
         break;

    case IP_TOS:
         s->ip_tos = *(int*)val;
         if (s->tcp_sock)
             s->tcp_sock->tos = s->ip_tos;
         break;

    case IP_TTL:
         s->ip_ttl = min (1, *(int*)val);
         if (s->udp_sock)
            s->udp_sock->ttl = s->ip_ttl;
         else if (s->tcp_sock)
            s->tcp_sock->ttl = s->ip_ttl;
         break;

    case IP_ADD_MEMBERSHIP:
    case IP_DROP_MEMBERSHIP:
#ifdef USE_MULTICAST
         l_pMreq = (struct ip_mreq*)val;
         if (!l_pMreq || len < sizeof(*l_pMreq))
         {
           SOCK_ERR (EINVAL);
           return (-1);
         }
         ip = ntohl (l_pMreq->imr_multiaddr.s_addr);
         if (!is_multicast(ip))
         {
           SOCK_ERR (EINVAL);
           return (-1);
         }
         if (!_multicast_on)
         {
           SOCK_ERR (EADDRNOTAVAIL);
           return (-1);
         }
         if (opt == IP_ADD_MEMBERSHIP && !join_mcast_group(ip))
         {
           SOCK_ERR (ENOBUFS);        /* !!correct errno? */
           return (-1);
         }
         if (opt == IP_DROP_MEMBERSHIP && !leave_mcast_group(ip))
         {
           SOCK_ERR (EADDRNOTAVAIL);  /* !!correct errno? */
           return (-1);
         }
#endif
         break;

    case IP_RECVOPTS:
    case IP_RECVRETOPTS:
    case IP_RECVDSTADDR:
    case IP_RETOPTS:
    case IP_MULTICAST_IF:
    case IP_MULTICAST_TTL:
    case IP_MULTICAST_LOOP:
    case IP_MULTICAST_VIF:
    case IP_RSVP_ON:
    case IP_RSVP_OFF:
    case IP_RSVP_VIF_ON:
    case IP_RSVP_VIF_OFF:
    case IP_PORTRANGE:
    case IP_RECVIF:
         break;

    default:
         SOCK_ERR (ENOPROTOOPT);
         return (-1);
  }
  return (0);
}

static int get_raw_opt (Socket *s, int opt, void *val, int *len)
{
  switch (opt)
  {
    case IP_OPTIONS:
         if (s->ip_opt)
         {
           *len = s->ip_opt_len;
           memcpy (val, s->ip_opt->ip_opts, *len);
         }
         else
         {
           memset (val, 0, *len);
           *len = 0;
         }
         break;

    case IP_HDRINCL:
         *(int*)val = (s->inp_flags & INP_HDRINCL);
         break;

    case IP_TOS:
         *(int*)val = s->ip_tos;
         break;

    case IP_TTL:
         *(int*)val = s->ip_ttl;
         break;

    case IP_RECVOPTS:
    case IP_RECVRETOPTS:
    case IP_RECVDSTADDR:
    case IP_RETOPTS:
    case IP_MULTICAST_IF:
    case IP_MULTICAST_TTL:
    case IP_MULTICAST_LOOP:
    case IP_MULTICAST_VIF:
    case IP_RSVP_ON:
    case IP_RSVP_OFF:
    case IP_RSVP_VIF_ON:
    case IP_RSVP_VIF_OFF:
    case IP_PORTRANGE:
    case IP_RECVIF:
         break;

    case IP_ADD_MEMBERSHIP:
    case IP_DROP_MEMBERSHIP:
    default:
         SOCK_ERR (ENOPROTOOPT);
         return (-1);
  }
  return (0);
}

/*
 * Set receive buffer size for TCP.
 * Max size accepted is 64k * (2 << TCP_MAX_WINSHIFT) = 1MByte.
 * Or 64kB for small/large models.
 */
static int tcp_rx_buf (tcp_Socket *tcp, unsigned size)
{
  BYTE *buf;

  size = min (size, MAX_TCP_RECV_BUF);  /* 64kB/1MB */
  buf  = realloc (tcp->rdata, size);
  if (!buf)
  {
    SOCK_ERR (ENOMEM);
    return (-1);
  }

  /* Copy the data to new buffer. Data might be overlapping
   * hence using movmem(). Also clear rest of buffer.
   */
  if (tcp->rdatalen > 0)
  {
    int len = min ((long)size, tcp->rdatalen);

    movmem (tcp->rdata, buf, len);
    if (size > tcp->rdatalen)
       memset (tcp->rdata + tcp->rdatalen, 0, size - tcp->rdatalen);
  }
  tcp->rdata       = buf;
  tcp->maxrdatalen = size;
#if (DOSX)
  if (size > 64*1024)
     tcp->send_wscale = size >> 16;
#endif
  return (0);
}

/*
 * Set transmit buffer size for TCP.
 * Max size accepted is 64k.
 */
static int tcp_tx_buf (tcp_Socket *tcp, unsigned size)
{
#ifdef NOT_YET
  BYTE *buf;

  size = min (size, MAX_TCP_SEND_BUF);
  buf  = realloc (tcp->data, size);
  if (!buf)
  {
    SOCK_ERR (ENOMEM);
    return (-1);
  }

  /* Copy current data to new buffer. Data might be overlapping
   * hence using movmem().
   */
  if (tcp->datalen > 0)
  {
    int len = min ((long)size, udp->datalen);
    movmem (udp->data, buf, len);
  }
  udp->data       = buf;
  udp->maxdatalen = size;
#else
  ARGSUSED (tcp);
  ARGSUSED (size);
#endif
  return (0);
}

/*
 * Set receive buffer size for UDP.
 * Max size accepted is 64k.
 */
static int udp_rx_buf (udp_Socket *udp, unsigned size)
{
  BYTE *buf;

  size = min (size, MAX_UDP_RECV_BUF);
  buf  = realloc (udp->rdata, size);
  if (!buf)
  {
    SOCK_ERR (ENOMEM);
    return (-1);
  }

  /* Copy current data to new buffer. Data might be overlapping
   * hence using movmem(). Also clear rest of buffer.
   */
  if (udp->rdatalen > 0)
  {
    int len = min ((long)size, udp->rdatalen);

    movmem (udp->rdata, buf, len);
    if (size > udp->rdatalen)
       memset (buf + udp->rdatalen, 0, size - udp->rdatalen);
  }
  udp->rdata       = buf;
  udp->maxrdatalen = size;
  return (0);
}

/*
 * Set transmit buffer sizes for UDP.
 * Max size accepted is 64k.
 */
static int udp_tx_buf (udp_Socket *udp, unsigned size)
{
#ifdef NOT_YET
  BYTE *buf;

  size = min (size, MAX_UDP_SEND_BUF);
  buf  = realloc (udp->data, size);
  if (!buf)
  {
    SOCK_ERR (ENOMEM);
    return (-1);
  }
#else
  ARGSUSED (udp);
  ARGSUSED (size);
#endif
  return (0);
}


/*
 * Set receive buffer size for RAW socket
 */
static int raw_rx_buf (raw_Socket *raw, unsigned size)
{
  /* to-do !! */
  ARGSUSED (raw);
  ARGSUSED (size);
  return (0);
}

static int raw_tx_buf (raw_Socket *raw, unsigned size)
{
  /* to-do !! */
  ARGSUSED (raw);
  ARGSUSED (size);
  return (0);
}


/*
 * Set send buffer "low water marks"
 */
static int set_tx_lowat (Socket *sock, unsigned size)
{
  switch (sock->so_type)
  {
    case SOCK_STREAM:
         sock->send_lowat = min (size, MAX_TCP_SEND_BUF-1);
         break;
    case SOCK_DGRAM:
         sock->send_lowat = min (size, MAX_UDP_SEND_BUF-1);
         break;
    case SOCK_RAW:
         sock->send_lowat = min (size, sizeof(sock->raw_sock->data)-1);
         break;
    default:
         SOCK_ERR (ENOPROTOOPT);
         return (-1);
  }
  return (0);
}

/*
 * Set receive/transmit buffer "low water marks"
 */
static int set_rx_lowat (Socket *sock, unsigned size)
{
  switch (sock->so_type)
  {
    case SOCK_STREAM:
         if (sock->tcp_sock)
            sock->send_lowat = min (size, sock->tcp_sock->maxrdatalen);
         break;
    case SOCK_DGRAM:
         if (sock->udp_sock)
            sock->send_lowat = min (size, sock->udp_sock->maxrdatalen);
         break;
    case SOCK_RAW:
         sock->send_lowat = min (size, sizeof(sock->raw_sock->data));
         break;
    default:
         SOCK_ERR (ENOPROTOOPT);
         return (-1);
  }
  return (0);
}

/*
 * Get receive/transmit buffer "low water marks"
 */
static int get_tx_lowat (const Socket *sock, unsigned *size)
{
  if (sock->so_type == SOCK_STREAM ||
      sock->so_type == SOCK_DGRAM  ||
      sock->so_type == SOCK_RAW)
  {
    *size = sock->send_lowat;
    return (0);
  }
  SOCK_ERR (ENOPROTOOPT);
  return (-1);
}

static int get_rx_lowat (const Socket *sock, unsigned *size)
{
  if (sock->so_type == SOCK_STREAM ||
      sock->so_type == SOCK_DGRAM  ||
      sock->so_type == SOCK_RAW)
  {
    *size = sock->recv_lowat;
    return (0);
  }
  SOCK_ERR (ENOPROTOOPT);
  return (-1);
}

#if defined(USE_DEBUG)
/*
 * Handle printing of option names
 */
struct opt_list {
       int         opt_val;
       const char *opt_name;
     };

static const struct opt_list sol_options[] = {
                  { SO_DEBUG,       "SO_DEBUG"       },
                  { SO_ACCEPTCONN,  "SO_ACCEPTCONN"  },
                  { SO_REUSEADDR,   "SO_REUSEADDR"   },
                  { SO_KEEPALIVE,   "SO_KEEPALIVE"   },
                  { SO_DONTROUTE,   "SO_DONTROUTE"   },
                  { SO_BROADCAST,   "SO_BROADCAST"   },
                  { SO_USELOOPBACK, "SO_USELOOPBACK" },
                  { SO_LINGER,      "SO_LINGER"      },
                  { SO_OOBINLINE,   "SO_OOBINLINE"   },
                  { SO_SNDBUF,      "SO_SNDBUF"      },
                  { SO_RCVBUF,      "SO_RCVBUF"      },
                  { SO_SNDLOWAT,    "SO_SNDLOWAT"    },
                  { SO_RCVLOWAT,    "SO_RCVLOWAT"    },
                  { SO_SNDTIMEO,    "SO_SNDTIMEO"    },
                  { SO_RCVTIMEO,    "SO_RCVTIMEO"    },
                  { SO_ERROR,       "SO_ERROR"       },
                  { SO_TYPE,        "SO_TYPE"        }
                };

static const struct opt_list tcp_options[] = {
                  { TCP_NODELAY, "TCP_NODELAY" },
                  { TCP_MAXSEG,  "TCP_MAXSEG"  },
                  { TCP_NOPUSH,  "TCP_NOPUSH"  },
                  { TCP_NOOPT,   "TCP_NOOPT"   }
                };

static const struct opt_list raw_options[] = {
                  { IP_OPTIONS        , "IP_OPTIONS"         },
                  { IP_HDRINCL        , "IP_HDRINCL"         },
                  { IP_TOS            , "IP_TOS"             },
                  { IP_TTL            , "IP_TTL"             },
                  { IP_RECVOPTS       , "IP_RECVOPTS"        },
                  { IP_RECVRETOPTS    , "IP_RECVRETOPTS"     },
                  { IP_RECVDSTADDR    , "IP_RECVDSTADDR"     },
                  { IP_RETOPTS        , "IP_RETOPTS"         },
                  { IP_MULTICAST_IF   , "IP_MULTICAST_IF"    },
                  { IP_MULTICAST_TTL  , "IP_MULTICAST_TTL"   },
                  { IP_MULTICAST_LOOP , "IP_MULTICAST_LOOP"  },
                  { IP_ADD_MEMBERSHIP , "IP_ADD_MEMBERSHIP"  },
                  { IP_DROP_MEMBERSHIP, "IP_DROP_MEMBERSHIP" },
                  { IP_MULTICAST_VIF  , "IP_MULTICAST_VIF"   },
                  { IP_RSVP_ON        , "IP_RSVP_ON"         },
                  { IP_RSVP_OFF       , "IP_RSVP_OFF"        },
                  { IP_RSVP_VIF_ON    , "IP_RSVP_VIF_ON"     },
                  { IP_RSVP_VIF_OFF   , "IP_RSVP_VIF_OFF"    },
                  { IP_PORTRANGE      , "IP_PORTRANGE"       },
                  { IP_RECVIF         , "IP_RECVIF"          },
                  { IP_FW_ADD         , "IP_FW_ADD"          },
                  { IP_FW_DEL         , "IP_FW_DEL"          },
                  { IP_FW_FLUSH       , "IP_FW_FLUSH"        },
                  { IP_FW_ZERO        , "IP_FW_ZERO"         },
                  { IP_FW_GET         , "IP_FW_GET"          },
                  { IP_NAT            , "IP_NAT"             }
                };


static const char *lookup (int option, const struct opt_list *opt, int num)
{
  static char buf[10];

  while (num)
  {
    if (opt->opt_val == option)
       return (opt->opt_name);
    num--;
    opt++;
  }
  sprintf (buf, "?%d", option);
  return (buf);
}

static const char *sockopt_name (int option, int level)
{
  switch ((DWORD)level)
  {
    case IPPROTO_UDP:
         return ("udp option!?");

    case SOL_SOCKET:
         return lookup (option, sol_options, DIM(sol_options));

    case IPPROTO_TCP:
         return lookup (option, tcp_options, DIM(tcp_options));

    case IPPROTO_IP:
    case IPPROTO_ICMP:
         return lookup (option, raw_options, DIM(raw_options));

    default:
         return ("invalid level?");
  }
}

#endif  /* USE_DEBUG    */
#endif  /* USE_BSD_FUNC */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -