Esempio n. 1
0
int res_send (const u_char *buf, int buflen, u_char *ans, int anssiz)
{
  hp   = (HEADER *) buf;
  anhp = (HEADER *) ans;

  ns_buf    = (u_char*)buf;
  ns_ans    = ans;
  ns_buflen = buflen;
  ns_anssiz = anssiz;

  if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  {
    /* errno should have been set by res_init() in this case
     */
    return (-1);
  }
  DprintQ ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
           (";; res_send()\n"), buf, buflen);

  v_circuit    = (_res.options & RES_USEVC) || buflen > PACKETSZ;
  gotsomewhere = 0;
  connreset    = 0;
  terrno       = ETIMEDOUT;
  badns        = 0;

  /* Send request, RETRY times, or until successful
   */
  for (Try = 0; Try < _res.retry; Try++)
  {
    for (ns = 0; ns < _res.nscount; ns++)
    {
      struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
      int    rc;

      do
        rc = name_server_send (ns, nsap);
      while (rc == SAME_NS);

      if (rc != NEXT_NS)
         return (rc);
    }
  }

  resolve_close();
  if (!v_circuit)
  {
    if (!gotsomewhere)
         SOCK_ERRNO (ECONNREFUSED); /* no nameservers found */
    else SOCK_ERRNO (ETIMEDOUT);    /* no answer obtained */
  }
  else
    SOCK_ERRNO (terrno);
  return (-1);
}
Esempio n. 2
0
static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t len,
                                /* for UDP sendto: */
                                rktio_addrinfo_t *addr)
{
  rktio_socket_t s = rktio_fd_socket(rktio, rfd);
  intptr_t sent;
  int errid = 0;

#ifdef RKTIO_SYSTEM_WINDOWS
# define SEND_BAD_MSG_SIZE(e) (e == WSAEMSGSIZE)
#else    
# ifdef SEND_IS_NEVER_TOO_BIG
#  define SEND_BAD_MSG_SIZE(errid) 0
# else
#  define SEND_BAD_MSG_SIZE(errid) (errid == EMSGSIZE)
# endif
#endif

  while (1) {
    if (addr) {
      /* Use first address that dosn't result in a bad-address error: */
      for (; addr; addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next) {
        do {
          sent = sendto(s, buffer, len, 0,
                        RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen);
        } while ((sent == -1) && NOT_WINSOCK(errno == EINTR));
        if (sent >= 0)
          break;
        errid = SOCK_ERRNO();
        if (!WAS_EBADADDRESS(errid))
          break;
      }
    } else {
      do {
        sent = send(s, buffer, len, 0);
      } while ((sent == -1) && NOT_WINSOCK(errno == EINTR));

      if (sent == -1)
        errid = SOCK_ERRNO();
    }
    
    if (sent >= 0)
      return sent;
    
    if (WAS_EAGAIN(errid))
      return 0;
    else if (SEND_BAD_MSG_SIZE(errid) && (len > 1)) {
      /* split the message and try again: */
      len >>= 1;
    } else {
Esempio n. 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);
}
Esempio n. 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);
}
Esempio n. 5
0
/*
 * BSD-style: \n
 * Make a FQDN from `hostname' & `def_domain'.
 * Set errno on failure and return -1.
 */
