示例#1
0
文件: gethost.c 项目: jwt27/watt32
/*
 * Return a 'struct hostent *' for an address.
 */
struct hostent *W32_CALL gethostbyaddr (const char *addr_name, int len, int type)
{
  struct _hostent h;

  SOCK_DEBUGF (("\ngethostbyaddr: %s",
                (type == AF_INET && addr_name) ?
                inet_ntoa(*(struct in_addr*)addr_name) :
                (type == AF_INET6 && addr_name) ?
                _inet6_ntoa(addr_name) : ""));

#if defined(USE_IPV6)
  if (type == AF_INET6 && len == sizeof(struct in6_addr))
  {
    struct hostent *he;

    SOCK_ENTER_SCOPE();
    he = gethostbyaddr6 (addr_name);
    SOCK_LEAVE_SCOPE();
    return (he);
  }
#endif

  if (gethostbyaddr_internal (addr_name, len, type, &h))
  {
    SOCK_DEBUGF ((" `%s'", h.h_name));
    if (!did_lookup)
       SOCK_DEBUGF ((", %s", h.h_timeout ? "cached" : "hosts-file"));
    return fill_hostent (&h);
  }

  SOCK_DEBUGF ((" failed (%s) ", did_lookup ? dom_strerror(dom_errno) :
                hstrerror(h_errno)));
  return (NULL);
}
示例#2
0
/*
 * Unhook signal-handlers and raise() signals we caught.
 */
int _sock_sig_restore (void)
{
  int i;

  if (signal_depth == 0 ||
      --signal_depth > 0)
     return (0);

  _sock_stop_timer();

  for (i = 0; i < DIM(sig_tab); i++)
  {
    int sig = sig_tab[i].sig_num;

#if (USE_SIGMASK)
    sigset_t pending, new_set;

    if (sigpending(&pending) == 0 &&
        sigismember(&pending,sig))
    {
      /* The signal became pending while we blocked it.
       * I.e. ^C was pressed, so act on it.
       */
      sigemptyset (&new_set);
      sigaddset (&new_set, sig);

      SOCK_DEBUGF ((", raising %s", sig_tab[i].sig_name));
      SOCK_ENTER_SCOPE();
      sigprocmask (SIG_UNBLOCK, &new_set, NULL);
      SOCK_LEAVE_SCOPE();
    }
#else
    signal (sig, sig_tab[i].old);
    if (!sig_tab[i].caught)
       continue;

    sig_tab[i].caught = FALSE;
    if (sig_tab[i].exit &&
        (sig_tab[i].old == SIG_DFL ||
         sig_tab[i].old == SIG_IGN ||
         sig_tab[i].old == sig_handler_watt))
    {
      char buf[30];

      strcpy (buf, "\nTerminating on ");
      strcat (buf, sig_tab[i].sig_name);
      sock_sig_exit (buf, sig);
      /* no return */
    }
    SOCK_DEBUGF ((", raising %s", sig_tab[i].sig_name));
    SOCK_ENTER_SCOPE();
    raise (sig);
    SOCK_LEAVE_SCOPE();
    return (-1);
#endif
  }
  return (0);
}
示例#3
0
/*
 * Handle non-blocking SOCK_STREAM connection.
 * Only called on 2nd (3rd etc) time a non-blocking
 * connect() is called.
 */
static int nblk_connect (Socket *socket)
{
  if (socket->so_state & SS_ISCONNECTED)
  {
    SOCK_DEBUGF ((", connected!"));
    socket->so_error = 0;
    return (0);
  }

  /* Don't let tcp_Retransmitter() timeout this socket
   * (unless there is a ARP timeout etc.)
   */
  socket->tcp_sock->timeout = 0;

  if ((socket->so_state & (SS_ISDISCONNECTING | SS_CONN_REFUSED)) ||
      (socket->tcp_sock->state >= tcp_StateCLOSED))
  {
    if (socket->so_error != 0 && socket->so_error != EALREADY)
    {
      SOCK_DEBUGF ((", %s", short_strerror(socket->so_error)));
      SOCK_ERRNO (socket->so_error);
    }
    else if (chk_timeout(socket->nb_timer))
    {
      socket->so_state &= ~SS_ISCONNECTING;
      SOCK_DEBUGF ((", ETIMEDOUT (%s)", socket->tcp_sock->err_msg));
      socket->so_error = ETIMEDOUT;
      SOCK_ERRNO (ETIMEDOUT);
    }
    else
    {
      SOCK_DEBUGF ((", ECONNREFUSED"));
      socket->so_error = ECONNREFUSED;
      SOCK_ERRNO (ECONNREFUSED);       /* could also be ECONNRESET */
    }
    return (-1);
  }

  if (socket->so_state & SS_ISCONNECTING)
  {
    SOCK_DEBUGF ((", EALREADY"));
    socket->so_error = EALREADY;       /* should be redundant */
    SOCK_ERRNO (EALREADY);
    return (-1);
  }

  SOCK_FATAL (("%s (%d) Fatal: Unhandled non-block event\n",
              __FILE__, __LINE__));
  return (-1);
}
示例#4
0
int W32_CALL getsockname (int s, struct sockaddr *name, int *namelen)
{
  Socket *socket = _socklist_find (s);
  int     sa_len;

  SOCK_PROLOGUE (socket, "\ngetsockname:%d", s);

  sa_len = (socket->so_family == AF_INET6) ? sizeof(struct sockaddr_in6) :
                                             sizeof(struct sockaddr_in);

  if (!name || !namelen || (*namelen < sa_len))
  {
    SOCK_DEBUGF ((", EINVAL"));
    SOCK_ERRNO (EINVAL);
    if (namelen)
       *namelen = 0;
    return (-1);
  }

  if (!socket->local_addr)
  {
    SOCK_DEBUGF ((", EINVAL"));
    SOCK_ERRNO (EINVAL);    /* according to HP/UX manpage */
    return (-1);
  }

  VERIFY_RW (name, *namelen);

  *namelen = sa_len;
  memcpy (name, socket->local_addr, sa_len);

#if defined(USE_IPV6)
  if (socket->so_family == AF_INET6)
  {
    const struct sockaddr_in6 *la = (const struct sockaddr_in6*)socket->local_addr;

    SOCK_DEBUGF ((", %s (%d)", _inet6_ntoa(&la->sin6_addr), ntohs(la->sin6_port)));
    ARGSUSED (la);
  }
  else
#endif
  {
    const struct sockaddr_in *la = socket->local_addr;

    SOCK_DEBUGF ((", %s (%d)", inet_ntoa(la->sin_addr), ntohs(la->sin_port)));
    ARGSUSED (la);
  }
  return (0);
}
示例#5
0
/*
 *  Setup remote_addr for SOCK_RAW/SOCK_DGRAM (connectionless) protocols.
 *  Must reconnect socket if 'remote_addr' and 'to' address are different.
 *  I.e we're sending to another host/port than last time.
 */
