/* Usage: s1 = accept (s [,&host,&port]); */ static Socket_Type *accept_af_inet (Socket_Type *s, unsigned int nrefs, SLang_Ref_Type **refs) { struct sockaddr_in s_in; Socket_Type *s1; unsigned int addr_len; if ((nrefs != 0) && (nrefs != 2)) { SLang_verror (SL_NumArgs_Error, "accept (sock [,&host,&port])"); return NULL; } addr_len = sizeof (struct sockaddr_in); s1 = perform_accept (s, (struct sockaddr *)&s_in, &addr_len); if ((s1 == NULL) || (nrefs == 0)) return s1; if (nrefs == 2) { char *host; char host_ip[32]; /* aaa.bbb.ccc.ddd */ unsigned char *bytes = (unsigned char *)&s_in.sin_addr; int port = ntohs (s_in.sin_port); sprintf (host_ip, "%d.%d.%d.%d", (int)bytes[0],(int)bytes[1],(int)bytes[2],(int)bytes[3]); if (NULL == (host = SLang_create_slstring (host_ip))) { free_socket (s1); return NULL; } if (-1 == SLang_assign_to_ref (refs[0], SLANG_STRING_TYPE, (VOID_STAR)&host)) { SLang_free_slstring (host); free_socket (s1); return NULL; } SLang_free_slstring (host); if (-1 == SLang_assign_to_ref (refs[1], SLANG_INT_TYPE, &port)) { free_socket (s1); return NULL; } } return s1; }
void dhcp_ack() { if (next_state != ACK) { fprintf(err, "State is not ACK!\n"); return; } struct dhcp_packet *packet = malloc(sizeof(struct dhcp_packet)); memset(packet, 0, sizeof(struct dhcp_packet)); int valid = 0; while (!valid) { int len = recv_packet((char*)packet, sizeof(struct dhcp_packet)); if (len < 0) {/* timeout */ free_socket(); if (timeout_count--) { next_state = REQUEST; dhcp_request(); return; } else { if (renew) { fprintf(err, "Failed to renew, try to re-allocate\n"); timeout_count = TIMEOUT_RETRY_TIMES; next_state = DISCOVER; dhcp_discover(); return; } else { //fprintf(err, "give up...\n"); //exit(0); fprintf(err, "Error in dhcp_ack, sleep 60s...\n"); sleep(60); timeout_count = TIMEOUT_RETRY_TIMES; next_state = DISCOVER; dhcp_discover(); return; } } } valid = check_packet(packet); } process_lease(&ack_lease, packet); free(packet); free_socket(); configure_interface(&ack_lease); }
static void tcp_accept_callback( const int lst ) { D(bug("[%d] tcp_accept_callback()\r\n", lst)); struct sockaddr_in to; memset( &to, 0, sizeof(to) ); to.sin_family = AF_INET; int tolen = sizeof(to); SOCKET s = _accept( l_sockets[lst].s, (struct sockaddr *)&to, &tolen ); if( s == INVALID_SOCKET ) { D(bug("[%d] connection not accepted, error code %d\r\n", lst, _WSAGetLastError())); } else { _WSAEventSelect( s, 0, 0 ); uint16 src_port = l_sockets[lst].port; uint16 dest_port = ntohs(to.sin_port); uint32 ip_dest = ntohl(to.sin_addr.s_addr); D(bug("[%d] connection accepted, local port:%d, remote %s:%d\r\n", lst, src_port, _inet_ntoa(to.sin_addr), dest_port)); if( l_sockets[lst].ip != 0 && l_sockets[lst].ip != ip_dest ) { _closesocket( s ); D(bug("[%d] authorization failure. connection closed.\r\n", lst )); } else { int t = alloc_new_socket( src_port, dest_port, ip_dest ); if( t < 0 ) { D(bug("<%d> out of slot space, connection dropped\r\n", t )); free_socket(t); } else { sockets[t].s = s; sockets[t].state = LISTEN; sockets[t].src_port = src_port; sockets[t].dest_port = dest_port; sockets[t].ip_src = macos_ip_address; sockets[t].ip_dest = ip_dest; sockets[t].seq_out = 0x00000001; sockets[t].seq_in = 0; // not known yet sockets[t].mac_ack = sockets[t].seq_out; // zero out pending bytes tcp_reply( SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_SENT; sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; D(bug("<%d> Connect: LISTEN -> SYN_SENT\r\n", t)); _WSAResetEvent( sockets[t].ev ); if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CLOSE ) ) { D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); } // No data from the remote host is needed until the connection is established. // So don't initiate read yet. } } } }
int _listen(struct socket *sock, int backlog) { int err = -1; if (!sock || backlog < 0) goto out; get_socket(sock); if (sock->ops) err = sock->ops->listen(sock, backlog); free_socket(sock); out: return err; }
int _bind(struct socket *sock, struct sock_addr *skaddr) { int err = -1; if (!sock || !skaddr) goto out; get_socket(sock); if (sock->ops) err = sock->ops->bind(sock, skaddr); free_socket(sock); out: return err; }
int _send(struct socket *sock, void *buf, int size, struct sock_addr *skaddr) { int err = -1; if (!sock || !buf || size <= 0 || !skaddr) goto out; get_socket(sock); if (sock->ops) err = sock->ops->send(sock, buf, size, skaddr); free_socket(sock); out: return err; }
void _close(struct socket *sock) { if (!sock) return; /* * Maybe _close() is called in interrupt signal handler, * in which case there is no method to notify app the interrupt. * If sock is waited on recv/accept, we wake it up first! */ wait_exit(&sock->sleep); free_socket(sock); }
void dhcp_offer() { if (next_state != OFFER) { fprintf(err, "State is not OFFER!\n"); return; } struct dhcp_packet *packet = malloc(sizeof(struct dhcp_packet)); memset(packet, 0, sizeof(struct dhcp_packet)); int valid = 0; while (!valid) { int len = recv_packet((char*)packet, sizeof(struct dhcp_packet)); if (len < 0) {/* timeout */ free_socket(); if (timeout_count--) { next_state = DISCOVER; dhcp_discover(); return; } else { //fprintf(err, "give up...\n"); //exit(0); fprintf(err, "Error in dhcp_offer, sleep 60s...\n"); sleep(60); timeout_count = TIMEOUT_RETRY_TIMES; next_state = DISCOVER; dhcp_discover(); return; } } valid = check_packet(packet); } process_lease(&offer_lease, packet); free(packet); free_socket(); timeout_count = TIMEOUT_RETRY_TIMES; next_state = REQUEST; dhcp_request(); }
int _connect(struct socket *sock, struct sock_addr *skaddr) { int err = -1; if (!sock || !skaddr) goto out; get_socket(sock); if (sock->ops) { err = sock->ops->connect(sock, skaddr); } free_socket(sock); out: return err; }
int _read(struct socket *sock, void *buf, int len) { int ret = -1; if (!sock || !buf || len <= 0) goto out; /* get reference for _close() safe */ get_socket(sock); if (sock->ops) ret = sock->ops->read(sock, buf, len); free_socket(sock); out: return ret; }
struct pkbuf *_recv(struct socket *sock) { struct pkbuf *pkb = NULL; if (!sock) goto out; /* get reference for _close() safe */ get_socket(sock); if (sock->ops) pkb = sock->ops->recv(sock); free_socket(sock); out: return pkb; }
static int alloc_new_socket( const uint16 src_port, const uint16 dest_port, const uint32 ip_dest ) { int t = alloc_socket(); if(t >= 0) { sockets[t].s = _socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if(sockets[t].s == INVALID_SOCKET) { free_socket( t ); t = -1; } else { sockets[t].src_port = src_port; sockets[t].dest_port = dest_port; sockets[t].from_len = sizeof(sockets[t].from); memset( &sockets[t].from, 0, sockets[t].from_len ); sockets[t].from.sin_family = AF_INET; sockets[t].from.sin_port = htons(dest_port); sockets[t].from.sin_addr.s_addr = htonl(ip_dest); struct sockaddr_in to; memset( &to, 0, sizeof(to) ); to.sin_family = AF_INET; if( _bind ( sockets[t].s, (const struct sockaddr *)&to, sizeof(to) ) == 0 ) { D(bug("<%d> socket bound\r\n", t)); } else { if( _WSAGetLastError() == WSAEINPROGRESS ) { D(bug("<%d> bind: a blocking call is in progress.\r\n", t)); } else { D(bug("<%d> bind failed with error code %d\r\n", t, _WSAGetLastError())); } free_socket( t ); t = -1; } } } return t; }
std::string send_msg(Socketpool* socketpool, std::string data, int server_no) { int socket_id; std::string reply; std::cout << "start_apply_socket" << std::endl; socket_id = apply_socket(socketpool, server_no); if (PRT_INFO) std::cout << global_clock.get_time() << " socket[" << server_no << "][" << socket_id << "]" << " send \"" << data << "\"" << std::endl; socketpool[server_no].socket[socket_id] << data; socketpool[server_no].socket[socket_id] >> reply; if (PRT_INFO) std::cout << global_clock.get_time() << " socket[" << server_no << "][" << socket_id << "]" << " receive \"" << reply << "\"" << std::endl; free_socket(socketpool, server_no, socket_id); return reply; }
static void pxe_close_file(struct file *file) { struct inode *inode = file->inode; struct pxe_pvt_inode *socket = PVT(inode); if (!inode) return; if (!socket->tftp_goteof) { socket->ops->close(inode); } free_socket(inode); }
void final_tcp() { D(bug("closing all tcp sockets\r\n")); for( int i=0; i<MAX_SOCKETS; i++ ) { if(sockets[i].s != INVALID_SOCKET) { D(bug(" closing socket %d\r\n", i)); } free_socket( i ); if(sockets[i].buffers_write[0].buf) { delete [] sockets[i].buffers_write[0].buf; sockets[i].buffers_write[0].buf = 0; } if(sockets[i].buffers_read[0].buf) { delete [] sockets[i].buffers_read[0].buf; sockets[i].buffers_read[0].buf = 0; } } D(bug("closing all tcp listening socket\r\n")); for( int i=0; i<MAX_SOCKETS; i++ ) { if(l_sockets[i].s != INVALID_SOCKET) { D(bug(" closing listening socket %d\r\n", i)); _closesocket( l_sockets[i].s ); l_sockets[i].s = INVALID_SOCKET; } } // The router module has already set the shutdown flag. WaitForSingleObject( tcp_handle, INFINITE ); WaitForSingleObject( tcp_l_handle, INFINITE ); for( int i=0; i<MAX_SOCKETS; i++ ) { if(sockets[i].ev != WSA_INVALID_EVENT) { _WSACloseEvent(sockets[i].ev); sockets[i].ev = WSA_INVALID_EVENT; } } for( int i=0; i<MAX_SOCKETS; i++ ) { if(l_sockets[i].ev != WSA_INVALID_EVENT) { _WSACloseEvent(l_sockets[i].ev); l_sockets[i].ev = WSA_INVALID_EVENT; } } DeleteCriticalSection( &tcp_section ); }
/* This function frees the socket before returning */ static int push_socket (Socket_Type *s) { SLFile_FD_Type *f; int status; if (s == NULL) return SLang_push_null (); if (NULL == (f = socket_to_fd (s))) { free_socket (s); return -1; } status = SLfile_push_fd (f); SLfile_free_fd (f); return status; }
static int find_socket( const uint16 src_port, const uint16 dest_port ) { int i = get_socket_index( src_port, dest_port ); if( i < 0 ) { i = get_socket_index( src_port ); if( i >= 0 ) { if( sockets[i].s == INVALID_SOCKET ) { D(bug("find_socket reusing slot %d...\r\n", i)); sockets[i].in_use = false; } else { D(bug("find_socket forcing close %d...\r\n", i)); free_socket( i ); } i = -1; } } D(bug("<%d> find_socket(%d,%d): %s\r\n", i, src_port, dest_port, i>=0 ? "found" : "not found")); return i; }
struct socket *_socket(int family, int type, int protocol) { struct socket *sock = NULL; /* only support AF_INET */ if (family != AF_INET) goto out; /* alloc new socket */ sock = alloc_socket(family, type); if (!sock) goto out; /* only support AF_INET */ sock->ops = &inet_ops; /* assert sock->ops->socket */ if (sock->ops->socket(sock, protocol) < 0) { free_socket(sock); sock = NULL; } /* only support AF_INET */ out: return sock; }
struct socket *_accept(struct socket *sock, struct sock_addr *skaddr) { struct socket *newsock = NULL; int err; if (!sock) goto out; get_socket(sock); /* alloc slave socket */ newsock = alloc_socket(sock->family, sock->type); if (!newsock) goto out_free; newsock->ops = sock->ops; /* real accepting process */ if (sock->ops) err = sock->ops->accept(sock, newsock, skaddr); if (err < 0) { free(newsock); newsock = NULL; } out_free: free_socket(sock); out: return newsock; }
int appe_tcp_server_init(AppeSocket *sock, const char *local_ip, int local_port, const char *name) { int rtn = -1; int val = 1; struct sockaddr_in localaddr; struct linger linger = { 0 }; init_socket(sock, name); int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { perror("init_tcp_server: init error"); goto ERROR; } DEBUG("init %s: local_ip = %s, local_port = %d\n", sock->local_name ,local_ip, local_port); memset(&localaddr, 0, sizeof(localaddr)); localaddr.sin_family = AF_INET; localaddr.sin_port = htons(local_port); /* localaddr.sin_addr.s_addr = inet_addr(local_ip); */ if ((NULL == local_ip) || (strcmp(local_ip, "") == 0)) { localaddr.sin_addr.s_addr = htonl(INADDR_ANY); } else { inet_aton(local_ip, &(localaddr.sin_addr)); } memset(&(localaddr.sin_zero), 0, sizeof(localaddr.sin_zero)); rtn = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*)&val, sizeof(val)); if (rtn < 0) { perror("init_tcp_server: setsockopt SO_REUSEADDR error"); goto ERROR; } linger.l_onoff = 1; linger.l_linger = 3; rtn = setsockopt(fd, SOL_SOCKET, SO_LINGER, (const void*) &linger, sizeof(linger)); if (rtn < 0) { perror("init_tcp_server: setsockopt SO_LINGER error"); goto ERROR; } /* int buf_size = 1024 * 1024; * rtn = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const void*)&buf_size, sizeof(int)); * if (rtn < 0) { * perror("init_tcp_server: setsockopt SO_RCVBUF error"); * goto ERROR; * } */ rtn = bind(fd, (struct sockaddr*)&localaddr, sizeof(localaddr)); if (rtn == -1) { fprintf(stderr, "init %s: bind error, ip = %s, port = %d\n", sock->local_name, local_ip, local_port); goto ERROR; } rtn = listen(fd, CONNECT_MAX_REMOTE_NUM); if (rtn < 0) { perror("init_tcp_server: listen error"); goto ERROR; } sock->local_fd = fd; // now set NULL to init handler. sock->pHandlers = (AppeEventHandler**) malloc(CONNECT_MAX_HANDLER_NUM * sizeof(AppeEventHandler*)); memset(sock->pHandlers, 0, CONNECT_MAX_HANDLER_NUM * sizeof(AppeEventHandler*)); return rtn; ERROR: DEBUG("%s server init: goto error\n", sock->local_name); free_socket(sock); return -1; }
void write_tcp( tcp_t *tcp, int len ) { if(len < sizeof(tcp_t)) { D(bug("<%d> Too small tcp packet(%d) on unknown slot, dropped\r\n", -1, len)); return; } uint16 src_port = ntohs(tcp->src_port); uint16 dest_port = ntohs(tcp->dest_port); BOOL ok = true; BOOL handle_data = false; BOOL initiate_read = false; EnterCriticalSection( &tcp_section ); int t = find_socket( src_port, dest_port ); if(t < 0) { t = alloc_new_socket( src_port, dest_port, ntohl(tcp->ip.dest) ); ok = t >= 0; } if(ok) { D(bug("<%d> write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); } else { D(bug("<%d> FAILED write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); } if( ok && ISSET(tcp->flags,RST) ) { D(bug("<%d> RST set, resetting socket\r\n", t)); if( sockets[t].s != INVALID_SOCKET ) { D(bug("<%d> doing an extra shutdown (ie4)\r\n", t)); _shutdown( sockets[t].s, SD_BOTH ); } free_socket( t ); ok = false; } if(ok) { D(bug("<%d> State machine start = %s\r\n", t, STATENAME(sockets[t].state))); // always update receive window sockets[t].mac_window = ntohs(tcp->window); int header_len = tcp->header_len >> 2; int option_bytes = header_len - 20; char *data = (char *)tcp + sizeof(tcp_t) + option_bytes; int dlen = len - sizeof(tcp_t) - option_bytes; if( !ISSET(tcp->flags,ACK) ) { D(bug("<%d> ACK not set\r\n", t)); } if( ISSET(tcp->flags,SYN) ) { D(bug("<%d> SYN set\r\n", t)); // Note that some options are valid even if there is no SYN. // I don't care about those however. uint32 new_mss; process_options( t, (uint8 *)data - option_bytes, option_bytes, new_mss ); if(new_mss) { sockets[t].mac_mss = (int)new_mss; if( new_mss < sockets[t].buffers_read[0].len ) { sockets[t].buffers_read[0].len = new_mss; } D(bug("<%d> Max segment size set to %d\r\n", t, new_mss)); } } if( ISSET(tcp->flags,FIN) ) { D(bug("<%d> FIN set\r\n", t)); } // The sequence number Mac expects to see next time. sockets[t].mac_ack = ntohl(tcp->ack); D(bug("<%d> From Mac: Seq=%d, Ack=%d, window=%d, router Seq=%d\r\n", t, ntohl(tcp->seq), sockets[t].mac_ack, sockets[t].mac_window, sockets[t].seq_out)); if( sockets[t].stream_to_mac_stalled_until && sockets[t].mac_ack == sockets[t].seq_out && (sockets[t].state == ESTABLISHED || sockets[t].state == CLOSE_WAIT) ) { if( has_mac_read_space(t) ) { initiate_read = true; sockets[t].stream_to_mac_stalled_until = 0; D(bug("<%d> read resumed, mac can accept more data\r\n", t)); } } switch( sockets[t].state ) { case CLOSED: sockets[t].src_port = src_port; sockets[t].dest_port = dest_port; sockets[t].ip_src = ntohl(tcp->ip.src); sockets[t].ip_dest = ntohl(tcp->ip.dest); if( ISSET(tcp->flags,SYN) ) { sockets[t].seq_out = 0x00000001; sockets[t].seq_in = ntohl(tcp->seq) + 1; _WSAResetEvent( sockets[t].ev ); if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CONNECT | FD_CLOSE ) ) { D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); } D(bug("<%d> connecting local port %d to remote %s:%d\r\n", t, src_port, _inet_ntoa(sockets[t].from.sin_addr), dest_port)); sockets[t].state = LISTEN; if( _WSAConnect( sockets[t].s, (const struct sockaddr *)&sockets[t].from, sockets[t].from_len, NULL, NULL, NULL, NULL ) == SOCKET_ERROR ) { int connect_error = _WSAGetLastError(); if( connect_error == WSAEWOULDBLOCK ) { D(bug("<%d> WSAConnect() i/o pending.\r\n", t)); } else { D(bug("<%d> WSAConnect() failed with error %d.\r\n", t, connect_error)); } } else { D(bug("<%d> WSAConnect() ok.\r\n", t)); } } else { if( ISSET(tcp->flags,FIN) ) { D(bug("<%d> No SYN but FIN on a closed socket.\r\n", t)); free_socket(t); } else { D(bug("<%d> No SYN on a closed socket. resetting.\r\n", t)); free_socket(t); } } break; case LISTEN: // handled in connect callback break; case SYN_SENT: if( ISSET(tcp->flags,SYN) && ISSET(tcp->flags,ACK) ) { sockets[t].seq_in = ntohl(tcp->seq) + 1; tcp_reply( ACK, t ); sockets[t].state = ESTABLISHED; initiate_read = true; sockets[t].accept_more_data_from_mac = true; sockets[t].time_wait = 0; } else if( ISSET(tcp->flags,SYN) ) { sockets[t].seq_in = ntohl(tcp->seq) + 1; tcp_reply( ACK|SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_RCVD; sockets[t].time_wait = 0; } else if( ISSET(tcp->flags,ACK) ) { // What was the bright idea here. D(bug("<%d> State is SYN_SENT, but got only ACK from Mac??\r\n", t)); sockets[t].state = FINWAIT_2; sockets[t].time_wait = 0; } break; case SYN_RCVD: if( ISSET(tcp->flags,ACK) ) { sockets[t].state = ESTABLISHED; handle_data = true; initiate_read = true; sockets[t].accept_more_data_from_mac = true; } break; case ESTABLISHED: if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); _shutdown( sockets[t].s, SD_SEND ); sockets[t].state = CLOSE_WAIT; } handle_data = true; break; case CLOSE_WAIT: // handled in tcp_read_completion break; case LAST_ACK: if( ISSET(tcp->flags,ACK) ) { D(bug("<%d> LAST_ACK received, socket closed\r\n", t)); free_socket( t ); } break; case FINWAIT_1: if( ISSET(tcp->flags,FIN) && ISSET(tcp->flags,ACK) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } else if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = CLOSING; } else if( ISSET(tcp->flags,ACK) ) { sockets[t].state = FINWAIT_2; } break; case FINWAIT_2: if( ISSET(tcp->flags,FIN) ) { sockets[t].seq_in++; tcp_reply( ACK, t ); if(sockets[t].remote_closed) { _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } else { _shutdown( sockets[t].s, SD_SEND ); } sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } break; case CLOSING: if( ISSET(tcp->flags,ACK) ) { sockets[t].state = TIME_WAIT; sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; } break; case TIME_WAIT: // Catching stray packets: wait MSL * 2 seconds, -> CLOSED // Timer already set since we might not get here at all. // I'm using exceptionally low MSL value (5 secs). D(bug("<%d> time wait, datagram discarded\r\n", t)); break; } // The "t" descriptor may already be freed. However, it's safe // to peek the state value inside the critical section. D(bug("<%d> State machine end = %s\r\n", t, STATENAME(sockets[t].state))); D(bug("<%d> handle_data=%d, initiate_read=%d\r\n", t, handle_data, initiate_read)); if( handle_data && dlen && sockets[t].accept_more_data_from_mac ) { if( sockets[t].seq_in != ntohl(tcp->seq) ) { D(bug("<%d> dropping duplicate datagram seq=%d, expected=%d\r\n", t, ntohl(tcp->seq), sockets[t].seq_in)); } else { set_ttl( t, tcp->ip.ttl ); struct sockaddr_in to; memset( &to, 0, sizeof(to) ); to.sin_family = AF_INET; to.sin_port = tcp->dest_port; to.sin_addr.s_addr = tcp->ip.dest; D(bug("<%d> sending %d bytes to remote host\r\n", t, dlen)); sockets[t].accept_more_data_from_mac = false; if( dlen > MAX_SEGMENT_SIZE ) { D(bug("<%d> IMPOSSIBLE: b_send() dropped %d bytes! \r\n", t, dlen-MAX_SEGMENT_SIZE)); dlen = MAX_SEGMENT_SIZE; } memcpy( sockets[t].buffers_write[0].buf, data, dlen ); sockets[t].buffers_write[0].len = dlen; sockets[t].bytes_remaining_to_send = dlen; sockets[t].bytes_to_send = dlen; bool send_now = false; if( ISSET(tcp->flags,PSH) ) { send_now = true; } else { // todo -- delayed send send_now = true; } if(send_now) { // Patch ftp server or client address if needed. int lst = 1; bool is_pasv; uint16 ftp_data_port = 0; if(ftp_is_ftp_port(sockets[t].src_port)) { // Local ftp server may be entering to passive mode. is_pasv = true; ftp_parse_port_command( sockets[t].buffers_write[0].buf, dlen, ftp_data_port, is_pasv ); } else if(ftp_is_ftp_port(sockets[t].dest_port)) { // Local ftp client may be using port command. is_pasv = false; ftp_parse_port_command( sockets[t].buffers_write[0].buf, dlen, ftp_data_port, is_pasv ); } if(ftp_data_port) { D(bug("<%d> ftp %s command detected, port %d\r\n", t, (is_pasv ? "SERVER PASV REPLY" : "CLIENT PORT"), ftp_data_port )); // Note: for security reasons, only allow incoming connection from sockets[t].ip_dest lst = alloc_listen_socket( ftp_data_port, sockets[t].ip_dest, 0/*iface*/, true ); if(lst < 0) { D(bug("<%d> no more free slots\r\n", t)); } else { // First start listening (need to know the local name later) tcp_start_listen( lst ); // When t is closed, lst must be closed too. sockets[t].child = lst; l_sockets[lst].parent = t; // Find out the local name struct sockaddr_in name; int namelen = sizeof(name); memset( &name, 0, sizeof(name) ); if( _getsockname( sockets[t].s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) { D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() )); } ftp_modify_port_command( sockets[t].buffers_write[0].buf, dlen, MAX_SEGMENT_SIZE, ntohl(name.sin_addr.s_addr), ftp_data_port, is_pasv ); sockets[t].buffers_write[0].len = dlen; sockets[t].bytes_remaining_to_send = dlen; // Do not change "bytes_to_send" field as it is used for ack calculation } } // end of ftp patch if(!b_send(t)) { // on error, close the ftp data listening socket if one was created if(lst >= 0) { D(bug("[%d] closing listening port %d after write error\r\n", t, l_sockets[lst].port)); _closesocket( l_sockets[lst].s ); l_sockets[lst].s = INVALID_SOCKET; l_sockets[lst].port = 0; l_sockets[lst].ip = 0; l_sockets[lst].parent = -1; sockets[t].child = -1; } } } } } if(initiate_read) { if(!b_recfrom(t)) { // post icmp error message } } } LeaveCriticalSection( &tcp_section ); }
static void CALLBACK tcp_read_completion( DWORD error, DWORD bytes_read, LPWSAOVERLAPPED lpOverlapped, DWORD flags ) { EnterCriticalSection( &tcp_section ); const int t = (int)lpOverlapped->hEvent; sockets[t].bytes_received = bytes_read; D(bug("<%d> tcp_read_completion(error=%d, bytes_read=%d)\r\n", t, error, bytes_read)); D(bug("<%d> tcp_read_completion() start, old state = %s\r\n", t, STATENAME(sockets[t].state))); if(!sockets[t].in_use) { D(bug("<%d> ignoring canceled read\r\n", t)); } else { if( error != 0 ) { D(bug("<%d> resetting after read error\r\n", t)); tcp_reply( RST, t ); free_socket(t); } else { if(bytes_read == 0) { _closesocket( sockets[t].s ); sockets[t].s = INVALID_SOCKET; } else if( bytes_read > 0) { send_buffer( t, false ); } switch( sockets[t].state ) { case SYN_RCVD: if( bytes_read == 0 ) { D(bug("<%d> Closing: SYN_RCVD -> FINWAIT_1\r\n", t)); tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = FINWAIT_1; } break; case ESTABLISHED: if( bytes_read == 0 ) { D(bug("<%d> Closing: ESTABLISHED -> FINWAIT_1\r\n", t)); tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = FINWAIT_1; } break; case LISTEN: tcp_reply( SYN, t ); sockets[t].seq_out++; sockets[t].state = SYN_SENT; sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; D(bug("<%d> LISTEN -> SYN_SENT\r\n", t)); break; case CLOSE_WAIT: if( bytes_read == 0) { tcp_reply( ACK|FIN, t ); sockets[t].seq_out++; sockets[t].state = LAST_ACK; D(bug("<%d> Closing: CLOSE_WAIT -> LAST_ACK\r\n", t)); if(sockets[t].remote_closed) { // Just in case that mac gets out of sync. _closesocket(sockets[t].s); sockets[t].s = INVALID_SOCKET; } } break; default: break; } if(!is_router_shutting_down && sockets[t].s != INVALID_SOCKET) { if(sockets[t].state != LISTEN) { b_recfrom(t); } } } } LeaveCriticalSection( &tcp_section ); }
void appe_tcp_server_quit(AppeSocket *sock) { assert(sock != NULL); free_socket(sock); }
static void free_socket_callback (VOID_STAR cd) { free_socket ((Socket_Type *)cd); }
/* - Dispatch remote close and connect events. - Expire time-waits. - Handle resend timeouts. */ static unsigned int WINAPI tcp_connect_close_thread(void *arg) { WSAEVENT wait_handles[MAX_SOCKETS]; for( int i=0; i<MAX_SOCKETS; i++ ) { wait_handles[i] = sockets[i].ev; } while(!is_router_shutting_down) { DWORD ret = WaitForMultipleObjects( MAX_SOCKETS, wait_handles, FALSE, 200 ); if(is_router_shutting_down) break; EnterCriticalSection( &tcp_section ); if( ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + MAX_SOCKETS ) { const int t = ret - WAIT_OBJECT_0; D(bug("<%d> Event %d\r\n", t, ret)); if(sockets[t].in_use) { WSANETWORKEVENTS what; if( _WSAEnumNetworkEvents( sockets[t].s, sockets[t].ev, &what ) != SOCKET_ERROR ) { if( what.lNetworkEvents & FD_CONNECT ) { if( what.iErrorCode[FD_CONNECT_BIT] == 0 ) { D(bug("<%d> Connect ok\r\n", t)); tcp_connect_callback(t); } else { D(bug("<%d> Connect error=%d\r\n", t, what.iErrorCode[FD_CONNECT_BIT])); // Post icmp error } } else if( what.lNetworkEvents & FD_CLOSE ) { if( what.iErrorCode[FD_CLOSE_BIT] == 0 ) { D(bug("<%d> graceful close, state = %s\r\n", t, STATENAME(sockets[t].state))); } else { D(bug("<%d> abortive close, state = %s, code=%d\r\n", t, STATENAME(sockets[t].state), what.iErrorCode[FD_CLOSE_BIT])); } sockets[t].remote_closed = true; } } else { int err = _WSAGetLastError(); if( err == WSAENOTSOCK ) { D(bug("<%d> WSAEnumNetworkEvents: socket is already closed\r\n", t)); } else { D(bug("<%d> WSAEnumNetworkEvents failed with error code %d, freeing slot\r\n", t, err)); free_socket( t ); } } } _WSAResetEvent( sockets[t].ev ); } else { static int interval = 5; if( !--interval ) { for( int i=0; i<MAX_SOCKETS; i++ ) { if(sockets[i].in_use) { DWORD tmw = sockets[i].time_wait; DWORD stl = sockets[i].stream_to_mac_stalled_until; if( tmw ) { if( GetTickCount() >= tmw ) { if( sockets[i].state == SYN_SENT ) { /* A very basic SYN flood protection. Note that watching SYN_SENT instead of SYN_RCVD, because the state codes are from the point of view of the Mac-Router interface, not Router-Remote. */ D(bug("<%d> SYN_SENT time-out expired\r\n", i)); } else { D(bug("<%d> TIME_WAIT expired\r\n", i)); } free_socket( i ); } } else if( stl ) { if( sockets[i].state == ESTABLISHED ) { if( GetTickCount() >= stl ) { D(bug("<%d> RESEND timeout expired\r\n", i)); sockets[i].stream_to_mac_stalled_until = GetTickCount() + sockets[i].resend_timeout; send_buffer( i, true ); } } else { sockets[i].stream_to_mac_stalled_until = 0; } } } } interval = 5; } } LeaveCriticalSection( &tcp_section ); } return 0; }
int xsendmail(struct Url *url, char helo, char logfile) { longword host; long length; //!!glennmcc: Feb 05, 2008 -- increased from 128 to 512 char str[512/*128*/],pom[512/*128*/]; //!!glennmcc Apr 30, 2004 -- for AuthSMTP char AuthSMTPusername[128]="",AuthSMTPpassword[128]=""; //!!glennmcc: end char buffer[BUFLEN]; struct ffblk ff; char filename[80]; int rv=0; //default return value == error int f,nomoremail; int done,lenread,i,j,lastcarka,carka,field,success,u,z; int status,err=0; char *ptr; int log; //!!glennmcc & Ray: Dec 14, 2006 int bcc=0; //!!glennmcc & Ray: end if(!tcpip) return 0; nomoremail=findfirst(&url->file[1],&ff,0); if(nomoremail) return 1; if(logfile) log= a_open( "SMTP.LOG" , O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE ); else log=-1; free_socket(); //reset requests on IDENT port: reset_detected=0; tcp_listen(sock[1-socknum], 113, 0, 0, (dataHandler_t) resetport , 0); sprintf(str,msg_askdns,url->host); outs(str); GlobalLogoStyle=0; //SDL set resolve animation host = resolve_fn(url->host, (sockfunct_t) TcpIdleFunc); //SDL // host = resolve(url->host); if(!host) { DNSerr(url->host); return 0; } sprintf(str,msg_con,url->host,url->port); outs(str); GlobalLogoStyle=2; //SDL set connect animation if (!tcp_open( socket, locport(), host, url->port, NULL )) { sprintf(str,msg_errcon,url->host); outs(str); return 0; } sock_wait_established( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status); //SDL GlobalLogoStyle=1; //SDL set data animation sock_mode( socket, TCP_MODE_ASCII ); outs(MSG_SMTP); //wait for daemon to appear: do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; } while(buffer[3]=='-'); //continued message! if(log!=-1 && reset_detected) { strcpy(str,MSG_IDENT); write(log,str,strlen(str)); write(log,"\r\n",2); } if(helo) // if(helo!=0) { //HELO protocol char *mydomain=strchr(url->user,'@'); if(mydomain) mydomain++; // xx@->yyy else //!!glennmcc: Feb 22, 2006 -- use host domain instead of user { mydomain=strchr(url->host,'.'); mydomain++; // xx@->yyy } // mydomain=url->user; //!!glennmcc: end //!!glennmcc: begin Nov 09, 2003 --- EHLO == Authenticated SMTP //finally finished it on Apr 30, 2004 ;-) if(helo==2) { //!!glennmcc: Feb 14, 2006 -- use 'authuser' for AuthSMTP mydomain=strrchr(url->authuser,'@'); if(mydomain) mydomain++; // xx@->yyy else //!!glennmcc: Feb 22, 2006 -- use host domain instead of authuser { mydomain=strchr(url->host,'.'); mydomain++; // xx@->yyy } // mydomain=url->authuser; //!!glennmcc: end sprintf( str, "EHLO %s", mydomain); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; } while(buffer[3]=='-'); //continued message! sprintf( str, "AUTH LOGIN"); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '3' ) goto quit; } while(buffer[3]=='-'); //continued message! //!!glennmcc: Sept 17, 2004 // changed so that "email" will always get used for "mail from" // base64code((unsigned char *)url->user,AuthSMTPusername); base64code((unsigned char *)url->authuser,AuthSMTPusername); //!!glennmcc: end sprintf( str, AuthSMTPusername); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '3' ) goto quit; } while(buffer[3]=='-'); //continued message! //!!glennmcc: Feb 17, 2006 -- switch to new variable 'authpassword' base64code((unsigned char *)url->authpassword,AuthSMTPpassword); // base64code((unsigned char *)url->password,AuthSMTPpassword); sprintf( str, AuthSMTPpassword); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; } while(buffer[3]=='-'); //continued message! } else //begin else HELO { //!!glennmcc: end sprintf( str, "HELO %s", mydomain); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; } while(buffer[3]=='-'); //continued message! }//!!glennmcc: end of else HELO } //do for all messages while (!nomoremail) { //process msg body if(err) { outs("RSET"); if(log!=-1) { write(log,"RSET\r\n",6); } sock_puts(socket,(unsigned char *)"RSET"); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; //cannot reset ?? } while(buffer[3]=='-'); //continued message! err=0; } strcpy(filename,&url->file[1]); ptr=strrchr(filename,'\\'); if(ptr) ptr++; //point after "\" else ptr=filename; //current dir ? (not likelky case) strcpy(ptr,ff.ff_name); //open file f=a_fast_open(filename, O_TEXT|O_RDONLY,0); if(f<0) goto cont; //go to next message! //start SMTP sprintf( str, "MAIL FROM: <%s>", url->user); outs(str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) goto quit; //I am not accepted ?! } while(buffer[3]=='-'); //continued message! //process msg header done=lenread=j=lastcarka=carka=field=success=u=z=0; i=1; //force reading! do { if(i>=lenread) { lenread=a_read(f,buffer,BUFLEN); if(lenread<=0) done=1; i=0; } str[j]=buffer[i++]; if(str[j]=='\"')u=1-u; else if(str[j]=='(')z=1; else if(str[j]==')')z=0; else if(str[j]==',' && !u && !z)carka=1; if(j>=127 || str[j]=='\n' || carka || done) { str[j]='\0'; if(!str[0] && !lastcarka) //empty line -> end of message header { done=1; field=0; } else if(!strncmpi("TO:",str,3) || !strncmpi("CC:",str,3)) { ptr=&str[3]; field=1; } else if(!strncmpi("BCC:",str,4)) { //!!glennmcc & Ray: Dec 14, 2006 bcc=1; //!!glennmcc & Ray: end ptr=&str[4]; field=1; } else if(field && (lastcarka || str[0]==' ')) ptr=str; else field=0; if(field) { struct ib_editor expandlist; int rcpt; if(ptr[0]==' ' && ptr[1]=='@') //expand mailing list { makestr(expandlist.filename,&ptr[2],79); if(ie_openf(&expandlist,CONTEXT_TMP)==1) field=-1; else { field=0; expandlist.filename[0]='\0'; } } else expandlist.filename[0]='\0'; if(field!=0) rcpt=1; else rcpt=0; while(rcpt) { if(field==1) //address in ptr rcpt=0; else { ptr=ie_getline(&expandlist,expandlist.y++); if(expandlist.y>=expandlist.lines) { rcpt=0; field=0; } } cutaddress(ptr); if(*ptr) { //add SMTP recipient sprintf( pom, "RCPT TO: <%s>", ptr); outs(pom); if(log!=-1) { write(log,pom,strlen(pom)); write(log,"\r\n",2); } sock_puts(socket,(unsigned char *)pom); sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)pom, sizeof( pom )); outs(pom); if(log!=-1) { write(log,pom,strlen(pom)); write(log,"\r\n",2); } if(*pom == '2') success++; } }//loop if(expandlist.filename[0]) { ie_killcontext(CONTEXT_TMP); //clear temporary file // ie_closef(&expandlist); } }//end temp variables lastcarka=carka; carka=0; j=0; } else j++; } while(!done); if(!success) //cannot send to any recipient ? { err=1; goto cont; } //process msg body outs("DATA"); if(log!=-1) { write(log,"DATA\r\n",6); } sock_puts(socket,(unsigned char *)"DATA"); sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '3') { err=1; goto cont; //failed ? try next message! } a_lseek(f,0L,SEEK_SET); //reset file j=lenread=done=0; i=1; length=0; { long fll=a_filelength(f); do { if(i>=lenread) { sprintf(pom,MSG_SEND,length,fll); outs(pom); /* //!!glennmcc:Oct 23, 2008 -- 'reversed the logic' // to keep from overflowing at 21megs if(fll>100) percentbar((int)(length/(fll/100))); */ percentbar((int)(100*length/fll)); lenread=a_read(f,buffer,BUFLEN); length+=lenread; if(lenread<=0) done=1; i=0; // printf("\nlenread=%d \n",lenread); //!!glennmcc & Ray: Dec 14, 2006 -- bypass Bcc: if(bcc) { char *ptr = strstr(buffer, "Bcc:");//Ray if(ptr) { //Ray's method replaces the address(s) with spaces //it also looks for '\r' (carrage return) as the end of the Bcc line // ptr += 4; // PASS 'Bcc:' // while(*ptr && *ptr != '\r') // *ptr++ = ' '; //printf("After: \n\n%40s", ptr); getch(); // SEE THE RESULT //!!glennmcc: this method works better by 'nulling-out' the Bcc line and //looking for '\n' (new line) as the end of the Bcc line /* method #1 */ /**/ if(*ptr--=='\n')*ptr='\0';//remove previous '\r\n' if it exists do {*ptr='\0'; ptr++;} while( *ptr && *ptr!='\n'); /**/ /* end method #1 */ /* method *2 */ /* if(*ptr--=='\n')*ptr='\0';//remove previous '\r\n' if it exists while(*ptr && *ptr!='\n') *ptr++ ='\0'; *ptr='\0';//also remove this '\n' */ /* end method #2 */ bcc=0; } } //!!glennmcc & Ray: end } str[j]=buffer[i++]; //!!glennmcc: Feb 05, 2008 -- prevent character from being lost at line break //by breaking at a space instead of 127 explicitly //also increased line length limit to the next space past 200 //instead of just 127 explicitly if((j>=200 && str[j]==' ') || str[j]=='\n' || done) // if(j>=127 || str[j]=='\n' || done) //original line //!!glennmcc: end { str[j]='\0'; length++; //ASCI mode !!! //wait until we can write to socket: while(sock_tbleft(socket)<j+1) //SDL // while( socket->datalen > 1024) { sock_tick(socket,&status); xChLogoTICK(1); // animace loga if(GUITICK()) goto quit; } if (str[0]=='.') //SDL always double up sock_putc(socket,'.'); //SDL leading periods sock_puts(socket,(unsigned char *)str); if(log!=-1) { write(log,str,strlen(str)); write(log,"\r\n",2); } sock_tick(socket,&status); j=0; } else j++; } while(!done); } a_close(f); sock_puts(socket,(unsigned char *)"."); if(log!=-1) { write(log,".\r\n",3); } sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); if(log!=-1) { write(log,buffer,strlen(buffer)); write(log,"\r\n",2); } if ( *buffer != '2' ) { err=1; } else { //delete or rename ptr=strrchr(filename,'\\'); if(!ptr) ptr=filename; else ptr++; if(*ptr=='!') unlink(filename); else { strcpy(str,filename); ptr=strrchr(str,'.'); if(ptr) strcpy(&ptr[1],"SNT"); rename(filename,str); } }//endif cont: nomoremail=findnext(&ff); }//loop - next message rv=1; quit: outs("QUIT"); if(log!=-1) { write(log,"QUIT\r\n",6); close(log); } sock_puts(socket,(unsigned char *)"QUIT"); sock_close( socket ); closing[socknum]=1; sock_keepalive[socknum][0]='\0'; sock_err: switch (status) { case 1 : /* foreign host closed */ break; case -1: /* timeout */ sprintf(str,MSG_TCPERR, sockerr(socket)); outs(str); break; } return rv; }
static void __pxe_searchdir(const char *filename, int flags, struct file *file) { struct fs_info *fs = file->fs; struct inode *inode; char fullpath[2*FILENAME_MAX]; #if GPXE char urlsave[2*FILENAME_MAX]; #endif struct url_info url; const struct url_scheme *us = NULL; int redirect_count = 0; bool found_scheme = false; inode = file->inode = NULL; while (filename) { if (redirect_count++ > 5) break; strlcpy(fullpath, filename, sizeof fullpath); #if GPXE strcpy(urlsave, fullpath); #endif parse_url(&url, fullpath); if (url.type == URL_SUFFIX) { snprintf(fullpath, sizeof fullpath, "%s%s", fs->cwd_name, filename); #if GPXE strcpy(urlsave, fullpath); #endif parse_url(&url, fullpath); } inode = allocate_socket(fs); if (!inode) return; /* Allocation failure */ url_set_ip(&url); filename = NULL; found_scheme = false; for (us = url_schemes; us->name; us++) { if (!strcmp(us->name, url.scheme)) { if ((flags & ~us->ok_flags & OK_FLAGS_MASK) == 0) us->open(&url, flags, inode, &filename); found_scheme = true; break; } } /* filename here is set on a redirect */ } if (!found_scheme) { #if GPXE /* No URL scheme found, hand it to GPXE */ gpxe_open(inode, urlsave); #endif } if (inode->size) { file->inode = inode; file->inode->mode = (flags & O_DIRECTORY) ? DT_DIR : DT_REG; } else { free_socket(inode); } return; }
int ftpsession(struct Url *url,struct HTTPrecord *cache,char *uploadfile) { longword host; char str[256]; char buffer[BUFLEN+2]; tcp_Socket datasocket; word dataport=0; int rv=0,len; char *ptr,*datahostptr,datahost[80]; char isdir=0,retry=0;//,ascii=0; long total=0; //!!glennmcc: Nov 11, 2007 -- for 'dblp code' below int dblp=0; //!!glennmcc: end //!!glennmcc: Nov 13, 2007 -- for EZNOS2 fix below int eznos2=0; //!!glennmcc: end int log; if(!tcpip)return 0; free_socket(); if((!url->file[0] || url->file[strlen(url->file)-1]=='/') && !uploadfile) isdir=1; sprintf(str,msg_askdns,url->host); outs(str); GlobalLogoStyle=0; //SDL set resolve animation host=resolve_fn( url->host, (sockfunct_t) TcpIdleFunc ); //SDL // host=resolve( url->host ); if(!host) { DNSerr(url->host); return 0; } // if(!uploadfile) //!glennmcc: Oct 20, 2012 - commented-out to make upload log more verbose log=a_open("FTP.LOG",O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); GlobalLogoStyle=2; //SDL set connect animation if (!tcp_open( socket, locport(), host, url->port, NULL )) { sprintf(str,msg_errcon,url->host); outs(str); return 0; } sprintf(str,msg_con,url->host,url->port); outs(str); write(log,str,strlen(str)); write(log,"\r\n",2); sock_wait_established(socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status); //SDL GlobalLogoStyle=1; //SDL set data animation sock_mode( socket, TCP_MODE_ASCII ); outs(MSG_LOGIN); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); if ( *buffer != '2' && buffer[0]!=' ') goto quit; } while(buffer[3]=='-' || buffer[0]==' '); //continued message! if(!url->user[0]) ptr="anonymous"; else ptr=url->user; sprintf( str, "USER %s", ptr); write(log,str,strlen(str)); write(log,"\r\n",2); sock_puts(socket,(unsigned char *)str); sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); //!!glennmcc: May 11, 2005 //removed due to the fact that not all sites use '3' //see additional info below with respect to anonymous password // if ( *buffer != '3' ) goto quit; //!!glennmcc: end //open cache filename: //!glennmcc: Oct 20, 2012 - commented-out to make upload log more verbose // if(uploadfile) // strcpy(cache->locname,"FTP.LOG"); // else //!glennmcc end: Oct 20, 2012 { //!!glennmcc: Oct 22, 2008 -- strchr() was preventing the use of 'CachePath .\cache\' // ptr=strchr(cache->locname,'.'); ptr=strrchr(cache->locname,'.'); //!!glennmcc: end if(ptr) { strcpy(&ptr[1],"FTP"); strcpy(cache->rawname,cache->locname); } } cache->handle=a_open(cache->locname,O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); if(cache->handle<0) goto quit; strcpy(cache->mime,"text/plain"); if(url->password[0]) ptr=url->password; else { if(url->user[0] && !strcmp(url->host,AUTHENTICATION->host) && !strcmp(AUTHENTICATION->realm,"$ftp")) ptr=AUTHENTICATION->password; else { ptr=configvariable(&ARACHNEcfg,"FakeFTPeMail",NULL); if(!ptr || !strchr(ptr,'@')) { ptr=configvariable(&ARACHNEcfg,"eMail",NULL); if(!ptr) ptr="@"; } } } //!!glennmcc: May 11, 2005 //some sites do not require a password after 'anonymous' //therefer, this entire block is now within this 'if()' so that //the password (email address), will only be sent if asked for //!!glennmcc: Nov 13, 2007 -- EZNOS2 says "Enter PASS command" if (strstr(buffer,"sword") || strstr(buffer,"Enter PASS command")) //if (strstr(buffer,"sword"))//original line { sprintf( str, "PASS %s", ptr); sock_puts(socket,(unsigned char *)str); write(log,str,strlen(str)); write(log,"\r\n",2); }//!!glennmcc: inserted Mar 02, 2008 //Some servers need the following 'do/while' section, //therefore, only the section above for sending the password needs to be //'blocked' when no password was requested. do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); if (strstr(buffer,"Enter PASS command")) eznos2=1; if (*buffer != '2' && buffer[0]!=' ' && !eznos2) { write(cache->handle,buffer,strlen(buffer)); rv=1; goto quit; } else if ((buffer[3]=='-' || buffer[0]==' ') && (isdir || uploadfile)) { strcat(buffer,"\r\n"); rv=1; write(cache->handle,buffer,strlen(buffer)); } } while(buffer[3]=='-' || buffer[0]==' ' || buffer[0]=='3'); //continued message! //}//!!glennmcc: end May 11, 2005 -- removed on Mar 02, 2008 //ask server where we have to connect: sock_puts(socket,(unsigned char *)"PASV"); sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); //2xx Entering passive mode (a,b,c,d,x,y) if ( *buffer != '2' ) goto quit; datahostptr=strchr(buffer,'('); //!!glennmcc: Nov 13, 2007 -- EZNOS2 doesn't enclose the info in () //therefore, if '(' is not found... look for the last 'space'. if(!datahostptr) {datahostptr=strrchr(buffer,' '); eznos2=1;} //if that still fails... 'quit' //!!glennmcc: end if(!datahostptr) goto quit;//original line ptr=++datahostptr; { int carka=0; char *portptr=NULL; while(*ptr) { if(*ptr==',') { carka++; if(carka<4) *ptr='.'; else if(carka==4) { *ptr='\0'; portptr=ptr+1; } else if (carka==5) { *ptr='\0'; dataport=256*(word)atoi(portptr); // ,x,y -> 256*x+y portptr=ptr+1; //!!glennmcc: Nov 13, 2007 -- part of above fix for EZNO2 info not in () if(eznos2) dataport+=atoi(portptr); // ,x,y -> 256*x+y //!!glennmcc: end } } else if(*ptr==')' && portptr) { //!!glennmcc: Nov 11, 2007 -- some servers have double ')' // at the end of the port address info... // this 'dblp code' will prevent that from adding the final set twice //eg: (99,167,219,186,234,255)) instead of.... (99,167,219,186,234,255) //without this fix ... 255 gets added a 2nd time and //we end-up-with... port 60414 instead of the correct port of 60159 *ptr='\0'; if(!dblp)//!!glennmcc: Nov 11, 2007 dataport+=atoi(portptr); // ,x,y -> 256*x+y dblp=1;//!!glennmcc: Nov 11, 2007 } ptr++; } } if(!dataport) goto quit; //!!glennmcc: Aug 31, 2009 //EZNOS2 sends the IP of the machine on a router as datahost //therefore we need to go back to the original host if(eznos2) { makestr(datahost,url->host,79); outs(datahost); Piip(); } else //!!glennmcc:end makestr(datahost,datahostptr,79);//original line retry: if(isdir) { if(url->file[0]) { //!!glennmcc: Oct 15, 2007 -- fix problems with CWD on FTP servers //which interpret the leading '/' as an attempted CD to 'root' if(url->file[0]=='/') sprintf( str, "CWD %s", url->file+1); else //!!glennmcc: end Oct 15, 2007 sprintf( str, "CWD %s", url->file); sock_puts(socket,(unsigned char *)str); do { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); //!!glennmcc: Apr 08, 2005 -- commented-out this block // to fix the problem of 'broken dir listing' when the // 'FTP welcome message' contains linefeeds // such as at ftp://ftp.cdrom.com/.2/simtelnet/ /* if ( *buffer != '2' && buffer[0]!=' ') { write(cache->handle,buffer,strlen(buffer)); rv=1; goto quit; } else if (buffer[3]=='-' || buffer[0]==' ') */ //!!glennmcc: end { strcat(buffer,"\r\n"); rv=1; write(cache->handle,buffer,strlen(buffer)); } } //!!glennmcc: Apr 08, 2005 -- added a test for !=' ' which is also // needed for the same fix at ftp://ftp.cdrom.com/.2/simtelnet/ while(buffer[3]=='-' || buffer[3]!=' ' || buffer[0]==' '); //continued message! // while(buffer[3]=='-' || buffer[0]==' '); //continued message! //!!glennmcc: end } strcpy(cache->mime,"ftp/list"); sprintf( str, "LIST"); } else { char *fnameptr; char mimestr[80]="ftp/binary"; fnameptr=strrchr(url->file,'/'); if(!fnameptr) { fnameptr=strrchr(url->file,'\\'); if(!fnameptr) fnameptr=url->file; else fnameptr++; } else fnameptr++; sprintf( str, "TYPE I"); if(fnameptr) { char ext[5]; strcpy(mimestr,"file/"); strncat(mimestr,fnameptr,70); mimestr[79]='\0'; get_extension(mimestr,ext); if(!strncmpi(ext,"TXT",3) || !strncmpi(ext,"HTM",3)) { //!!glennmcc: begin June 09, 2002 //optionally upload TXT and HTM in binary mode ptr=configvariable(&ARACHNEcfg,"UseBinaryFTP",NULL); if(!ptr || toupper(*ptr)=='N') //!!glennmcc: end sprintf( str, "TYPE A"); // ascii=1; } } strcpy(cache->mime,mimestr); sock_puts(socket,(unsigned char *)str); write(log,str,strlen(str)); write(log,"\r\n",2); sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); if ( *buffer != '2' || uploadfile) { strcat(buffer,"\n"); write(cache->handle,buffer,strlen(buffer)); } if ( *buffer != '2' ) { rv=1; goto quit; } if(!uploadfile) //!!glennmcc: Oct 17, 2007 -- fix problems with FTP servers //which interpret the leading '/' as an attempted CD to 'root' if(url->file[0]=='/') sprintf( str, "RETR %s", url->file+1); else sprintf( str, "RETR %s", url->file); //original single line above this comment //!!glennmcc: end else sprintf( str, "STOR %s", url->file); } sock_puts(socket,(unsigned char *)str); write(log,str,strlen(str)); write(log,"\r\n",2); //!!glennmcc: Oct 19, 2008 -- back to original fix //!!glennmcc: Nov 15, 2007 -- always 'close' the connection when done //with both dir listings and file downloads //Apr 10, 2007 fix did it only for dir listings if(isdir || strstr(str,"RETR")) //if(isdir) sock_puts(socket,(unsigned char *)"QUIT");//!!glennmcc: Apr 10, 2007 //!!glennmcc: end if(!retry) { //get file using datahost & dataport GlobalLogoStyle=0; //SDL set resolve animation host=resolve_fn( datahost, (sockfunct_t) TcpIdleFunc ); //SDL // host=resolve( datahost ); if(!host) goto quit; GlobalLogoStyle=2; //SDL set connect animation if (!tcp_open( &datasocket, locport(), host, dataport, NULL )) { sprintf(str,msg_errcon,datahost); outs(str); goto quit; } sprintf(str,msg_con,datahost,dataport); outs(str); write(log,str,strlen(str)); write(log,"\r\n",2); //wait for datasocket to open: sock_wait_established(&datasocket, sock_delay, (sockfunct_t) TcpIdleFunc, &status); //SDL //!!glennmcc: Sep 27, 2008 -- increase D/L speed on cable & DSL //many thanks to 'mik' for pointing me in the right direction. :) { #ifdef DEBUG char sp[80]; sprintf(sp,"Available stack = %u bytes",_SP); outs(sp); Piip(); Piip(); #endif if(_SP>(1024*SETBUFSIZE)) { char setbuf[1024*SETBUFSIZE]; sock_setbuf(&datasocket, (unsigned char *)setbuf, 1024*SETBUFSIZE); } } //!!glennmcc: end GlobalLogoStyle=1; //SDL set data animation } //wait for "110 openning connection" (or "550 ....error....") sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); write(log,buffer,strlen(buffer)); write(log,"\r\n",2); // printf("FTP daemon said>"); // puts(buffer); if ( *buffer != '1' || uploadfile) { strcat(buffer,"\n"); write(cache->handle,buffer,strlen(buffer)); } if ( *buffer != '1' ) { if(!strncmp(buffer,"550",3) && !retry) { retry=1; isdir=1-isdir; if(isdir) strcat(url->file,"/"); else { int i=strlen(url->file); if(i>0 && url->file[i-1]=='/') url->file[i-1]='\0'; } goto retry; } strcpy(cache->mime,"text/plain"); rv=1; goto dataquit; } if(!uploadfile) //-------------------------------------- download --------------- { while ( 1 ) { xChLogoTICK(1); if(GUITICK()) if(GLOBAL.gotolocation || GLOBAL.abort) goto dataquit; if (sock_dataready( &datasocket )) { len = sock_fastread( &datasocket, (unsigned char*)buffer, BUFLEN ); write(cache->handle,buffer,len); total+=len; sprintf(str,MSG_BYTESR,MSG_DOWNLD,total); outs(str); } else sock_tick( &datasocket, &status ); //shift TCP/IP } } else //-------------------------------------- upload ------------------ { int f,lenread,done; long length; char pom[256]; /* if(ascii) f=a_sopen(uploadfile,O_RDONLY|O_TEXT, SH_DENYNO, S_IREAD); else*/ f=a_sopen(uploadfile,O_RDONLY|O_BINARY, SH_DENYNO, S_IREAD); if(f<0) goto dataquit; lenread=done=0; length=0l; { long filel=a_filelength(f); while(1) { sprintf(pom,MSG_UPLOAD,length,filel); outs(pom); //!!glennmcc:Oct 23, 2008 -- 'reversed the logic' // to keep from overflowing at 21megs if(filel>100) percentbar((int)(length/(filel/100))); // percentbar((int)(100*length/filel)); lenread=a_read(f,buffer,BUFLEN); length+=lenread; if(lenread<=0) done=1; //wait until we can write to socket: while(sock_tbleft(&datasocket)<lenread) //SDL // while( datasocket.datalen > 1024) { sock_tick(&datasocket,&status); xChLogoTICK(1); // animation of logo if(GUITICK()) goto dataquit; } if(done) { sock_close( &datasocket ); a_close(f); goto dataclose; } sock_fastwrite(&datasocket,(unsigned char *)buffer,lenread); sock_tick(&datasocket,&status); }//loop } } dataquit: //!!glennmcc: Nov 15, 2007 -- removed sock_abort because it was // sometimes preventing the connection from being closed, // therefore preventing access to several files within a short time // due to too many connections open from the same IP // sock_abort( &datasocket );//original line //!!glennmcc: end dataclose: outs(MSG_CLOSE); sock_puts(socket,(unsigned char *)"QUIT");//!!glennmcc: Dec 04, 2006 sock_wait_closed( &datasocket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL if(uploadfile) { sock_wait_input( socket, sock_delay, (sockfunct_t) TcpIdleFunc, &status ); //SDL sock_gets( socket, (unsigned char *)buffer, sizeof( buffer )); outs(buffer); } quit: sock_puts(socket,(unsigned char *)"QUIT"); sock_close( socket ); closing[socknum]=1; sock_keepalive[socknum][0]='\0'; // sock_wait_closed( socket, sock_delay, NULL, &status ); //we will better wait because we are about to deallocate datasocket sock_err: switch (status) { case 1 : /* foreign host closed */ write(log,MSG_CLOSE,strlen(MSG_CLOSE)); write(log,"\r\n",2); close(log); break; case -1: /* timeout */ sprintf(str,MSG_TCPERR, sockerr(socket)); outs(str); write(log,str,strlen(str)); write(log,"\r\n",2); close(log); break; } if(total) { cache->knowsize=1; cache->size=total; rv=1; } if(cache->handle>=0) { a_close(cache->handle); rv=1; } return rv; }
static void gather_sctp(void) { struct sock *sock; struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; struct xsctp_inpcb *xinpcb; struct xsctp_tcb *xstcb; struct xsctp_raddr *xraddr; struct xsctp_laddr *xladdr; const char *varname; size_t len, offset; char *buf; int hash, vflag; int no_stcb, local_all_loopback, foreign_all_loopback; vflag = 0; if (opt_4) vflag |= INP_IPV4; if (opt_6) vflag |= INP_IPV6; varname = "net.inet.sctp.assoclist"; if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { if (errno != ENOENT) err(1, "sysctlbyname()"); return; } if ((buf = (char *)malloc(len)) == NULL) { err(1, "malloc()"); return; } if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { err(1, "sysctlbyname()"); free(buf); return; } xinpcb = (struct xsctp_inpcb *)(void *)buf; offset = sizeof(struct xsctp_inpcb); while ((offset < len) && (xinpcb->last == 0)) { if ((sock = calloc(1, sizeof *sock)) == NULL) err(1, "malloc()"); sock->socket = xinpcb->socket; sock->proto = IPPROTO_SCTP; sock->protoname = "sctp"; if (xinpcb->flags & SCTP_PCB_FLAGS_UNBOUND) sock->state = SCTP_CLOSED; else if (xinpcb->maxqlen == 0) sock->state = SCTP_BOUND; else sock->state = SCTP_LISTEN; if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { sock->family = AF_INET6; sock->vflag = INP_IPV6; } else { sock->family = AF_INET; sock->vflag = INP_IPV4; } prev_laddr = NULL; local_all_loopback = 1; while (offset < len) { xladdr = (struct xsctp_laddr *)(void *)(buf + offset); offset += sizeof(struct xsctp_laddr); if (xladdr->last == 1) break; if ((laddr = calloc(1, sizeof(struct addr))) == NULL) err(1, "malloc()"); switch (xladdr->address.sa.sa_family) { case AF_INET: #define __IN_IS_ADDR_LOOPBACK(pina) \ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) local_all_loopback = 0; #undef __IN_IS_ADDR_LOOPBACK sockaddr(&laddr->address, AF_INET, &xladdr->address.sin.sin_addr, htons(xinpcb->local_port)); break; case AF_INET6: if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) local_all_loopback = 0; sockaddr(&laddr->address, AF_INET6, &xladdr->address.sin6.sin6_addr, htons(xinpcb->local_port)); break; default: errx(1, "adress family %d not supported", xladdr->address.sa.sa_family); } laddr->next = NULL; if (prev_laddr == NULL) sock->laddr = laddr; else prev_laddr->next = laddr; prev_laddr = laddr; } if (sock->laddr == NULL) { if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) err(1, "malloc()"); sock->laddr->address.ss_family = sock->family; if (sock->family == AF_INET) sock->laddr->address.ss_len = sizeof(struct sockaddr_in); else sock->laddr->address.ss_len = sizeof(struct sockaddr_in); local_all_loopback = 0; } if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) err(1, "malloc()"); sock->faddr->address.ss_family = sock->family; if (sock->family == AF_INET) sock->faddr->address.ss_len = sizeof(struct sockaddr_in); else sock->faddr->address.ss_len = sizeof(struct sockaddr_in); no_stcb = 1; while (offset < len) { xstcb = (struct xsctp_tcb *)(void *)(buf + offset); offset += sizeof(struct xsctp_tcb); if (no_stcb) { if (opt_l && (!opt_L || !local_all_loopback) && ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || (xstcb->last == 1))) { hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; sockhash[hash] = sock; } else { free_socket(sock); } } if (xstcb->last == 1) break; no_stcb = 0; if (opt_c) { if ((sock = calloc(1, sizeof *sock)) == NULL) err(1, "malloc()"); sock->socket = xinpcb->socket; sock->proto = IPPROTO_SCTP; sock->protoname = "sctp"; sock->state = (int)xstcb->state; if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { sock->family = AF_INET6; sock->vflag = INP_IPV6; } else { sock->family = AF_INET; sock->vflag = INP_IPV4; } } prev_laddr = NULL; local_all_loopback = 1; while (offset < len) { xladdr = (struct xsctp_laddr *)(void *)(buf + offset); offset += sizeof(struct xsctp_laddr); if (xladdr->last == 1) break; if (!opt_c) continue; if ((laddr = calloc(1, sizeof(struct addr))) == NULL) err(1, "malloc()"); switch (xladdr->address.sa.sa_family) { case AF_INET: #define __IN_IS_ADDR_LOOPBACK(pina) \ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) local_all_loopback = 0; #undef __IN_IS_ADDR_LOOPBACK sockaddr(&laddr->address, AF_INET, &xladdr->address.sin.sin_addr, htons(xstcb->local_port)); break; case AF_INET6: if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) local_all_loopback = 0; sockaddr(&laddr->address, AF_INET6, &xladdr->address.sin6.sin6_addr, htons(xstcb->local_port)); break; default: errx(1, "adress family %d not supported", xladdr->address.sa.sa_family); } laddr->next = NULL; if (prev_laddr == NULL) sock->laddr = laddr; else prev_laddr->next = laddr; prev_laddr = laddr; } prev_faddr = NULL; foreign_all_loopback = 1; while (offset < len) { xraddr = (struct xsctp_raddr *)(void *)(buf + offset); offset += sizeof(struct xsctp_raddr); if (xraddr->last == 1) break; if (!opt_c) continue; if ((faddr = calloc(1, sizeof(struct addr))) == NULL) err(1, "malloc()"); switch (xraddr->address.sa.sa_family) { case AF_INET: #define __IN_IS_ADDR_LOOPBACK(pina) \ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) foreign_all_loopback = 0; #undef __IN_IS_ADDR_LOOPBACK sockaddr(&faddr->address, AF_INET, &xraddr->address.sin.sin_addr, htons(xstcb->remote_port)); break; case AF_INET6: if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) foreign_all_loopback = 0; sockaddr(&faddr->address, AF_INET6, &xraddr->address.sin6.sin6_addr, htons(xstcb->remote_port)); break; default: errx(1, "adress family %d not supported", xraddr->address.sa.sa_family); } faddr->next = NULL; if (prev_faddr == NULL) sock->faddr = faddr; else prev_faddr->next = faddr; prev_faddr = faddr; } if (opt_c) { if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; sockhash[hash] = sock; } else { free_socket(sock); } } } xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); offset += sizeof(struct xsctp_inpcb); } free(buf); }