Пример #1
0
/**
  Signal the receive token with the specific error or
  set socket error code after error is received.

  @param  Sock                  Pointer to the socket.
  @param  Error                 The error code received.

**/
VOID
SockRcvdErr (
  IN OUT SOCKET       *Sock,
  IN     EFI_STATUS   Error
  )
{
  SOCK_TOKEN  *SockToken;

  if (!IsListEmpty (&Sock->RcvTokenList)) {

    SockToken = NET_LIST_HEAD (
                  &Sock->RcvTokenList,
                  SOCK_TOKEN,
                  TokenList
                  );

    RemoveEntryList (&SockToken->TokenList);

    SIGNAL_TOKEN (SockToken->Token, Error);

    FreePool (SockToken);
  } else {

    SOCK_ERROR (Sock, Error);
  }
}
Пример #2
0
int sockinetaddr::gethostname (char *hostname, size_t hostnameLen) const
{
  hostname[0] = '\0';

  if (sin_addr.s_addr == htonl(INADDR_ANY)) {
    if (::gethostname(hostname, hostnameLen) == -1) {
      SOCK_ERROR("sockinetaddr", "gethostname");
      hostname[0] = '\0';
      return -1;
    }
    return 0;
  }

  int hostErrno;
  struct hostent hostResult;
  char hostBuffer[4096];
  hostent* hp;
  if ((my_gethostbyaddr_r((const char*) &sin_addr, sizeof(sin_addr),
			  family(), &hostResult, hostBuffer, 2048, &hp,
			  &hostErrno) != 0) ||
      (hp == 0))
  {
    sockinetaddr::herror("gethostbyaddr");
    return -1;
  }
  if ((hp->h_name) && (strlen(hp->h_name) < hostnameLen)) {
    strcpy (hostname, hp->h_name);
    return 0;
  }
  return -1;
}
Пример #3
0
sockinetaddr sockinetbuf::peeraddr() const
{
  sockinetaddr sin (GetModuleName(), GetLog(), GetDiagBase());
  socklen_t len = sin.size();
  if (::getpeername(rep->sock, sin.addr (), &len) == -1)
    SOCK_ERROR("sockinetbuf", "getpeername");
  return sin;
}
Пример #4
0
int sockinetaddr::setport(const char* sn, const char* pn)
{
  servent* sp = getservbyname(sn, pn);
  if (sp == 0)
  {
    SOCK_ERROR("sockinetaddr", "invalid service name");
    return -1;
  }
  sin_port = sp->s_port;
  return 0;
}
Пример #5
0
/* Use the native UNIX call */
void sockinetaddr::herror(const char* em) const
{
#ifdef _decunix_
  if (errno)
    Error(500, L"%s%S%s%d%s%S%s%d", L"class", em, L"h_errno", h_errno,
	  L"errnoStr", strerror(errno), L"errno", errno);
  else
    Error(500, L"%s%S%s%d", L"class", em, L"h_errno", h_errno);
#else
  SOCK_ERROR(em, hstrerror(h_errno));
#endif
}
Пример #6
0
/**
  Called by the low layer protocol to indicate that there will be no more data
  from the communication peer.

  This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
  IO tokens with the error status EFI_CONNECTION_FIN.

  @param[in, out]  Sock                  Pointer to the socket.

**/
VOID
SockNoMoreData (
  IN OUT SOCKET *Sock
  )
{
  EFI_STATUS  Err;

  SOCK_NO_MORE_DATA (Sock);

  if (!IsListEmpty (&Sock->RcvTokenList)) {

    ASSERT (0 == GET_RCV_DATASIZE (Sock));

    Err = Sock->SockError;

    SOCK_ERROR (Sock, EFI_CONNECTION_FIN);

    SockFlushPendingToken (Sock, &Sock->RcvTokenList);

    SOCK_ERROR (Sock, Err);

  }
}
Пример #7
0
/**
  Timeout handler for TCP retransmission timer.

  @param  Tcb      Pointer to the TCP_CB of this TCP instance.

**/
VOID
TcpRexmitTimeout (
  IN OUT TCP_CB *Tcb
  )
{
  UINT32  FlightSize;

  DEBUG ((EFI_D_WARN, "TcpRexmitTimeout: transmission "
    "timeout for TCB %p\n", Tcb));

  //
  // Set the congestion window. FlightSize is the
  // amount of data that has been sent but not
  // yet ACKed.
  //
  FlightSize        = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
  Tcb->Ssthresh     = MAX ((UINT32) (2 * Tcb->SndMss), FlightSize / 2);

  Tcb->CWnd         = Tcb->SndMss;
  Tcb->LossRecover  = Tcb->SndNxt;

  Tcb->LossTimes++;
  if ((Tcb->LossTimes > Tcb->MaxRexmit) &&
      !TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {

    DEBUG ((EFI_D_ERROR, "TcpRexmitTimeout: connection closed "
      "because too many timeouts for TCB %p\n", Tcb));

    if (EFI_ABORTED == Tcb->Sk->SockError) {
      SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
    }

    TcpClose (Tcb);
    return ;
  }

  TcpBackoffRto (Tcb);
  TcpRetransmit (Tcb, Tcb->SndUna);
  TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);

  Tcb->CongestState = TCP_CONGEST_LOSS;
  TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
}
Пример #8
0
/**
  Timeout handler for keepalive timer.

  @param  Tcb      Pointer to the TCP_CB of this TCP instance.

**/
VOID
TcpKeepaliveTimeout (
  IN OUT TCP_CB *Tcb
  )
{
  Tcb->KeepAliveProbes++;

  //
  // Too many Keep-alive probes, drop the connection
  //
  if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {

    if (EFI_ABORTED == Tcb->Sk->SockError) {
      SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
    }

    TcpClose (Tcb);
    return ;
  }

  TcpSendZeroProbe (Tcb);
  TcpSetKeepaliveTimer (Tcb);
}
Пример #9
0
/* Winsock.h maps h_errno to WSAGetLastError() function call */
void sockinetaddr::herror(const char* em) const
{
  int err;
  switch(h_errno) { /* calls WSAGetLastError() */
   case HOST_NOT_FOUND:
     err = 1;
     break;
   case TRY_AGAIN:
     err = 2;
     break;
   case NO_RECOVERY:
     err = 3;
     break;
   case NO_ADDRESS:
     err = 4;
     break;
   default:
     err = 5;
     break;
  }

  SOCK_ERROR(em, errmsg[err]);
}
Пример #10
0
/**
  Connect timeout handler.

  @param  Tcb      Pointer to the TCP_CB of this TCP instance.

**/
VOID
TcpConnectTimeout (
  IN OUT TCP_CB *Tcb
  )
{
  if (!TCP_CONNECTED (Tcb->State)) {
    DEBUG ((EFI_D_ERROR, "TcpConnectTimeout: connection closed "
      "because conenction timer timeout for TCB %p\n", Tcb));

    if (EFI_ABORTED == Tcb->Sk->SockError) {
      SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
    }

    if (TCP_SYN_RCVD == Tcb->State) {
      DEBUG ((EFI_D_WARN, "TcpConnectTimeout: send reset because "
        "connection timer timeout for TCB %p\n", Tcb));

      TcpResetConnection (Tcb);

    }

    TcpClose (Tcb);
  }
}
Пример #11
0
static int powerdns_get_data_stream(list_item_t *item, /* {{{ */
                                    char **ret_buffer,
                                    size_t *ret_buffer_size) {
  int sd;
  int status;

  char temp[4096];
  char *buffer = NULL;
  size_t buffer_size = 0;

  sd = socket(PF_UNIX, item->socktype, 0);
  if (sd < 0) {
    FUNC_ERROR("socket");
    return (-1);
  }

  struct timeval timeout;
  timeout.tv_sec = 5;
  timeout.tv_usec = 0;
  status = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  if (status != 0) {
    FUNC_ERROR("setsockopt");
    close(sd);
    return (-1);
  }

  status =
      connect(sd, (struct sockaddr *)&item->sockaddr, sizeof(item->sockaddr));
  if (status != 0) {
    SOCK_ERROR("connect", item->sockaddr.sun_path);
    close(sd);
    return (-1);
  }

  /* strlen + 1, because we need to send the terminating NULL byte, too. */
  status = send(sd, item->command, strlen(item->command) + 1,
                /* flags = */ 0);
  if (status < 0) {
    SOCK_ERROR("send", item->sockaddr.sun_path);
    close(sd);
    return (-1);
  }

  while (42) {
    char *buffer_new;

    status = recv(sd, temp, sizeof(temp), /* flags = */ 0);
    if (status < 0) {
      SOCK_ERROR("recv", item->sockaddr.sun_path);
      break;
    } else if (status == 0)
      break;

    buffer_new = realloc(buffer, buffer_size + status + 1);
    if (buffer_new == NULL) {
      FUNC_ERROR("realloc");
      status = -1;
      break;
    }
    buffer = buffer_new;

    memcpy(buffer + buffer_size, temp, status);
    buffer_size += status;
    buffer[buffer_size] = 0;
  } /* while (42) */
  close(sd);

  if (status < 0) {
    sfree(buffer);
  } else {
    assert(status == 0);
    *ret_buffer = buffer;
    *ret_buffer_size = buffer_size;
  }

  return (status);
} /* }}} int powerdns_get_data_stream */
Пример #12
0
static int powerdns_get_data_dgram(list_item_t *item, /* {{{ */
                                   char **ret_buffer, size_t *ret_buffer_size) {
  int sd;
  int status;

  char temp[4096];
  char *buffer = NULL;
  size_t buffer_size = 0;

  struct sockaddr_un sa_unix = {0};

  cdtime_t cdt_timeout;

  sd = socket(PF_UNIX, item->socktype, 0);
  if (sd < 0) {
    FUNC_ERROR("socket");
    return (-1);
  }

  sa_unix.sun_family = AF_UNIX;
  sstrncpy(sa_unix.sun_path,
           (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
           sizeof(sa_unix.sun_path));

  status = unlink(sa_unix.sun_path);
  if ((status != 0) && (errno != ENOENT)) {
    SOCK_ERROR("unlink", sa_unix.sun_path);
    close(sd);
    return (-1);
  }

  do /* while (0) */
  {
    /* We need to bind to a specific path, because this is a datagram socket
     * and otherwise the daemon cannot answer. */
    status = bind(sd, (struct sockaddr *)&sa_unix, sizeof(sa_unix));
    if (status != 0) {
      SOCK_ERROR("bind", sa_unix.sun_path);
      break;
    }

    /* Make the socket writeable by the daemon.. */
    status = chmod(sa_unix.sun_path, 0666);
    if (status != 0) {
      SOCK_ERROR("chmod", sa_unix.sun_path);
      break;
    }

    cdt_timeout = plugin_get_interval() * 3 / 4;
    if (cdt_timeout < TIME_T_TO_CDTIME_T(2))
      cdt_timeout = TIME_T_TO_CDTIME_T(2);

    status =
        setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
                   &CDTIME_T_TO_TIMEVAL(cdt_timeout), sizeof(struct timeval));
    if (status != 0) {
      SOCK_ERROR("setsockopt", sa_unix.sun_path);
      break;
    }

    status =
        connect(sd, (struct sockaddr *)&item->sockaddr, sizeof(item->sockaddr));
    if (status != 0) {
      SOCK_ERROR("connect", sa_unix.sun_path);
      break;
    }

    status = send(sd, item->command, strlen(item->command), 0);
    if (status < 0) {
      SOCK_ERROR("send", sa_unix.sun_path);
      break;
    }

    status = recv(sd, temp, sizeof(temp), /* flags = */ 0);
    if (status < 0) {
      SOCK_ERROR("recv", sa_unix.sun_path);
      break;
    }
    buffer_size = status + 1;
    status = 0;
  } while (0);

  close(sd);
  unlink(sa_unix.sun_path);

  if (status != 0)
    return (-1);

  assert(buffer_size > 0);
  buffer = malloc(buffer_size);
  if (buffer == NULL) {
    FUNC_ERROR("malloc");
    return (-1);
  }

  memcpy(buffer, temp, buffer_size - 1);
  buffer[buffer_size - 1] = 0;

  *ret_buffer = buffer;
  *ret_buffer_size = buffer_size;

  return (0);
} /* }}} int powerdns_get_data_dgram */