static int setup_udp_raw (Socket *socket, const struct sockaddr *to, int tolen)
{
  struct sockaddr_in *peer = (struct sockaddr_in*) to;
  DWORD  keepalive = socket->keepalive;
  WORD   lport     = 0;
  char  *rdata     = NULL;
  int    rc;

  if (socket->so_state & SS_ISCONNECTED)
  {
    /* Don't reconnect if same peer address/port.
     */
    if (peer->sin_addr.s_addr == socket->remote_addr->sin_addr.s_addr &&
        peer->sin_port        == socket->remote_addr->sin_port)
       return (1);

    SOCK_DEBUGF ((socket, ", reconnecting"));

    free (socket->remote_addr);
    socket->remote_addr = NULL;

    /* Clear any effect of previous ICMP errors etc.
     */
    socket->so_state &= ~(SS_CONN_REFUSED|SS_CANTSENDMORE|SS_CANTRCVMORE);
    socket->so_error  = 0;

    if (socket->so_type == SOCK_DGRAM)
    {
      lport = socket->udp_sock->myport;
      rdata = (char*)socket->udp_sock->rdata;  /* preserve current data */
    }
  }

  /* For SOCK_DGRAM, udp_close() will be called when (re)opening socket.
   */
  _sock_enter_scope();
  rc = connect (socket->fd, to, tolen);
  _sock_leave_scope();

  if (rc < 0)
     return (-1);


  if (rdata)  /* Must be SOCK_DGRAM */
  {
    udp_Socket *udp = socket->udp_sock;

    free (udp->rdata);                /* free new rx-buffer set in connect() */
    udp->rdata       = (BYTE*) rdata; /* reuse previous data buffer */
    udp->maxrdatalen = DEFAULT_RCV_WIN;

    grab_localport (lport);   /* Restore freed localport */
  }

  /* restore keepalive timer changed in connect()
   */
  socket->keepalive = keepalive;
  return (1);
}
示例#6
0
int W32_CALL getpeername (int s, struct sockaddr *name, int *namelen)
{
  Socket *socket = _socklist_find (s);
  int     sa_len;

  SOCK_PROLOGUE (socket, "\ngetpeername:%d", s);

  sa_len = (socket->so_family == AF_INET6) ? sizeof(struct sockaddr_in6) :
                                             sizeof(struct sockaddr_in);

  if (!name || !namelen || (*namelen < sa_len))
  {
    SOCK_DEBUGF ((", EINVAL"));
    SOCK_ERRNO (EINVAL);
    if (namelen)
       *namelen = 0;
    return (-1);
  }

  if (!(socket->so_state & SS_ISCONNECTED))
  {
    SOCK_DEBUGF ((", ENOTCONN"));
    SOCK_ERRNO (ENOTCONN);
    return (-1);
  }
  VERIFY_RW (name, *namelen);

  *namelen = sa_len;
  memcpy (name, socket->remote_addr, *namelen);

#if defined(USE_IPV6)
  if (socket->so_family == AF_INET6)
  {
    const struct sockaddr_in6 *ra = (const struct sockaddr_in6*)socket->remote_addr;
    SOCK_DEBUGF ((", %s (%d)", _inet6_ntoa(&ra->sin6_addr), ntohs(ra->sin6_port)));
    ARGSUSED (ra);
  }
  else
#endif
  {
    const struct sockaddr_in *ra = socket->remote_addr;
    SOCK_DEBUGF ((", %s (%d)", inet_ntoa(ra->sin_addr), ntohs(ra->sin_port)));
    ARGSUSED (ra);
  }
  return (0);
}
示例#7
0
/*
 * Check for catched signals
 */
static int chk_signals (void)
{
  if (_sock_sig_pending())
  {
    SOCK_DEBUGF ((", EINTR"));
    SOCK_ERRNO (EINTR);
    return (-1);
  }
  return (0);
}
示例#8
0
/*
 * Handle SOCK_DGRAM connection. Always blocking in _arp_resolve()
 */
static int udp_connect (Socket *socket)
{
#if defined(USE_IPV6)
  if (socket->so_family == AF_INET6)
  {
    const struct sockaddr_in6 *la = (const struct sockaddr_in6*) socket->local_addr;
    const struct sockaddr_in6 *ra = (const struct sockaddr_in6*) socket->remote_addr;

    if (!_UDP6_open (socket, &ra->sin6_addr, la->sin6_port, ra->sin6_port))
    {
      SOCK_DEBUGF ((", no route (udp6)"));
      SOCK_ERRNO (EHOSTUNREACH);
      STAT (ip6stats.ip6s_noroute++);
      return (-1);
    }
  }
  else
#endif
  if (!_UDP_open (socket,
                  socket->remote_addr->sin_addr,
                  socket->local_addr->sin_port,
                  socket->remote_addr->sin_port))
  {
    /* errno already set in udp_open() */
    SOCK_DEBUGF ((", %s", socket->udp_sock->err_msg));
    return (-1);
  }

  if ((socket->so_state & SS_PRIV) && socket->bcast_pool)
  {
    /* undo what udp_open() did above.
     * !!Fix me: clears recv data.
     */
    sock_recv_init ((sock_type*)socket->udp_sock,
                    socket->bcast_pool, socket->pool_size);
  }

  socket->so_state &= ~SS_UNCONNECTED;
  socket->so_state |=  SS_ISCONNECTED;
  return (0);
}
示例#9
0
文件: gethost.c 项目: jwt27/watt32
/*
 * Return a 'struct hostent *' for name.
 */
struct hostent * W32_CALL gethostbyname (const char *name)
{
  struct _hostent h;
  const char *alias;

  SOCK_DEBUGF (("\ngethostbyname: `%s'", name));

  if (gethostbyname_internal(name, &alias, &h))
  {
#if defined(USE_DEBUG)
    int i;
    for (i = 0; i < h.h_num_addr; i++)
        SOCK_DEBUGF ((" %s,", inet_ntoa(*(struct in_addr*)&h.h_address[i])));

    if (!did_lookup)
       SOCK_DEBUGF ((" %s", h.h_timeout ? "cached" :
                     from_where ? from_where : "hosts-file"));

    if (alias)
       SOCK_DEBUGF ((" (alias %s)", alias));
#endif
    return fill_hostent (&h);
  }

  if (called_from_resolve)
       SOCK_DEBUGF ((", unknown (called from resolve)"));
  else SOCK_DEBUGF ((", failed (%s)", did_lookup ? dom_strerror(dom_errno) :
                      hstrerror(h_errno)));
  return (NULL);
}
示例#10
0
int _sock_sig_setup (void)
{
    volatile int sig;

    if (signal_depth > 0)
        return (0);

    if (++signal_depth > 1)
        return (0);

    _sock_start_timer();
    wat_brkmode = wathndlcbrk;
    wathndlcbrk = 0;
    watcbroke   = 0;

    sigalrm_caught = sigbrk_caught  = 0;
    sigint_caught  = sigquit_caught = 0;

    old_sigint = signal (SIGINT, sig_catch);

#if defined(SIGQUIT)
    old_sigquit = signal (SIGQUIT, sig_catch);
#endif

#if defined(SIGBREAK)
    old_sigbrk = signal (SIGBREAK, sig_catch);
#endif

#if defined(SIGPIPE)
    old_sigpipe = signal (SIGPIPE, sig_catch);
#endif

#if defined(SIGALRM) && TRAP_SIGALRM
    old_sigalrm = signal (SIGALRM, sig_catch);
    block_sigalrm();
#endif

    sig = setjmp (sig_jmp);
    if (sig == 0)
        return (0);


    /* We'll get here only when sig_catch() calls longjmp()
     */
    SOCK_DEBUGF ((NULL, ", interrupted by %s\n", sig_name(sig)));
    _sock_sig_restore();
    return (-1);
}
示例#11
0
int sock_fgets (char *buf, int max, FILE *stream)
{
  int        rc, s = fileno (stream);
  Socket    *sock  = _socklist_find (s);
  sock_type *sk    = NULL;

  SOCK_PROLOGUE (sock, "\nsock_fgets:%d", s);

  if (sock->tcp_sock)
     sk = (sock_type*) sock->tcp_sock;
  else if (sock->udp_sock)
     sk = (sock_type*) sock->udp_sock;

  rc = sk ? sock_gets (sk, (BYTE*)buf, max) : -1;

  SOCK_DEBUGF ((", rc %d", rc));
  return (rc);
}
示例#12
0
文件: gethost.c 项目: jwt27/watt32
int main (void)
{
  const struct hostent *h;
  const char *host_name = "test-host";
  int   wait_time;
  DWORD addr_list [MAX_ADDRESSES+1];

  dbug_init();
  sock_init();
  print_hosts();

  wait_time = netdbCacheLife + 1;
  memset (&addr_list, 0, sizeof(addr_list));
  addr_list[0] = htonl (_inet_addr("80.22.33.45"));
  addr_list[1] = htonl (_inet_addr("222.22.33.46"));
  addr_list[2] = htonl (_inet_addr("217.22.33.47"));
  addr_list[3] = htonl (_inet_addr("81.22.33.48"));
  addr_list[4] = INADDR_NONE;

  SOCK_DEBUGF (("\nadd_hostent: `%s'", host_name));
  add_hostent (NULL, host_name, "some.cname.org", &addr_list[1],
               addr_list[0], netdbCacheLife);
  h = gethostbyname (host_name);
  if (!h)
  {
    fprintf (stderr, "gethostbyname() failed!. h_errno = %d\n", h_errno);
    return (1);
  }
  fprintf (stderr, "Waiting for cache-entry to timeout..");
  Sleep (wait_time);

  fprintf (stderr, "gethostbyname() should do a DNS lookup now.\n");
  h = gethostbyname (host_name);
  if (h)
     fprintf (stderr, "entry didn't timeout!.\n");

#if defined(USE_FORTIFY)
  Fortify_ListAllMemory();
  Fortify_OutputStatistics();
#endif
  return (0);
}
示例#13
0
文件: get_ip.c 项目: basecq/q2dos
void W32_CALL freehostent (struct hostent *he)
{
  char *p;

  SOCK_DEBUGF (("\nfreehostent: %s ", he->h_name));

  if (!he->h_name)   /* possible double freeing */
     return;

  free (he->h_name);
  he->h_name = NULL;

  for (p = he->h_addr_list[0]; p; p++)
      free (p);

  for (p = he->h_aliases[0]; p; p++)
      free (p);

  free (he->h_aliases);
  free (he->h_addr_list);
  free (he);
}
示例#14
0
/*
 *  Allocate and fill local/remote addresses for 'clone'.
 *  Take local address from 'socket', and remote address from
 *  TCB of clone.
 */