int W32_CALL gethostname (char *buffer, int buflen)
{
  /* the FQDN when no hostname has been set is "localhost.localdomain".
   * the FQDN when a hostname has been set, but no domname is set, is 'my_hostname'
   * the FQDN when both are set is 'my_hostname.my_domname'
   */
  const char *my_hostname = "localhost";
  const char *my_domname  = "localdomain";
  int   pos;

  if (!buffer || buflen < 0)
  {
    SOCK_ERRNO (EINVAL);
    return (-1);
  }
  if (buflen == 0)
     return (0);

#if (DOSX)
  if (!valid_addr((DWORD)buffer, buflen))
  {
    SOCK_ERRNO (EFAULT);
    return (-1);
  }
#endif

  if (*hostname) /* otherwise use localhost.localdomain */
  {
    my_hostname = hostname;
    my_domname  = NULL;         /* have hostname but no domain name */
    if (def_domain && *def_domain)
       my_domname = def_domain;
  }
  pos = 0;
  while (pos < buflen && *my_hostname)
      buffer[pos++] = *my_hostname++;

  if (pos < buflen && my_domname)
  {
    buffer[pos++] = '.';
    /*@-nullderef@*/
    while (pos < buflen && *my_domname)
        buffer[pos++] = *my_domname++;
  }
  if (pos < buflen)
     buffer[pos] = '\0';
  return (0);
}
Esempio n. 6
0
// millisecs
std::error_code
PollPoller::poll(int timeout,
                   std::unordered_map<int, Dispatcher *> &active_dispatchers) {

  if (fds_.size() == 0) {
    ::Sleep(timeout);
    return LS_OK_ERROR();
  }
  int num_events = ::WSAPoll(&*fds_.begin(), fds_.size(), timeout);

  if (num_events < 0) {
    if (SOCK_ERRNO() == CERR(EINTR)) {
      return LS_OK_ERROR();
    }
  } else if (num_events == 0) {
    return LS_OK_ERROR();
  } else {
    for (auto it = fds_.begin(); it != fds_.end() && num_events > 0; ++it) {
      if (it->revents > 0) {
        --num_events;
        Dispatcher *dispatcher = dispatchers_[it->fd];
        dispatcher->set_poll_event_data(
            it->revents & (POLLIN | POLLPRI), it->revents & POLLOUT,
            it->revents & POLLERR,
            (it->revents & POLLHUP) && !(it->revents & POLLIN));
        active_dispatchers[dispatcher->get_fd()] = dispatcher;
      }
    }
  }
  return LS_OK_ERROR();
}
Esempio n. 7
0
/**
 * BSD-style: \n
 * Expects a "Fully Qualified Domain Name" in `fqdn'.
 * Split at first `.' and extract `hostname' and `def_domain'.
 * Set errno on failure and return -1.
 */
int W32_CALL sethostname (const char *fqdn, int len)
{
  int pos;

  if (!fqdn || !*fqdn || len < 0 || len > MAX_HOSTLEN)
  {
    SOCK_ERRNO (EINVAL);
    return (-1);
  }

#if (DOSX)
  if (!valid_addr((DWORD)fqdn, len))
  {
    SOCK_ERRNO (EFAULT);
    return (-1);
  }
#endif

  pos = 0;
  while (pos < len && fqdn[pos] != '.')
  {
    if (!fqdn[pos]) /* should do complete alpha/digit/underscore check here */
    {
      pos = 0;
      break;
    }
    pos++;
  }
  if (pos == 0) /* leading '.' or invalid char in name */
  {
    SOCK_ERRNO (EINVAL);
    return (-1);
  }
  if (pos >= SIZEOF(hostname))
  {
    SOCK_ERRNO (ERANGE);
    return (-1);
  }
  if (fqdn[pos] == '.') /* a trailing '.' is ok too */
  {
    if (setdomainname(&fqdn[pos+1], len-pos) != 0)
       return (-1);
  }
  memcpy (&hostname[0], fqdn, pos);
  hostname[pos] = '\0';
  return (0);
}
Esempio n. 8
0
static void do_get_socket_error(rktio_t *rktio) {
  rktio->errid = SOCK_ERRNO();
#ifdef RKTIO_SYSTEM_WINDOWS
  rktio->errkind = RKTIO_ERROR_KIND_WINDOWS;
#else
  rktio->errkind = RKTIO_ERROR_KIND_POSIX;
#endif
}
Esempio n. 9
0
/*
 * Raise SIGPIPE/SIGURG if signal defined (not needed yet).
 * Return -1 with errno = EPIPE.
 */
int _sock_sig_epipe (void)
{
#if defined(SIGPIPE)
  raise (SIGPIPE);
#endif
  SOCK_ERRNO (EPIPE);
  return (-1);
}
Esempio n. 10
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);
}
Esempio n. 11
0
/*
 * Check for catched signals
 */
static int chk_signals (void)
{
  if (_sock_sig_pending())
  {
    SOCK_DEBUGF ((", EINTR"));
    SOCK_ERRNO (EINTR);
    return (-1);
  }
  return (0);
}
Esempio n. 12
0
/**
 * BSD-style: \n
 * Set the host's domain name.
 * Set errno on failure and return -1.
 */
