Пример #1
0
/* 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;
}
Пример #2
0
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);
}
Пример #3
0
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.
			}
		}
	}
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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);
}
Пример #8
0
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();
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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);
}
Пример #15
0
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 );
}
Пример #16
0
/* 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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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 );
}
Пример #22
0
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 );
}
Пример #23
0
void appe_tcp_server_quit(AppeSocket *sock)
{
    assert(sock != NULL);

    free_socket(sock);
}
Пример #24
0
static void free_socket_callback (VOID_STAR cd)
{
   free_socket ((Socket_Type *)cd);
}
Пример #25
0
/*
	- 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;
}
Пример #26
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;
}
Пример #27
0
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;
}
Пример #28
0
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;
}
Пример #29
0
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);
}