static int alloc_addr (Socket *socket, Socket *clone)
{
  struct in_addr peer;

  clone->local_addr  = SOCK_CALLOC (sizeof(*clone->local_addr));
  clone->remote_addr = SOCK_CALLOC (sizeof(*clone->remote_addr));

  if (!clone->local_addr || !clone->remote_addr)
  {
    SOCK_DEBUGF ((socket, ", ENOMEM"));
    SOCK_ERR (ENOMEM);
    return (-1);
  }

  peer.s_addr = htonl (clone->tcp_sock->hisaddr);
  clone->local_addr->sin_family  = AF_INET;
  clone->local_addr->sin_port    = socket->local_addr->sin_port;
  clone->local_addr->sin_addr    = socket->local_addr->sin_addr;

  clone->remote_addr->sin_family = AF_INET;
  clone->remote_addr->sin_port   = htons (clone->tcp_sock->hisport);
  clone->remote_addr->sin_addr   = peer;
  return (0);
}
示例#15
0
文件: gethost.c 项目: jwt27/watt32
void DumpHostsCache (void)
{
  struct _hostent *h;
  time_t now;

  if (!ReverseHostsList())
     return;

  SOCK_DEBUGF ((" \n\nCached IPv4 hosts:                         "
                "Address         TTL       Alias\n"));
  now = time (NULL);

  for (h = host0; h; h = h->h_next)
  {
    const char *ip_str, *cache_time;
    int   i;

    if (h->h_real_ttl == 0)   /* skip fixed hosts-file records */
       continue;

    cache_time = ((long)(h->h_timeout - now) < 0) ? "timedout" :
                  hms_str(h->h_real_ttl);
    ip_str     = (h->h_address[0] == INADDR_NONE) ? "<none>" :
                  inet_ntoa(*(struct in_addr*)&h->h_address[0]);

    SOCK_DEBUGF (("  %-40s %-15s %8s  ", h->h_name, ip_str, cache_time));
    for (i = 0; h->h_aliases[i]; i++)
        SOCK_DEBUGF (("%s ", h->h_aliases[i]));
    if (i == 0)
         SOCK_DEBUGF (("<none>\n"));
    else SOCK_DEBUGF ((" \n"));

    for (i = 1; i < h->h_num_addr; i++)
        SOCK_DEBUGF (("%42s %s\n", "",
                      inet_ntoa(*(struct in_addr*)&h->h_address[i])));
  }
}
示例#16
0
/*
 *  Raw IP transmitter
 */
static int ip_transmit (Socket *socket, const void *tx, int len)
{
  eth_address eth;
  u_long      dest;
  unsigned    tx_len, tx_room;
  sock_type  *sk = (sock_type*)socket->udp_sock;

  struct ip   *ip  = (struct ip*) tx;
  const  BYTE *buf = (const BYTE*) tx;
  WORD   flags     = 0;
  DWORD  offset;
  UINT   h_len, o_len;

  tcp_tick (NULL);        /* process other TCBs too */
  tcp_Retransmitter (1);

  /* This should never happen
   */
  if (ip && (socket->so_state & SS_NBIO) &&
      sock_tbleft(sk) < (len + socket->send_lowat))
  {
    SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
    SOCK_ERR (EWOULDBLOCK);
    return (-1);
  }

  if (ip)
  {
    offset = ntohs (ip->ip_off);
    flags  = offset & ~IP_OFFMASK;
    offset = (offset & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */
  }

  SOCK_DEBUGF ((socket, ", %s / Raw",
                inet_ntoa(socket->remote_addr->sin_addr)));

  if (ip && (socket->inp_flags & INP_HDRINCL))
  {
    dest    = ip->ip_dst.s_addr;
    tx_len  = len;
    tx_room = mtu;
  }
  else
  {
    dest    = socket->remote_addr->sin_addr.s_addr;
    tx_len  = len + sizeof (*ip);
    tx_room = mtu + sizeof (*ip);
  }

  if (!dest || !_arp_resolve(ntohl(dest),&eth,0))
  {
    SOCK_DEBUGF ((socket, ", no route"));
    SOCK_ERR (EHOSTUNREACH);
    STAT (ipstats.ips_noroute++);
    return (-1);
  }

#if defined(USE_FRAGMENTS)
  if (!(socket->inp_flags & INP_HDRINCL) &&
      tx_len + socket->ip_opt_len > tx_room)
  {
    sk = (sock_type*)socket->raw_sock;

    if (flags & IP_DF)
    {
      SOCK_DEBUGF ((socket, ", EMSGSIZE"));
      SOCK_ERR (EMSGSIZE);
      STAT (ipstats.ips_toolong++);
      return (-1);
    }
    return SEND_IP_FRAGMENTS (sk, sk->raw.ip_type, dest, buf, len);
  }
#else
  if (!(socket->inp_flags & INP_HDRINCL) &&
      tx_len + socket->ip_opt_len > tx_room)
  {
    SOCK_DEBUGF ((socket, ", EMSGSIZE"));
    SOCK_ERR (EMSGSIZE);
    STAT (ipstats.ips_toolong++);
    return (-1);
  }
#endif

  ip = (struct ip*) _eth_formatpacket (&eth, IP_TYPE);

  if (socket->inp_flags & INP_HDRINCL)
  {
    memcpy (ip, buf, len);
    if (ip->ip_src.s_addr == 0)
    {
      ip->ip_src.s_addr = gethostid();
      ip->ip_sum = 0;
      ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2);
    }
    if (ip->ip_sum == 0)
        ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2);
  }
  else
  {
    if (socket->ip_opt && socket->ip_opt_len > 0)
    {
      BYTE *data;

      o_len = min (socket->ip_opt_len, sizeof(socket->ip_opt->ip_opts));
      h_len = sizeof(*ip) + o_len;
      data  = (BYTE*)ip + h_len;
      memcpy (ip+1, &socket->ip_opt->ip_opts, o_len);
      memcpy (data, buf, len);
      tx_len += o_len;
      if (socket->ip_opt->ip_dst.s_addr)   /* using source routing */
         dest = socket->ip_opt->ip_dst.s_addr;
    }
    else
    {
      if (buf)
         memcpy (ip+1, buf, len);
      h_len = sizeof (*ip);
    }

    ip->ip_v   = IPVERSION;
    ip->ip_hl  = h_len >> 2;
    ip->ip_tos = socket->ip_tos;
    ip->ip_len = htons (tx_len);
    ip->ip_id  = _get_ip_id();
    ip->ip_off = 0;
    ip->ip_ttl = socket->ip_ttl;
    ip->ip_p   = socket->so_proto;

    ip->ip_src.s_addr = gethostid();
    ip->ip_dst.s_addr = dest;

    ip->ip_sum = 0;
    ip->ip_sum = ~checksum (ip, h_len);
  }

  DEBUG_TX (NULL, ip);

  if (!_eth_send(tx_len))
  {
    SOCK_DEBUGF ((socket, ", ENETDOWN"));
    SOCK_ERR (ENETDOWN);
    return (-1);
  }
  if (buf)
     buf += tx_len;

  return (len);
}
示例#17
0
/*
 *  UDP transmitter
 */