int W32_CALL setdomainname (const char *name, int len)
{
  if (!name || len < 0 || len > SIZEOF(defaultdomain)-1)
  {
    SOCK_ERRNO (EINVAL);
    return (-1);
  }

#if (DOSX)
  if (!valid_addr((DWORD)name, len))
  {
    SOCK_ERRNO (EFAULT);
    return (-1);
  }
#endif

  def_domain = StrLcpy (defaultdomain, name, len);
  return (0);
}
Esempio n. 13
0
/**
 * BSD-style: \n
 * Return domain name of this host.
 * As per BSD spec, the resultant buffer ...
 * ... "will be null-terminated _unless_there_is_insufficient_space_";
 *
 * Set errno on failure and return -1.
 */
int W32_CALL getdomainname (char *buffer, int buflen)
{
  const char *my_domainname = def_domain ? def_domain : "";

  if (!buffer || buflen < 0 || buflen < (int)strlen(my_domainname))
  {
    SOCK_ERRNO (EINVAL);
    return (-1);
  }
#if (DOSX)
  if (!valid_addr((DWORD)buffer, buflen))
  {
    SOCK_ERRNO (EFAULT);
    return (-1);
  }
#endif

  strncpy (buffer, my_domainname, buflen);
  /* no terminating '\0' needs to be forced here per bsd spec */
  return (0);
}
Esempio n. 14
0
struct hostent * W32_CALL gethostbyname_r (const char *name,
                                           struct hostent *result,
                                           char *buffer, int buf_len,
                                           int *p_errno)
{
  UNFINISHED();
  *p_errno = ERANGE;
  SOCK_ERRNO (ERANGE);
  ARGSUSED (name);
  ARGSUSED (result);
  ARGSUSED (buffer);
  ARGSUSED (buf_len);
  return (NULL);
}
Esempio n. 15
0
int W32_CALL shutdown (int s, int how)
{
  Socket *socket = _socklist_find (s);

#if defined(USE_DEBUG)
  static char fmt[] = "\nshutdown:%d/??";
  static char rrw[] = "r w rw";

  how &= 3;
  fmt [sizeof(fmt)-3] = rrw [2*how];
  fmt [sizeof(fmt)-2] = rrw [2*how+1];
#endif

  SOCK_PROLOGUE (socket, fmt, s);

  switch (how)
  {
    case SHUT_RD:
         socket->so_error    = ESHUTDOWN;
         socket->so_state   |=  SS_CANTRCVMORE;
      /* socket->so_options &= ~SO_ACCEPTCONN; */

         /** \todo For tcp, should send RST if we get
          *        incoming data. Don't send ICMP error.
          */
         return (0);

    case SHUT_WR:
         socket->so_error    = ESHUTDOWN;
         socket->so_state   |=  SS_CANTSENDMORE;
         socket->so_state   &= ~SS_ISLISTENING;
      /* socket->so_options &= ~SO_ACCEPTCONN; */

         /** \todo For tcp, should send FIN when all Tx data
          *        has been ack'ed.
          * close_s(s) should be same as shutdown(s,SHUT_WR)
          */
         return (0);

    case SHUT_RDWR:
         socket->so_error    = ESHUTDOWN;
         socket->so_state   |= (SS_CANTRCVMORE | SS_CANTSENDMORE);
         socket->so_state   &= ~SS_ISLISTENING;
      /* socket->so_options &= ~SO_ACCEPTCONN; */
         return (0);
  }

  SOCK_ERRNO (EINVAL);
  return (-1);
}
Esempio n. 16
0
std::error_code check_socket_error(int fd) {
#ifdef WIN32
  char err = 0;
#else
  int err = 0;
#endif
  socklen_t len = sizeof(err);
  int i = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
  if (i == -1) {
    return LS_GENERIC_ERROR(SOCK_ERRNO());
  } else if (err != 0) {
    return LS_GENERIC_ERROR(err);
  }
  return LS_OK_ERROR();
}
Esempio n. 17
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);
}
Esempio n. 18
0
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
{
  rktio_socket_t s = rktio_fd_socket(rktio, rfd);
  int rn;
  
  do {
    rn = recv(s, buffer, len, 0);
  } while ((rn == -1) && NOT_WINSOCK(errno == EINTR));

  if (rn > 0)
    return rn;
  else if (rn == 0)
    return RKTIO_READ_EOF;
  else {
    int err = SOCK_ERRNO();
    if (WAS_EAGAIN(err))
      return 0;
    else {
      get_socket_error();
      return RKTIO_READ_ERROR;
    }
  }
}
Esempio n. 19
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);
}
Esempio n. 20
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);
}
Esempio n. 21
0
/* WARNING: all parameters MUST be valid,
 *          NULL pointers lead to a crash.
 */
