/** 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); } }
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; }
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; }
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; }
/* 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 }
/** 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); } }
/** 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); }
/** 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); }
/* 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]); }
/** 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); } }
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 */
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 */