static int udp_transmit (Socket *socket, const void *buf, int len)
{
  sock_type *sk   = (sock_type*) socket->udp_sock;
  u_long     dest = socket->remote_addr->sin_addr.s_addr;
  int        tx_room, rc;
  int        is_bcast, is_multi;

  if (!tcp_tick(sk))
  {
    socket->so_state |= SS_CANTSENDMORE;
    SOCK_DEBUGF ((socket, ", ENOTCONN (can't send)")); /* !! or EPIPE */
    SOCK_ERR (ENOTCONN);
    return (-1);
  }
  tcp_Retransmitter (1);

  if ((socket->so_state & SS_NBIO) && check_non_block_tx(socket,&len) < 0)
  {
    SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
    SOCK_ERR (EWOULDBLOCK);
    return (-1);
  }

  is_bcast = (dest == INADDR_BROADCAST || dest == INADDR_ANY);
  is_multi = IN_MULTICAST (ntohl(socket->remote_addr->sin_addr.s_addr));

  SOCK_DEBUGF ((socket, ", %s (%d) / UDP %s",
                inet_ntoa(socket->remote_addr->sin_addr),
                ntohs(socket->remote_addr->sin_port),
                is_multi ? "(mc)" : ""));

  if (len == 0)   /* 0-byte probe packet */
     return ip_transmit (socket, NULL, 0);

  tx_room = sock_tbleft (sk);  /* always MTU-28 */

  /* Special tests for broadcast messages
   */
  if (is_bcast)
  {
    if (len > tx_room)        /* don't allow fragments */
    {
      SOCK_DEBUGF ((socket, ", EMSGSIZE"));
      SOCK_ERR (EMSGSIZE);
      STAT (ipstats.ips_odropped++);
      return (-1);
    }
    if (_pktserial)           /* Link-layer doesn't allow broadcast */
    {
      SOCK_DEBUGF ((socket, ", EADDRNOTAVAIL"));
      SOCK_ERR (EADDRNOTAVAIL);
      STAT (ipstats.ips_odropped++);
      return (-1);
    }
  }

  /* set new TTL if setsockopt() used before sending to Class-D socket
   */
  if (is_multi)
     sk->udp.ttl = socket->ip_ttl;

#if defined(USE_FRAGMENTS)
  if ((long)len > USHRT_MAX - sizeof(udp_Header))
  {
    SOCK_DEBUGF ((socket, ", EMSGSIZE"));
    SOCK_ERR (EMSGSIZE);
    STAT (ipstats.ips_toolong++);
    return (-1);
  }

  if (len > tx_room)
     return SEND_IP_FRAGMENTS (sk, UDP_PROTO, dest, buf, len);
#endif

  rc = sock_write (sk, (BYTE*)buf, len);
  if (rc <= 0)    /* error in udp_write() */
  {
    SOCK_DEBUGF ((socket, ", ENETDOWN"));
    SOCK_ERR (ENETDOWN);
    return (-1);
  }
  return (rc);
}
示例#18
0
/*
 *  TCP transmitter
 */
static int tcp_transmit (Socket *socket, const void *buf, int len, int flags)
{
  sock_type *sk = (sock_type*)socket->tcp_sock;

  tcp_tick (sk);
  tcp_Retransmitter (1);

  if (sk->tcp.state < tcp_StateESTAB || sk->tcp.state >= tcp_StateLASTACK)
  {
    socket->so_state |= SS_CANTSENDMORE;
    SOCK_DEBUGF ((socket, ", ENOTCONN (%s)",  /* !! or EPIPE */
                 (sk->tcp.locflags & LF_GOT_FIN) ?
                   "got FIN" : "can't send"));
    SOCK_ERR (ENOTCONN);
    return (-1);
  }

  if (socket->so_state & SS_NBIO)
  {
    int in_len = len;

    if (check_non_block_tx(socket,&len) < 0)
    {
      SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
      SOCK_ERR (EWOULDBLOCK);
      return (-1);
    }
    if (in_len != len)
       SOCK_DEBUGF ((socket, " [%d]", len)); /* trace "len=x [y]" */
  }

  SOCK_DEBUGF ((socket, ", %s (%d) / TCP",
                inet_ntoa(socket->remote_addr->sin_addr),
                ntohs(socket->remote_addr->sin_port)));

#if 0
  /* Must wait for room in send buffer
   */
  if ((flags & MSG_WAITALL) || len > sock_tbleft(sk))
       len = sock_write (sk, (BYTE*)buf, len);
  else len = sock_fastwrite (sk, (BYTE*)buf, len);

#else
  /* This is more efficient. The above sock_fastwrite() would
   * effectively turn off Nagle's algorithm.
   */
  ARGSUSED (flags);
  len = sock_write (sk, (BYTE*)buf, len);
#endif

  if (len <= 0)    /* error in tcp_write() */
  {
    if (sk->tcp.state != tcp_StateESTAB)
    {
      SOCK_DEBUGF ((socket, ", ENOTCONN"));
      SOCK_ERR (ENOTCONN);   /* maybe EPIPE? */
    }
    else
    {
      SOCK_DEBUGF ((socket, ", ENETDOWN"));
      SOCK_ERR (ENETDOWN);
    }
    return (-1);
  }
  return (len);
}
示例#19
0
文件: gethost.c 项目: jwt27/watt32
/*
 * Modify an expired cached entry or create a new node and
 * add it to the linked list. Not used for entries in hosts-file.
 */
static struct _hostent  *add_hostent
       (struct _hostent *h,
        const char      *name,   /* Host name */
        const char      *cname,  /* Canonical name (CNAME) */
        DWORD           *alist,  /* List of alternate addresses */
        DWORD            addr,   /* Main IP-address */
        DWORD            ttl)    /* Time-to-live (sec) */
{
  DWORD real_ttl = ttl;
  int   i;

  ttl = min (ttl, netdbCacheLife);  /* clamp the TTL */

  if (h)         /* reuse expired entry */
  {
    if (h->h_name)
       free (h->h_name);
    if (h->h_aliases[0])
       free (h->h_aliases[0]);     /* !! max 1 alias */
    memset (&h->h_address[1], 0,   /* clear old alternates */
            sizeof(h->h_address)-sizeof(u_long));
    h->h_aliases[0] = NULL;
  }
  else           /* create a new node */
  {
    h = (struct _hostent*) calloc (sizeof(*h), 1);
    if (h)
    {
      h->h_next = host0;
      host0 = h;
    }
  }

  if (!cname || !cname[0])
     cname = NULL;

  if (addr != INADDR_NONE)
     SOCK_DEBUGF ((", CNAME %s, ttl %lus,",
                   cname ? cname : "<none>", real_ttl));
  if (h)
  {
    h->h_timeout    = ttl ? time (NULL) + ttl : 0;
    h->h_real_ttl   = real_ttl;
    h->h_address[0] = addr;
    h->h_num_addr   = 1;

    for (i = 0; alist; i++)
    {
      if (alist[i] == INADDR_NONE || alist[i] == INADDR_ANY)
         break;
      h->h_address[i+1] = alist[i];
      h->h_num_addr++;
    }
    if (cname)    /* swap name with CNAME */
    {
      h->h_name       = strdup (cname);
      h->h_aliases[0] = strdup (name);  /* !! only allow 1 alias */
    }
    else
      h->h_name = strdup (name);
  }
  else
    SOCK_DEBUGF ((" ENOMEM"));

#if defined(TEST_PROG)  /* test updated cache */
  if (h)
  {
    printf ("new entry: name %-30.30s -> address %s ",
            h->h_name, inet_ntoa(*(struct in_addr*)&h->h_address[0]));
    for (i = 1; i < h->h_num_addr; i++)
        printf (", %s",
                inet_ntoa(*(struct in_addr*)&h->h_address[i]));
    puts ("");
  }
  else
    printf ("new entry: ENOMEM\n");
#endif

  return (h);
}
示例#20
0
/*
 * transmit() flags:
 *   MSG_DONTROUTE                                     (not supported)
 *   MSG_EOR       Close sending side after data sent
 *   MSG_TRUNC                                         (not supported)
 *   MSG_CTRUNC                                        (not supported)
 *   MSG_OOB                                           (not supported)
 *   MSG_WAITALL   Wait till room in tx-buffer         (not supported)
 */