ret_t
cherokee_socket_writev (cherokee_socket_t  *socket,
                        const struct iovec *vector,
                        uint16_t            vector_len,
                        size_t             *pcnt_written)
{
	int    re;
	int    i;
	ret_t  ret;
	size_t cnt;

	*pcnt_written = 0;

	/* There must be something to send, otherwise behaviour is undefined
	 * and as we don't want this case, we have to enforce assertions.
	 */
	return_if_fail (vector != NULL && vector_len > 0, ret_error);

	if (likely (socket->is_tls != TLS))
	{
#ifdef _WIN32
		int i;
		size_t total;

		for (i = 0, re = 0, total = 0; i < vector_len; i++) {
			if (vector[i].iov_len == 0)
				continue;
			do {
				re = send (SOCKET_FD(socket), vector[i].iov_base, vector[i].iov_len, 0);
			} while ((re == -1) && (errno == EINTR));

			if (re < 0)
				break;

			total += re;

			/* if it is a partial send, then stop sending data
			 */
			if (re != vector[i].iov_len)
				break;
		}
		*pcnt_written = total;

		/* if we have sent at least one byte,
		 * then return OK.
		 */
		if (likely (total > 0))
			return ret_ok;

		if (re == 0) {
			int err = SOCK_ERRNO();
			if (i == vector_len)
				return ret_ok;
			/* Retry later.
			 */
			return ret_eagain;
		}

#else /* ! WIN32 */

		do {
			re = writev (SOCKET_FD(socket), vector, vector_len);
		} while ((re == -1) && (errno == EINTR));

		if (likely (re > 0)) {
			*pcnt_written = (size_t) re;
			return ret_ok;
		}
		if (re == 0) {
			int i;
			/* Find out whether there was something to send or not.
			 */
			for (i = 0; i < vector_len; i++) {
				if (vector[i].iov_base != NULL && vector[i].iov_len > 0)
					break;
			}
			if (i < vector_len)
				return ret_eagain;
			/* No, nothing to send, so return ok.
			 */
			return ret_ok;
		}
#endif
		if (re < 0) {
			int err = SOCK_ERRNO();

			switch (err) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
			case EWOULDBLOCK:
#endif
			case EAGAIN:
				return ret_eagain;

			case EPIPE:
#ifdef ENOTCONN
			case ENOTCONN:
#endif
			case ECONNRESET:
				socket->status = socket_closed;
			case ETIMEDOUT:
			case EHOSTUNREACH:
				return ret_error;
			}

			LOG_ERRNO (errno, cherokee_err_error,
				   CHEROKEE_ERROR_SOCKET_WRITEV, SOCKET_FD(socket));
		}
		return ret_error;

	}

	/* TLS connection: Here we don't worry about sparing a few CPU
	 * cycles, so we reuse the single send case for TLS.
	 */
	for (i = 0; i < vector_len; i++) {
		if ((vector[i].iov_len == 0) ||
		    (vector[i].iov_base == NULL))
			continue;

		cnt = 0;
		ret = cherokee_socket_write (socket, vector[i].iov_base, vector[i].iov_len, &cnt);
		if (ret != ret_ok) {
			return ret;
		}

		*pcnt_written += cnt;
		if (cnt == vector[i].iov_len)
			continue;

		/* Unfinished */
		return ret_ok;
	}

	/* Did send everything */
	return ret_ok;
}
Esempio n. 22
0
/**
 * _eth_send() does the actual transmission once we are complete with
 * filling the buffer.  Do any last minute patches here, like fix the
 * size. Send to "loopback" device if it's IP and destination matches
 * loopback network (127.x.x.x.).
 *
 * Return length of network-layer packet (not length of link-layer
 * packet).
 */