static int transmit (const char *func, int s, const void *buf, int len,
                     int flags, const struct sockaddr *to, int tolen)
{
  Socket *socket = _socklist_find (s);
  int     rc;

  SOCK_DEBUGF ((socket, "\n%s:%d, len=%d", func, s, len));

  if (!socket)
  {
    if (_sock_dos_fd(s))
    {
      SOCK_DEBUGF ((NULL, ", ENOTSOCK"));
      SOCK_ERR (ENOTSOCK);
      return (-1);
    }
    SOCK_DEBUGF ((NULL, ", EBADF"));
    SOCK_ERR (EBADF);
    return (-1);
  }

  if (socket->so_type == SOCK_STREAM ||      /* TCP-socket or */
      (socket->so_state & SS_ISCONNECTED))   /* "connected" udp/raw */
  {
    /* Note: SOCK_RAW doesn't really need a local address/port, but
     * makes the code more similar for all socket-types.
     * Disadvantage is that SOCK_RAW ties up a local port and a bit
     * more memory.
     */

    if (!socket->local_addr)
    {
      SOCK_DEBUGF ((socket, ", no local_addr"));
      SOCK_ERR (ENOTCONN);
      return (-1);
    }

    if (!socket->remote_addr)
    {
      SOCK_DEBUGF ((socket, ", no remote_addr"));
      SOCK_ERR (ENOTCONN);
      return (-1);
    }

    if (socket->so_state & SS_CONN_REFUSED)
    {
      if (socket->so_error == ECONNRESET)  /* set in tcp_sockreset() */
      {
        SOCK_DEBUGF ((socket, ", ECONNRESET"));
        SOCK_ERR (ECONNRESET);
      }
      else
      {
        SOCK_DEBUGF ((socket, ", ECONNREFUSED"));
        SOCK_ERR (ECONNREFUSED);
      }
      return (-1);
    }
  }

  /* connectionless protocol setup
   */
  if (socket->so_type == SOCK_DGRAM || socket->so_type == SOCK_RAW)
  {
    if (!to || tolen < sizeof(*to))
    {
      SOCK_DEBUGF ((socket, ", no to-addr"));
      SOCK_ERR (EINVAL);
      return (-1);
    }
    if (setup_udp_raw(socket,to,tolen) < 0)
       return (-1);
  }

  VERIFY_RW (buf, len);


  /* Setup SIGINT handler now.
   */
  if (_sock_sig_setup() < 0)
  {
    SOCK_ERR (EINTR);
    return (-1);
  }

  switch (socket->so_type)
  {
    case SOCK_DGRAM:
         rc = udp_transmit (socket, buf, len);
         break;

    case SOCK_STREAM:
         rc = tcp_transmit (socket, buf, len, flags);
         break;

    case SOCK_RAW:
         rc = ip_transmit (socket, buf, len);
         break;

    default:
         SOCK_DEBUGF ((socket, ", EPROTONOSUPPORT"));
         SOCK_ERR (EPROTONOSUPPORT);
         rc = -1;
  }

  _sock_sig_restore();

  if (rc >= 0 && (flags & MSG_EOR))
     msg_eor_close (socket);

  return (rc);
}
示例#21
0
/*
 * Unhook signal-handlers and optionally chain to previous handlers
 * if we caught signals.
 */
void _sock_sig_restore (void)
{
    if (signal_depth == 0)
        return;

    if (--signal_depth > 0)
        return;

    _sock_stop_timer();
    watcbroke   = 0;
    wathndlcbrk = wat_brkmode;

#if defined(SIGALRM) && TRAP_SIGALRM
    signal (SIGALRM, old_sigalrm);
    unblock_sigalrm();

#if 0
    /* don't do this since a socket function might be called from an
     * alarm handler. This could cause serious recursion and stack fault.
     */
    if (sigalrm_caught && old_sigalrm != SIG_IGN && old_sigalrm != SIG_DFL)
    {
        sigalrm_caught = 0;
        (*old_sigalrm) (SIGALRM);
    }
#endif
#endif

#if defined(SIGBREAK)
    signal (SIGBREAK, old_sigbrk);
    if (sigbrk_caught && old_sigbrk != SIG_IGN && old_sigbrk != SIG_DFL)
    {
        sigbrk_caught = 0;
        (*old_sigbrk) (SIGBREAK);
    }
#endif

#if defined(SIGPIPE)
    signal (SIGPIPE, old_sigpipe);
    if (sigpipe_caught)
    {
        if (old_sigpipe != SIG_IGN && old_sigpipe != SIG_DFL)
        {
            sigpipe_caught = 0;
            (*old_sigpipe) (SIGPIPE);
        }
        else
        {
            outsnl (_LANG("Terminating on SIGPIPE"));
            exit (-1);
        }
    }
#endif

#if defined(SIGQUIT)
    signal (SIGQUIT, old_sigquit);
    if (sigquit_caught)
    {
        if (old_sigquit != SIG_IGN && old_sigquit != SIG_DFL)
        {
            sigquit_caught = 0;
            (*old_sigquit) (SIGQUIT);
        }
        else
        {
            SOCK_DEBUGF ((NULL, "\nExiting stuck program"));
            exit (-1);
        }
    }
#endif

    signal (SIGINT, old_sigint);
    if (sigint_caught && old_sigint != SIG_IGN && old_sigint != SIG_DFL)
    {
        sigint_caught = 0;
        (*old_sigint) (SIGINT);
    }

    sigalrm_caught = sigbrk_caught  = 0;
    sigint_caught  = sigquit_caught = 0;
    sigpipe_caught = 0;
}
示例#22
0
/*
 * connect()
 *  "connect" will attempt to open a connection on a foreign IP address and
 *  foreign port address.  This is achieved by specifying the foreign IP
 *  address and foreign port number in the "servaddr".
 */
int W32_CALL connect (int s, const struct sockaddr *servaddr, int addrlen)
{
  struct   sockaddr_in  *addr   = (struct sockaddr_in*) servaddr;
  struct   sockaddr_in6 *addr6  = (struct sockaddr_in6*) servaddr;
  struct   Socket       *socket = _socklist_find (s);
  volatile int rc, sa_len;
  BOOL     is_ip6;

  SOCK_PROLOGUE (socket, "\nconnect:%d", s);

  is_ip6 = (socket->so_family == AF_INET6);
  sa_len = is_ip6 ? sizeof(*addr6) : sizeof(*addr);

  if (_sock_chk_sockaddr(socket, servaddr, addrlen) < 0)
     return (-1);

  if (socket->so_type == SOCK_STREAM)
  {
    if (socket->so_state & SS_ISCONNECTED)
    {
      SOCK_DEBUGF ((", EISCONN"));
      SOCK_ERRNO (EISCONN);
      return (-1);
    }
    if (socket->so_options & SO_ACCEPTCONN)
    {
      SOCK_DEBUGF ((", EOPNOTSUPP (listen sock)"));
      SOCK_ERRNO (EOPNOTSUPP);
      return (-1);
    }
    if (!is_ip6 && IN_MULTICAST(ntohl(addr->sin_addr.s_addr)))
    {
      SOCK_DEBUGF ((", EINVAL (mcast)"));
      SOCK_ERRNO (EINVAL);
      return (-1);
    }
    else if (is_ip6 && IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr))
    {
      SOCK_DEBUGF ((", EINVAL (mcast)"));
      SOCK_ERRNO (EINVAL);
      return (-1);
    }
  }

  if (socket->remote_addr)
  {
    if ((socket->so_type == SOCK_STREAM) &&
        (socket->so_state & SS_NBIO))
       return nblk_connect (socket);

    SOCK_DEBUGF ((", connect already done!"));
    SOCK_ERRNO (EISCONN);
    return (-1);
  }

  socket->remote_addr = (struct sockaddr_in*) SOCK_CALLOC (sa_len);
  if (!socket->remote_addr)
  {
    SOCK_DEBUGF ((", ENOMEM (rem)"));
    SOCK_ERRNO (ENOMEM);
    return (-1);
  }

#if defined(USE_IPV6)
  if (is_ip6)
  {
    struct sockaddr_in6 *ra = (struct sockaddr_in6*)socket->remote_addr;

    ra->sin6_family = AF_INET6;
    ra->sin6_port   = addr6->sin6_port;
    memcpy (&ra->sin6_addr, &addr6->sin6_addr, sizeof(ra->sin6_addr));
  }
  else