int _eth_send (WORD len, const void *sock, const char *file, unsigned line)
{
#if defined(USE_DEBUG) || defined(USE_LOOPBACK)
  unsigned errline = 0;
#endif
  BOOL send_loopback_to_driver = FALSE;

  SIO_TRACE (("_eth_send, len %d", len));

  if (!_eth_is_init)  /* GvB 2002-09, Lets us run without a working eth */
  {
    SOCK_ERRNO (ENETDOWN);
    return (0);
  }

#if defined(WIN32)
  /*
   * Just a test for now; send it to the driver and look what happens....
   * They go on the wire and not to the Winsock loopback provider.
   * No surprise here yet.
   */
  if (loopback_mode & LBACK_MODE_WINSOCK)
     send_loopback_to_driver = TRUE;
#endif

  if (proto == IP4_TYPE)
  {
    /* Sending to loopback device if IPv4.
     */
    const in_Header *ip = (const in_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        _ip4_is_loopback_addr(intel(ip->destination)))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), FALSE, &errline);
#else
      STAT (ip4stats.ips_odropped++);    /* packet dropped (null-device) */
#endif
      goto debug_tx;
    }
  }

#if defined(USE_IPV6)
  else if (proto == IP6_TYPE)
  {
    const in6_Header *ip = (const in6_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        IN6_IS_ADDR_LOOPBACK(&ip->destination))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), TRUE, &errline);
#else
      STAT (ip6stats.ip6s_odropped++);
#endif
      goto debug_tx;
    }
  }
#endif  /* USE_IPV6 */

#if defined(USE_PPPOE)
  else if (proto == PPPOE_SESS_TYPE)
  {
    pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data;

    pppoe->length = intel16 (len+2);
    len += PPPOE_HDR_SIZE + 2;      /* add 2 for protocol */
  }
#endif

  /* Store the last Tx CPU timestamp (for debugging).
   */
#if (DOSX) && !(DOSX & WINWATT)
  if (_dbugxmit && has_rdtsc)
     get_rdtsc2 (&_eth_last.tx.tstamp);
#endif

  /* Do the MAC-dependant transmit. `len' on return is total length
   * of link-layer packet sent. `len' is 0 on failure. The xmit-hook
   * is used by e.g. libpcap/libnet.
   */
  if (_eth_xmit_hook)
       len = (*_eth_xmit_hook) (TX_BUF(), len + _pkt_ip_ofs);
  else len = (*mac_transmit) (TX_BUF(), len + _pkt_ip_ofs);

  if (len > _pkt_ip_ofs)
  {
    _eth_last.tx.size = len;
    len -= _pkt_ip_ofs;
  }
  else
  {
    if (debug_on)
       outs ("Tx failed. ");
    len = 0;
    _eth_last.tx.size = 0;
  }

debug_tx:

#if defined(NEED_PKT_SPLIT)
  pkt_split_mac_out (TX_BUF());
#endif

#if defined(USE_STATISTICS)
  if (len > 0)
     update_out_stat();
#endif

#if defined(USE_DEBUG)
  if (_dbugxmit)
    (*_dbugxmit) (sock, (const in_Header*)nw_pkt, file, line);

  if (len == 0)
  {
    if (errline && !send_loopback_to_driver)
       dbug_printf ("** Error in loopback handler, line %u\n", errline);
    else
    {
      const char err[] = "** Transmit fault **\n";
      TCP_CONSOLE_MSG (0, ("%s", err));
      dbug_printf (err);
    }
  }
#else
  ARGSUSED (sock);
  ARGSUSED (file);
  ARGSUSED (line);
#endif

  /* Undo hack done in pppoe_mac_format()
   */
  if (proto == PPPOE_SESS_TYPE || _pktdevclass == PDCLASS_ETHER)
     _pkt_ip_ofs = sizeof(eth_Header);
  return (len);
}
Esempio n. 23
0
/* WARNING: all parameters MUST be valid,
 *          NULL pointers lead to a crash.
 */
ret_t
cherokee_socket_read (cherokee_socket_t *socket,
                      char              *buf,
                      int                buf_size,
                      size_t            *pcnt_read)
{
	ret_t   ret;
	int     err;
	ssize_t len;

	*pcnt_read = 0;

	/* There must be something to read, otherwise behaviour is undefined
	 * and as we don't want this case, we have to enforce assertions.
	 */
	return_if_fail (buf != NULL && buf_size > 0, ret_error);

	if (unlikely (socket->status == socket_closed)) {
		TRACE(ENTRIES, "Reading a closed socket: fd=%d (TLS=%d)\n", SOCKET_FD(socket), (socket->is_tls == TLS));
		return ret_eof;
	}

	if (likely (socket->is_tls != TLS)) {
		/* Plain read
		 */
		do {
			len = recv (SOCKET_FD(socket), buf, buf_size, 0);
		} while ((len < 0) && (errno == EINTR));

		if (likely (len > 0)) {
			*pcnt_read = len;
			return ret_ok;
		}

		if (len == 0) {
			socket->status = socket_closed;
			return ret_eof;
		}

		/* Error handling
		 */
		err = SOCK_ERRNO();

		TRACE(ENTRIES",read", "Socket read error fd=%d: '%s'\n",
		      SOCKET_FD(socket), strerror(errno));

		switch (err) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
		case EAGAIN:
			return ret_eagain;

		case EPIPE:
#ifdef ENOTCONN
		case ENOTCONN:
#endif
		case ECONNRESET:
			socket->status = socket_closed;
		case ETIMEDOUT:
		case EHOSTUNREACH:
			return ret_error;
		}

		LOG_ERRNO (errno, cherokee_err_error,
			   CHEROKEE_ERROR_SOCKET_READ, SOCKET_FD(socket));
		return ret_error;

	} else if (socket->cryptor != NULL) {
		ret = cherokee_cryptor_socket_read (socket->cryptor,
		                                    buf, buf_size, pcnt_read);
		switch (ret) {
		case ret_ok:
		case ret_error:
		case ret_eagain:
			return ret;
		case ret_eof:
			socket->status = socket_closed;
			return ret_eof;
		default:
			RET_UNKNOWN(ret);
			return ret;
		}
	}

	return ret_error;
}
Esempio n. 24
0
/* WARNING: all parameters MUST be valid,
 *          NULL pointers lead to a crash.
 */
ret_t
cherokee_socket_write (cherokee_socket_t *socket,
                       const char        *buf,
                       int                buf_len,
                       size_t            *pcnt_written)
{
	ret_t   ret;
	int     err;
	ssize_t len;

	*pcnt_written = 0;

	/* There must be something to send, otherwise behaviour is undefined
	 * and as we don't want this case, we have to enforce assertions.
	 */
	return_if_fail (buf != NULL && buf_len > 0, ret_error);

	if (likely (socket->is_tls != TLS)) {
		do {
			len = send (SOCKET_FD(socket), buf, buf_len, 0);
		} while ((len < 0) && (errno == EINTR));

		if (likely (len > 0) ) {
			/* Return n. of bytes sent.
			 */
			*pcnt_written = len;
			return ret_ok;
		}

		if (len == 0) {
			/* Very strange, socket is ready but nothing
			 * has been written, retry later.
			 */
			return ret_eagain;
		}

		/* Error handling
		 */
		err = SOCK_ERRNO();

		switch (err) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
		case EAGAIN:
			return ret_eagain;

		case EPIPE:
		case ECONNRESET:
#ifdef ENOTCONN
		case ENOTCONN:
#endif
			socket->status = socket_closed;
		case ETIMEDOUT:
		case EHOSTUNREACH:
			return ret_error;
		}

		LOG_ERRNO (errno, cherokee_err_error,
			   CHEROKEE_ERROR_SOCKET_WRITE, SOCKET_FD(socket));

		return ret_error;

	} else if (socket->cryptor != NULL) {
		ret = cherokee_cryptor_socket_write (socket->cryptor,
		                                     (char *)buf, buf_len, pcnt_written);
		switch (ret) {
		case ret_ok:
		case ret_error:
		case ret_eagain:
			return ret;
		case ret_eof:
			socket->status = socket_closed;
			return ret_eof;
		default:
			RET_UNKNOWN(ret);
			return ret;
		}
	}

	return ret_error;
}
Esempio n. 25
0
ret_t
cherokee_socket_connect (cherokee_socket_t *sock)
{
	int r;
	int err;

	TRACE (ENTRIES",connect", "connect type=%s\n",
	       SOCKET_AF(sock) == AF_INET  ? "AF_INET"  :
	       SOCKET_AF(sock) == AF_INET6 ? "AF_INET6" :
	       SOCKET_AF(sock) == AF_UNIX  ? "AF_UNIX"  : "Unknown");

	do {
		switch (SOCKET_AF(sock)) {
		case AF_INET:
			r = connect (SOCKET_FD(sock),
			             (struct sockaddr *) &SOCKET_ADDR(sock),
			             sizeof(struct sockaddr_in));
			break;
#ifdef HAVE_IPV6
		case AF_INET6:
			r = connect (SOCKET_FD(sock),
			             (struct sockaddr *) &SOCKET_ADDR(sock),
			             sizeof(struct sockaddr_in6));
			break;
#endif
#ifdef HAVE_SOCKADDR_UN
		case AF_UNIX:
			if (SOCKET_SUN_PATH (socket)[0] != 0) {
				r = connect (SOCKET_FD(sock),
				             (struct sockaddr *) &SOCKET_ADDR(sock),
				             SUN_LEN (SOCKET_ADDR_UNIX(sock)));
			}
			else {
				r = connect (SOCKET_FD(sock),
				             (struct sockaddr *) &SOCKET_ADDR(sock),
				             SUN_ABSTRACT_LEN (SOCKET_ADDR_UNIX(sock)));
			}
			break;
#endif
		default:
			SHOULDNT_HAPPEN;
			return ret_no_sys;
		}
	} while ((r == -1) && (errno == EINTR));

	if (r < 0) {
		err = SOCK_ERRNO();
		TRACE (ENTRIES",connect", "connect error=%d '%s'\n", err, strerror(err));

		switch (err) {
		case EISCONN:
			break;
		case EINVAL:
		case ENOENT:
		case ECONNRESET:
		case ECONNREFUSED:
		case EADDRNOTAVAIL:
			return ret_deny;
		case ETIMEDOUT:
			return ret_error;
		case EAGAIN:
		case EALREADY:
		case EINPROGRESS:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			return ret_eagain;
		default:
			LOG_ERRNO_S (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_CONNECT);
			return ret_error;
		}
	}

	TRACE (ENTRIES",connect", "succeed. fd=%d\n", SOCKET_FD(sock));

	sock->status = socket_reading;
	return ret_ok;
}
Esempio n. 26
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);
}
Esempio n. 27
0
/**
 * Try asking a LAN extension of DOS for a host-name.
 */