#endif
  {
    socket->remote_addr->sin_family = AF_INET;
    socket->remote_addr->sin_port   = addr->sin_port;
    socket->remote_addr->sin_addr   = addr->sin_addr;
  }

  if (!socket->local_addr)
  {
    SOCK_DEBUGF ((", auto-binding"));

    socket->local_addr = (struct sockaddr_in*) SOCK_CALLOC (sa_len);
    if (!socket->local_addr)
    {
      free (socket->remote_addr);
      socket->remote_addr = NULL;
      SOCK_DEBUGF ((", ENOMEM (loc)"));
      SOCK_ERRNO (ENOMEM);
      return (-1);
    }

#if defined(USE_IPV6)
    if (is_ip6)
    {
      struct sockaddr_in6 *la = (struct sockaddr_in6*)socket->local_addr;

      la->sin6_family = AF_INET6;
      la->sin6_port   = htons (find_free_port(0,TRUE));
      memcpy (&la->sin6_addr, &in6addr_my_ip, sizeof(la->sin6_addr));
    }
    else
#endif
    {
      socket->local_addr->sin_family      = AF_INET;
      socket->local_addr->sin_port        = htons (find_free_port(0,TRUE));
      socket->local_addr->sin_addr.s_addr = htonl (my_ip_addr);
    }
  }

  SOCK_DEBUGF ((", src/dest ports: %u/%u",
                ntohs(socket->local_addr->sin_port),
                ntohs(socket->remote_addr->sin_port)));


  /* Not safe to run sock_daemon() now
   */
  _sock_crit_start();

  /* Setup SIGINT handler now.
   */
  if (_sock_sig_setup() < 0)
  {
    SOCK_ERRNO (EINTR);
    SOCK_DEBUGF ((", EINTR"));
    _sock_crit_stop();
    return (-1);
  }

  switch (socket->so_type)
  {
    case SOCK_STREAM:
         rc = tcp_connect (socket);
         break;

    case SOCK_DGRAM:
         rc = udp_connect (socket);
         break;

    case SOCK_RAW:
         rc = raw_connect (socket);
         break;

    default:
         SOCK_ERRNO (EPROTONOSUPPORT);
         rc = -1;
         break;
  }

  _sock_sig_restore();
  _sock_crit_stop();
  return (rc);
}
示例#23
0
/*
 * Handle SOCK_STREAM blocking connection. Or non-blocking connect
 * the first time connect() is called.
 */
static int tcp_connect (Socket *socket)
{
  DWORD timeout;
  int   status;

#if defined(USE_IPV6)
  if (socket->so_family == AF_INET6)
  {
    const struct sockaddr_in6 *la = (const struct sockaddr_in6*) socket->local_addr;
    const struct sockaddr_in6 *ra = (const struct sockaddr_in6*) socket->remote_addr;

    if (!_TCP6_open (socket, &ra->sin6_addr, la->sin6_port, ra->sin6_port))
    {
      /* errno already set in _TCP6_open() */
      SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg));
      return (-1);
    }
  }
  else
#endif
  if (!_TCP_open (socket,
                  socket->remote_addr->sin_addr,
                  socket->local_addr->sin_port,
                  socket->remote_addr->sin_port))
  {
    /* errno already set in tcp_open() */
    SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg));
    return (-1);
  }

  /* Don't let tcp_Retransmitter() kill this socket
   * before our `socket->timeout' expires
   */
  socket->tcp_sock->locflags |= LF_RCVTIMEO;

  /* We're here only when connect() is called the 1st time
   * (blocking or non-blocking socket).
   */
  socket->so_state |= SS_ISCONNECTING;
  timeout = set_timeout (1000 * socket->timeout);

  if (socket->so_state & SS_NBIO)
  {
    /* if user calls getsockopt(SO_ERROR) before calling connect() again
     */
    socket->so_error = EALREADY;
    socket->nb_timer = timeout;
    SOCK_DEBUGF ((", EINPROGRESS"));
    SOCK_ERRNO (EINPROGRESS);
    return (-1);
  }

  /* Handle blocking stream socket connect.
   * Maybe we should use select_s() instead ?
   * Maybe set LF_NOCLOSE for all BSD sockets?
   */
  status = _ip_delay0 ((sock_type*)socket->tcp_sock,
                       socket->timeout, (UserHandler)chk_signals,
                       NULL);

  if (socket->so_error == EHOSTUNREACH)
  {
    SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg ?
                  socket->tcp_sock->err_msg : "no route"));
    SOCK_ERRNO (EHOSTUNREACH);
    return (-1);
  }

  /* We got an ICMP_UNREACH from someone
   */
  if (socket->so_state & SS_CONN_REFUSED)
  {
    socket->so_state &= ~SS_ISCONNECTING;
    SOCK_DEBUGF ((", ECONNREFUSED"));
    SOCK_ERRNO (ECONNREFUSED);
    return (-1);
  }

  if (status < 0 && chk_timeout(timeout))
  {
    socket->so_state &= ~SS_ISCONNECTING;
    SOCK_DEBUGF ((", ETIMEDOUT"));
    SOCK_ERRNO (ETIMEDOUT);
    return (-1);
  }

  if (status < 0)
  {
    socket->so_state &= ~SS_ISCONNECTING;
    SOCK_DEBUGF ((", ECONNRESET"));
    SOCK_ERRNO (ECONNRESET);
    return (-1);
  }

  socket->so_state &= ~(SS_UNCONNECTED | SS_ISCONNECTING);
  socket->so_state |=  SS_ISCONNECTED;
  return (0);
}
示例#24
0
int accept (int s, struct sockaddr *addr, int *addrlen)
{
  Socket  *clone, *socket;
  volatile DWORD   timeout;
  volatile int     newsock = -1;
  volatile int     que_idx;
  volatile int     maxconn;

  socket = _socklist_find (s);

  SOCK_PROLOGUE (socket, "\naccept:%d", s);

  if (!socket->local_addr)
  {
    SOCK_DEBUGF ((socket, ", not bound"));
    SOCK_ERR (ENOTCONN);
    return (-1);
  }

  if (socket->so_type != SOCK_STREAM)
  {
    SOCK_DEBUGF ((socket, ", EOPNOTSUPP"));
    SOCK_ERR (EOPNOTSUPP);
    return (-1);
  }

  if (!(socket->so_options & SO_ACCEPTCONN)) /* listen() not called */
  {
    SOCK_DEBUGF ((socket, ", not SO_ACCEPTCONN"));
    SOCK_ERR (EINVAL);
    return (-1);
  }

  if (!(socket->so_state & (SS_ISLISTENING | SS_ISCONNECTING)))
  {
    SOCK_DEBUGF ((socket, ", not listening"));
    SOCK_ERR (ENOTCONN);
    return (-1);
  }

  if (addr && addrlen)
  {
    if (*addrlen < sizeof(*addr))
    {
      SOCK_DEBUGF ((socket, ", EFAULT"));
      SOCK_ERR (EFAULT);
      return (-1);
    }
    VERIFY_RW (addr, *addrlen);
  }

  /* Get max possible TCBs on listen-queue.
   * Some (or all) may be NULL until a SYN comes in.
   */
  maxconn = socket->backlog;
  if (maxconn < 1 || maxconn > SOMAXCONN)
  {
    SOCK_FATAL (("%s(%d): Illegal socket backlog %d",
                __FILE__, __LINE__, maxconn));
    SOCK_ERR (EINVAL);
    return (-1);
  }

  if (socket->timeout)
       timeout = set_timeout (1000 * socket->timeout);
  else timeout = 0UL;


  if (_sock_sig_setup() < 0)
  {
    SOCK_ERR (EINTR);
    goto accept_fail;
  }

  /* Loop over all queue-slots and accept first connected TCB
   */
  for (que_idx = 0; ; que_idx = (++que_idx % maxconn))
  {
    tcp_Socket *sk = socket->listen_queue [que_idx];

    tcp_tick (NULL);

    SOCK_YIELD();

    /* No SYNs received yet. This shouldn't happen if we called 'accept()'
     * after 'select_s()' said that socket was readable. (At least one
     * connection on the listen-queue).
     */
    if (sk)
    {
      /* This could happen if 'accept()' was called too long after connection
       * was established and then closed by peer. This could also happen if
       * someone did a portscan on us. I.e. he sent 'SYN', we replied with
       * 'SYN+ACK' and he never sent an 'ACK'. Thus we timeout in
       * 'tcp_Retransmitter()' and abort the TCB.
       *
       * Queue slot is in any case ready for another 'SYN' to come and be
       * handled by '_sock_append()'.
       */
      if (sk->state >= tcp_StateLASTACK && sk->ip_type == 0)
      {
        SOCK_DEBUGF ((socket, ", aborted TCB (idx %d)", que_idx));
        listen_free (socket, que_idx);
        continue;
      }

      /* !!to-do: Should maybe loop over all maxconn TCBs and accept the
       *          one with oldest 'syn_timestamp'.
       */
      if (tcp_established(sk))
      {
        SOCK_DEBUGF ((socket, ", connected! (idx %d)", que_idx));
        break;
      }
    }

    /* We've polled all listen-queue slots and none are connected.
     * Return fail if socket is non-blocking.
     */
    if (que_idx == maxconn-1 && (socket->so_state & SS_NBIO))
    {
      SOCK_DEBUGF ((socket, ", would block"));
      SOCK_ERR (EWOULDBLOCK);
      goto accept_fail;
    }

    if (chk_timeout(timeout))
    {
      SOCK_DEBUGF ((socket, ", ETIMEDOUT"));
      SOCK_ERR (ETIMEDOUT);
      goto accept_fail;
    }
  }

  /* We're here only when above 'tcp_established()' succeeded.
   * Now duplicate 'socket' into a new listening socket 'clone'
   * with handle 'newsock'.
   */
  _sock_enter_scope();
  newsock = dup_bind (socket, &clone, que_idx);
  if (newsock < 0)
     goto accept_fail;

  if (alloc_addr(socket, clone) < 0)
  {
    SOCK_DEL_FD (newsock);
    goto accept_fail;
  }

  /* Clone is connected, but *not* listening/accepting.
   * Note: other 'so_state' bits from parent is unchanged.
   *       e.g. clone may be non-blocking.
   */
  clone->so_state   |=  SS_ISCONNECTED;
  clone->so_state   &= ~(SS_ISLISTENING | SS_ISCONNECTING);
  clone->so_options &= ~SO_ACCEPTCONN;

  /* Prevent a PUSH on first segment sent.
   */
  sock_noflush ((sock_type*)clone->tcp_sock);

  SOCK_DEBUGF ((clone, "\nremote %s (%d)",
                inet_ntoa (clone->remote_addr->sin_addr),
                ntohs (clone->remote_addr->sin_port)));

  if (addr && addrlen)
  {
    struct sockaddr_in *sa = (struct sockaddr_in*)addr;

    sa->sin_family = AF_INET;
    sa->sin_port   = clone->remote_addr->sin_port;
    sa->sin_addr   = clone->remote_addr->sin_addr;
    memset (sa->sin_zero, 0, sizeof(sa->sin_zero));
    *addrlen = sizeof(*sa);
  }

  _sock_leave_scope();
  _sock_sig_restore();
  return (newsock);

accept_fail:
  _sock_leave_scope();
  _sock_sig_restore();
  return (-1);
}
示例#25
0
/*
 *  Called from tcp_fsm.c / tcp_listen_state() (via _tcp_syn_hook) to
 *  append a new connection to the listen-queue of socket 'sock'.
 *
 *  TCB on input ('orig') has received a SYN. Replace TCB on output
 *  with a cloned TCB that we append to the listen-queue and eventually
 *  is used by accept() to create a new socket.
 *
 *  TCB on input ('orig') must still be listening for further connections
 *  on the same port as specified in call to _TCP_listen().
 */