int _get_machine_name (char *buf, int size)
{
  IREGS reg;
  char *h;
  char  dosBuf[16];
  int   len;

  memset (&reg, 0, sizeof(reg));
  reg.r_ax = 0x5E00;

#if (DOSX & DJGPP)
  if (_go32_info_block.size_of_transfer_buffer < sizeof(dosBuf))
     return (-1);
  reg.r_ds = __tb / 16;
  reg.r_dx = __tb & 15;

#elif (DOSX & (PHARLAP|X32VM|POWERPAK))
  if (_watt_dosTbSize < sizeof(dosBuf) || !_watt_dosTbr)
     return (-1);
  reg.r_ds = RP_SEG (_watt_dosTbr);
  reg.r_dx = RP_OFF (_watt_dosTbr);

#elif (DOSX & DOS4GW)
  if (_watt_dosTbSize < sizeof(dosBuf) || !_watt_dosTbSeg)
     return (-1);
  reg.r_ds = _watt_dosTbSeg;
  reg.r_dx = 0;

#elif (DOSX == 0)
  reg.r_ds = FP_SEG (dosBuf);
  reg.r_dx = FP_OFF (dosBuf);

#else
  #error Help me!
#endif

  GEN_INTERRUPT (0x21, &reg);
  if ((reg.r_flags & CARRY_BIT) || hiBYTE(reg.r_cx) == 0)
     return (-1);

#if (DOSX & DJGPP)
  dosmemget (__tb, sizeof(dosBuf), dosBuf);

#elif (DOSX & (PHARLAP|X32VM|POWERPAK))
  ReadRealMem ((void*)&dosBuf, _watt_dosTbr, sizeof(dosBuf));

#elif (DOSX & DOS4GW)
  memcpy (dosBuf, SEG_OFS_TO_LIN(_watt_dosTbSeg,0), sizeof(dosBuf));
#endif

  /* Remove right space padding
   */
  h = dosBuf + min (strlen(dosBuf), sizeof(dosBuf)-1);
  while (h > dosBuf && h[-1] == ' ')
        h--;

  *h  = '\0';
  h   = dosBuf;
  len = strlen (h);
  if (len + 1 > size)
  {
    SOCK_ERRNO (ERANGE);
    return (-1);
  }
  strcpy (buf, h);
  strlwr (buf);
  return (0);
}