int _sock_append (tcp_Socket **tcp)
{
  tcp_Socket *clone;
  tcp_Socket *orig = *tcp;
  Socket     *sock = NULL;   /* associated socket for '*tcp' */
  int         i;

  /* Lookup BSD-socket for Wattcp TCB
   */
  if (!_tcp_find_hook || (sock = (*_tcp_find_hook)(orig)) == NULL)
  {
    SOCK_DEBUGF ((NULL, "\n  sock_append: not found!?"));
    return (0);  /* i.e. could be a native Wattcp socket */
  }

  SOCK_DEBUGF ((sock, "\n  sock_append:%d", sock->fd));

  if (!(sock->so_options & SO_ACCEPTCONN))
  {
    SOCK_DEBUGF ((sock, ", not SO_ACCEPTCONN"));
    return (-1);  /* How could this happen? */
  }

  /* Find the first vacant slot for this clone
   */
  for (i = 0; i < sock->backlog; i++)
      if (!sock->listen_queue[i])
         break;

  if (i >= sock->backlog || i >= SOMAXCONN)
  {
    /* !!to-do: drop the oldest (or a random) slot in the listen-queue.
     */
    SOCK_DEBUGF ((sock, ", queue full (idx %d)", i));
    return (-1);
  }

  SOCK_DEBUGF ((sock, ", idx %d", i));

  clone = SOCK_CALLOC (sizeof(*clone));
  if (!clone)
  {
    SOCK_DEBUGF ((sock, ", ENOMEM"));
    return (-1);
  }

  /* Link in the semi-connected socket (SYN received, ACK will be sent)
   */
  sock->listen_queue[i]  = clone;
  sock->syn_timestamp[i] = set_timeout (0);

  /* Copy the TCB (except Tx-buffer) to clone
   */
  memcpy (clone, orig, sizeof(*clone) - sizeof(clone->data));
  clone->safetytcp = SAFETYTCP;

  /* Increase the TCP window (to 16kB)
   */
  sock_setbuf ((sock_type*)clone, calloc(DEFAULT_RCV_WIN,1), DEFAULT_RCV_WIN);

  /* Undo what tcp_handler() and tcp_listen_state() did to
   * this listening socket.
   */
  orig->hisport = 0;
  orig->hisaddr = 0;
  orig->myaddr  = 0;

  orig->seqnum  = INIT_SEQ();   /* set new ISS */
  orig->unhappy = FALSE;
  CLR_PEER_MAC_ADDR (orig);

#if defined(USE_DEBUG)          /* !!needs some work */
  orig->last_acknum[0] = orig->last_acknum[1] = 0;
  orig->last_seqnum[0] = orig->last_seqnum[1] = 0;
#endif

  clone->next  = _tcp_allsocs;
  _tcp_allsocs = clone;         /* prepend clone to TCB-list */
  *tcp = clone;                 /* clone is now the new TCB */
  return (0);
}
示例#26
0
int sock_recv_from (sock_type *s, void *hisip, WORD *hisport,
                    void *buffer, unsigned len, int peek)
{
#if !defined(USE_UDP_ONLY)
  _tcp_Socket *t;
#endif
  recv_buf    *p, *oldest = NULL;
  recv_data   *r = (recv_data*) s->udp.rx_data;
  long seqnum = LONG_MAX;
  int  i;

  if (r->recv_sig != RECV_USED)
  {
    SOCK_ERRNO (EBADF);

    /* To differentiate an error from 0-byte probe (also -1) */
    return (-1);
  }

  switch (s->udp.ip_type)
  {
    case UDP_PROTO:
         p = (recv_buf*) r->recv_bufs;

         /* find the oldest used UDP buffer.
          */
         for (i = 0; i < r->recv_bufnum; i++, p++)
         {
           switch (p->buf_sig)
           {
             case RECV_UNUSED:
                  break;

             case RECV_USED:
                  /* Drop looped packets sent by us (running
                   * under Win32 DOS box using NDIS3PKT or SwsVpkt).
                   */
                  if ((_eth_ndis3pkt || _eth_SwsVpkt) &&
                      !s->tcp.is_ip6 && p->buf_hisip == intel(my_ip_addr))
                  {
                    p->buf_sig = RECV_UNUSED;
                    continue;
                  }
                  if (p->buf_seqnum < seqnum)  /* ignore wraps */
                  {
                    seqnum = p->buf_seqnum;
                    oldest = p;
#if 0
                    SOCK_DEBUGF (("\nsock_recv_from(): buffer %d, "
                                  "seq-num %ld, len %d",
                                  i, seqnum, p->buf_len));
#endif
                  }
                  break;

             default:
                  outsnl (_LANG("ERROR: sock_recv_init data err"));
                  return (0);
           }
         }
         break;

#if !defined(USE_UDP_ONLY)
    case TCP_PROTO:
         t = &s->tcp;
         len = min (len, (unsigned)t->rx_datalen);
         if (len)
             memcpy (buffer, r->recv_bufs, len);
         return (len);
#endif
  }

  if (!oldest)
     return (0);

  /* found the oldest UDP packet */

  p = oldest;
  if (p->buf_len < 0)  /* a 0-byte probe packet */
     len = -1;
  else
  {
    len = min ((unsigned)p->buf_len, len);
    memcpy (buffer, p->buf_data, len);
  }

#if defined(USE_IPV6)
  if (s->tcp.is_ip6)
  {
    if (hisip)
       memcpy (hisip, &p->buf_hisip6, sizeof(ip6_address));
  }
  else
#endif
  if (hisip)
     *(DWORD*)hisip = p->buf_hisip;

  if (hisport)
     *hisport = p->buf_hisport;

  if (!peek)
     p->buf_sig = RECV_UNUSED;
  return (len);
}
示例#27
0
文件: get_ip.c 项目: basecq/q2dos
/*
 * AI_V4MAPPED + AF_INET6
 * If no IPv6 address then a query for IPv4 and map returned values.
 *
 * AI_ALL + AI_V4MAPPED + AF_INET6
 * Return IPv6 and IPv4 mapped.
 *
 * AI_ADDRCONFIG
 * Only return IPv6 / IPv4 address if there is an interface of that
 * type active.
 */
struct hostent * W32_CALL
getipnodebyname (const char *name, int af, int flags, int *error)
{
  struct hostent *he1 = NULL;
  struct hostent *he2 = NULL;
  struct in_addr  in4;
  struct in6_addr in6;
  BOOL   have_v4 = TRUE, have_v6 = TRUE;
  BOOL   v4 = FALSE, v6 = FALSE;
  int    tmp_err;

  SOCK_DEBUGF (("\ngetipnodebyname: %s ", name));

  /* If we care about active interfaces then check.
   */
  if (flags & AI_ADDRCONFIG)
     scan_interface (&have_v4, &have_v6);

  /* Check for literal address.
   */
  v4 = inet_pton (AF_INET, name, &in4);
  if (!v4)
     v6 = inet_pton (AF_INET6, name, &in6);

  /* Impossible combination?
   */
  if ((af == AF_INET6 && !(flags & AI_V4MAPPED) && v4) ||
      (af == AF_INET && v6) ||
      (!have_v4 && v4) ||
      (!have_v6 && v6) ||
      (!have_v4 && af == AF_INET) ||
      ((!have_v6 && af == AF_INET6) && ((flags & AI_V4MAPPED) && have_v4)) ||
      !(flags & AI_V4MAPPED))
  {
    *error = HOST_NOT_FOUND;
    return (NULL);
  }

  /* Literal address?
   */
  if (v4 || v6)
  {
    struct hostent he;
    char  *addr_list[2];
    char  *aliases[1];

    he.h_name         = (char*) name;
    he.h_addr_list    = addr_list;
    he.h_addr_list[0] = (v4 ? (char*)&in4 : (char*)&in6);
    he.h_addr_list[1] = NULL;
    he.h_aliases      = aliases;
    he.h_aliases[0]   = NULL;
    he.h_length       = (v4 ? INADDRSZ : IN6ADDRSZ);
    he.h_addrtype     = (v4 ? AF_INET  : AF_INET6);
    return copyandmerge (&he, NULL, af, error);
  }

  tmp_err = NO_RECOVERY;
  if (have_v6 && af == AF_INET6)
  {
#if defined(USE_IPV6)
    he1 = gethostbyname6 (name);
#else
    he1 = NULL;
#endif
    if (!he1)
       tmp_err = HOST_NOT_FOUND;
  }

  if (have_v4 &&
      (af == AF_INET ||
       (af == AF_INET6 &&
        (flags & AI_V4MAPPED) && (!he1 || (flags & AI_ALL)))))
  {
    SOCK_ENTER_SCOPE();
    he2 = gethostbyname (name);
    SOCK_LEAVE_SCOPE();
    if (!he2 || !he1)
    {
      *error = HOST_NOT_FOUND;
      return (NULL);
    }
  }
  else
    *error = tmp_err;

  return copyandmerge (he1, he2, af, error);
}
示例#28
0
/*
 * Gets upcalled when data arrives.
 * We MUST set 'p->buf_len = -1' to signal a 0-byte UDP packet
 * not 0
 */
static int sock_recvdaemon (sock_type *s, const void *data, unsigned len,
                            const tcp_PseudoHeader *ph, const udp_Header *udp)
{
  recv_data *r;
  recv_buf  *p;
  unsigned   i;

  switch (s->udp.ip_type)
  {
    case UDP_PROTO:
         r = (recv_data*) s->udp.rx_data;
         p = (recv_buf*) r->recv_bufs;
         if (r->recv_sig != RECV_USED)
         {
           outsnl (_LANG("ERROR: udp recv data conflict"));
           return (0);
         }
         /* find an unused buffer
          */
         for (i = 0; i < r->recv_bufnum; i++, p++)
             switch (p->buf_sig)
             {
               case RECV_USED:
                    break;
               case RECV_UNUSED:  /* take this one */
                    p->buf_sig     = RECV_USED;
                    p->buf_hisport = udp->srcPort;
                    p->buf_seqnum  = seq_num++;
#if defined(USE_IPV6)
                    if (s->udp.is_ip6)
                       memcpy (&p->buf_hisip6, &((tcp_PseudoHeader6*)ph)->src,
                               sizeof(p->buf_hisip6));

                    else
#endif
                       p->buf_hisip = ph->src;
                    len = min (len, sizeof(p->buf_data));
                    if (len > 0)
                    {
                      memcpy (p->buf_data, data, len);
                      p->buf_len = (short) len;
                    }
                    else
                      p->buf_len = -1;  /* a 0-byte probe */
#if 0
                    SOCK_DEBUGF (("\nsock_recvdaemon(): buffer %d, "
                                  "seq-num %ld, len %d",
                                  i, seq_num-1, p->buf_len));
#endif
                    return (0);
               default:
                    outsnl (_LANG("ERROR: sock_recv_daemon data err"));
                    return (0);
             }
         return (0);

#if !defined(USE_UDP_ONLY)
    case TCP_PROTO:
         {
           _tcp_Socket *t = &s->tcp;

           r = (recv_data*) t->rx_data;

           if (r->recv_sig != RECV_USED)
           {
             outsnl (_LANG("ERROR: tcp recv data conflict"));
             return (0);
           }
           /* stick it on the end if you can
            */
           i = t->max_rx_data - t->rx_datalen;
           if (i > 1)
           {
             /* we can accept some of this */
             if (len > i)
                 len = i;
             if (len > 0)
                memcpy (r->recv_bufs + t->rx_datalen, data, len);
             t->rx_datalen += len;
             return (len);
           }
           return (0);   /* didn't take none */
         }
#endif
  }
  return (0);
}
示例#29
0
文件: get_ip.c 项目: basecq/q2dos
struct hostent * W32_CALL
getipnodebyaddr (const void *src, size_t len, int af, int *error)
{
  struct hostent *he1, *he2;
  const  BYTE *cp = (const BYTE*) src;

  SOCK_DEBUGF (("\ngetipnodebyaddr: "));

  if (!src)
  {
    *error = NO_RECOVERY;
    return (NULL);
  }

  switch (af)
  {
    case AF_INET:
         if (len < INADDRSZ)
         {
           *error = NO_RECOVERY;
           return (NULL);
         }
         break;
#if defined(USE_IPV6)
    case AF_INET6:
         if (len < IN6ADDRSZ)
         {
           *error = NO_RECOVERY;
           return (NULL);
         }
         break;
#endif
    default:
         *error = NO_RECOVERY;
         return (NULL);
  }

  /* Look up IPv4 and IPv4 mapped/compatible addresses.
   */
  if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) ||
      (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) ||
      (af == AF_INET))
  {
    if (af == AF_INET6)
       cp += 12;

    SOCK_ENTER_SCOPE();
    he1 = gethostbyaddr ((const char*)cp, 4, AF_INET);
    SOCK_LEAVE_SCOPE();

    if (af == AF_INET)
       goto ret_copy;

    /* Convert from AF_INET to AF_INET6.
     */
    he2 = copyandmerge (he1, NULL, af, error);
    if (he2)
    {
      memcpy (he2->h_addr, src, len);  /* Restore original address */
      SOCK_DEBUGF (("%s", af == AF_INET ?
                    inet_ntoa(*(struct in_addr*)&he2->h_addr) :
                    _inet6_ntoa(he2->h_addr)));
    }
    return (he2);
  }

  he1 = gethostbyaddr (src, len, AF_INET6);   /* Lookup IPv6 address */

ret_copy:
  if (!he1)
  {
    *error = HOST_NOT_FOUND;
    return (NULL);
  }
  return copyandmerge (he1, NULL, af, error);
}