Example #1
0
void echo_discard_start (void)
{
#if defined(USE_DEBUG)
  char buf[100], ip1[20], ip2[20];
  sprintf (buf, "echo-daemon %s, %s/%u, discard-daemon %s, %s/%u\r\n\r\n",
           do_echo ? "yes" : "no", _inet_ntoa(ip1,echo_host), echo_port,
           do_disc ? "yes" : "no", _inet_ntoa(ip2,disc_host), disc_port);
  dbug_write_raw (buf);
#endif

  if (do_echo)
  {
    udp_listen (&udp_echo_sock, echo_host, echo_port, 0,
                (ProtoHandler)udp_handler);
    udp_echo_sock.sockmode |= UDP_MODE_NOCHK;
    tcp_listen (&tcp_echo_sock, echo_host, echo_port, 0, NULL, 0);
  }

  if (do_disc)
  {
    udp_listen (&udp_disc_sock, disc_host, disc_port, 0,
                (ProtoHandler)udp_handler);
    udp_disc_sock.sockmode |= UDP_MODE_NOCHK;
    tcp_listen (&tcp_disc_sock, disc_host, disc_port, 0, NULL, 0);
  }

  if (do_echo || do_disc)
     addwattcpd (echo_discard_daemon);
}
Example #2
0
void 
pppLinkStatusCallback(void *ctx, int errCode, void *arg)
{
    switch(errCode) {
    case PPPERR_NONE:               /* No error. */
        {
        struct ppp_addrs *ppp_addrs = arg;

        printf("pppLinkStatusCallback: PPPERR_NONE");
        printf(" our_ipaddr=%s", _inet_ntoa(ppp_addrs->our_ipaddr.addr));
        printf(" his_ipaddr=%s", _inet_ntoa(ppp_addrs->his_ipaddr.addr));
        printf(" netmask=%s", _inet_ntoa(ppp_addrs->netmask.addr));
        printf(" dns1=%s", _inet_ntoa(ppp_addrs->dns1.addr));
        printf(" dns2=%s\n", _inet_ntoa(ppp_addrs->dns2.addr));
        }
        break;

    case PPPERR_PARAM:             /* Invalid parameter. */
        printf("pppLinkStatusCallback: PPPERR_PARAM\n");
        break;

    case PPPERR_OPEN:              /* Unable to open PPP session. */
        printf("pppLinkStatusCallback: PPPERR_OPEN\n");
        break;

    case PPPERR_DEVICE:            /* Invalid I/O device for PPP. */
        printf("pppLinkStatusCallback: PPPERR_DEVICE\n");
        break;

    case PPPERR_ALLOC:             /* Unable to allocate resources. */
        printf("pppLinkStatusCallback: PPPERR_ALLOC\n");
        break;

    case PPPERR_USER:              /* User interrupt. */
        printf("pppLinkStatusCallback: PPPERR_USER\n");
        break;

    case PPPERR_CONNECT:           /* Connection lost. */
        printf("pppLinkStatusCallback: PPPERR_CONNECT\n");
        break;

    case PPPERR_AUTHFAIL:          /* Failed authentication challenge. */
        printf("pppLinkStatusCallback: PPPERR_AUTHFAIL\n");
        break;

    case PPPERR_PROTOCOL:          /* Failed to meet protocol. */
        printf("pppLinkStatusCallback: PPPERR_PROTOCOL\n");
        break;

    default:
        printf("pppLinkStatusCallback: unknown errCode %d\n", errCode);
        break;
    }
}
Example #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.
			}
		}
	}
}
Example #4
0
/**
 * Handle ICMP_REDIRECT messages.
 */
static void icmp_redirect (const union ICMP_PKT *icmp, const in_Header *ip,
                           const in_Header *orig_ip, int code)
{
  DWORD new_ip = intel (icmp->ip.ipaddr);
  DWORD old_ip = intel (orig_ip->destination);
  const char *msg;

  if (new_ip == old_ip)
  {
    /* Possibly because we and router use different netmasks
     */
  }
  else if ((new_ip ^ my_ip_addr) & sin_mask) /* new host not on subnet */
  {
    char buf[100];

    strcpy (buf, ", GW = ");
    strcat (buf, _inet_ntoa(NULL,new_ip));
    icmp_bogus (ip, ICMP_REDIRECT, buf);
    return;
  }

  msg = icmp_redirect_str[code];
  icmp_print (1, msg, ip->source);

  switch (orig_ip->proto)
  {
#if !defined(USE_UDP_ONLY)
    case TCP_PROTO:
         if (do_redirect.tcp)  /* do it to some socket */
            _tcp_cancel (orig_ip, ICMP_REDIRECT, code, msg, &new_ip);
         break;
#endif
    case UDP_PROTO:
         if (do_redirect.udp)
            _udp_cancel (orig_ip, ICMP_REDIRECT, code, msg, &new_ip);
         break;

    case ICMP_PROTO:
         if (do_redirect.icmp)
         {
        /* _ip_recursion = TRUE; !! */
           _arp_register (new_ip, old_ip);
        /* _ip_recursion = FALSE; !! */
         }
         break;

    case IGMP_PROTO:
         if (do_redirect.igmp)
         {
        /* _ip_recursion = TRUE; !! */
           _arp_register (new_ip, old_ip);
        /* _ip_recursion = FALSE; !! */
         }
         break;
  }
}
Example #5
0
void psocket (const sock_type *s)
{
  char buf[20];

  (*_outch) ('[');
  outs (_inet_ntoa(buf, s->tcp.hisaddr));
  (*_outch) (':');
  itoa (s->tcp.hisport, buf, 10);
  outs (buf);
  (*_outch) (']');
}
Example #6
0
static void icmp_print (int dbg_lvl, const char *msg, DWORD src)
{
  if (debug_on < dbg_lvl)
     return;

  outs ("\nICMP: ");
  if (src)
  {
    outs ("(");
    outs (_inet_ntoa(NULL,intel(src)));
    outs ("): ");
  }
  outsnl (_LANG(msg));
}
Example #7
0
static inline void sniff_loop_ip(session_t *s, int len, const u_char *packet) {
	const struct iphdr *ip;
	int size_ip;

	CHECK_LEN(sizeof(struct iphdr))			ip = (struct iphdr *) (packet);
	size_ip = ip->ip_hl*4;
	
	if (size_ip < 20) {
		debug_error("sniff_loop_ip()   * Invalid IP header length: %u bytes\n", size_ip);
		return;
	}
	
	if (ip->ip_p == IPPROTO_TCP)
		sniff_loop_tcp(s, len - size_ip, packet + size_ip, ip, size_ip);
	else if (ip->ip_p == IPPROTO_UDP) 
		sniff_loop_udp(s, len - size_ip, packet + size_ip, ip);
	else if (ip->ip_p == IPPROTO_ICMP) {	/* ICMP, stub only */
		const struct icmphdr *icmp;

		CHECK_LEN(size_ip + sizeof(struct icmphdr));	icmp = (struct icmphdr *) (packet + size_ip);

		debug_function("sniff_loop_ip() IP/ICMP %15s <==> %15s TYPE: %d CODE: %d CHKSUM: %d\n",
				_inet_ntoa(ip->ip_src),		/* src ip */
				_inet_ntoa(ip->ip_dst),		/* dest ip */
				icmp->icmp_type,
				icmp->icmp_code,
				icmp->icmp_cksum);
		/* XXX */
	} else {
		/* other, implement if u want to || die. */
		debug_error("sniff_loop_ip() IP/0x%x %15s <==> %15s\n",
				ip->ip_p,			/* protocol */
				_inet_ntoa(ip->ip_src),		/* src ip */
				_inet_ntoa(ip->ip_dst));	/* dest ip */

	}
}
Example #8
0
static inline void sniff_loop_udp(session_t *s, int len, const u_char *packet, const struct iphdr *ip) {
#define	RIVCHAT_PACKET_LEN 328
	static const char rivchat_magic[11] = { 'R', 'i', 'v', 'C', 'h', 'a', 't' /* here NULs */};	/* RivChat\0\0\0\0 */

	/* XXX here, make some struct with known UDP services, and demangler-function */
	const struct udphdr *udp;
	connection_t *hdr;

	const char *payload;
	int size_payload;

	/* XXX, it's enough? */
	/* code copied from: http://gpsbots.com/tutorials/sniff_packets.php */
	CHECK_LEN(sizeof(struct udphdr));	udp = (struct udphdr *) (packet);

	hdr = sniff_udp_get(ip, udp);

	payload = (char *) (packet + sizeof(struct udphdr));
	size_payload = g_ntohs(udp->th_len)-sizeof(struct udphdr);

	CHECK_LEN(sizeof(struct udphdr) + size_payload);

	debug_error("sniff_loop_udp() IP/UDP %15s:%5d <==> %15s:%5d\n",
			_inet_ntoa(hdr->srcip),		/* src ip */
			hdr->srcport,			/* src port */
			_inet_ntoa(hdr->dstip),		/* dest ip */
			hdr->dstport);			/* dest port */

	if (size_payload == RIVCHAT_PACKET_LEN && !memcmp(payload, rivchat_magic, sizeof(rivchat_magic))) {		/* RIVCHAT	[check based on header (11b), ~100% hit] */
		sniff_rivchat(s, hdr, (rivchat_packet *) payload, size_payload);
	} else if (hdr->srcport == 53 || hdr->dstport == 53) {								/* DNS		[check based on port, ~80% hit] */
		sniff_dns(s, hdr, (DNS_HEADER *) payload, size_payload);
	} else {													/* OTHER PROTOs, feel free */
		debug_error("NOT RIVCHAT/ NOT DNS:\n");
		tcp_print_payload((u_char *) payload, size_payload);
	}
}
Example #9
0
File: inet_ntop.c Project: 8l/FUZIX
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
	if (af != AF_INET) {
		errno = EAFNOSUPPORT;
		return NULL;
	}
	if (size < 18) {
		errno = ENOSPC;
		return NULL;
	}
	/* This isn't strictly correct because it means we are not
	   re-entrant. Really we need to rework _itoa() to have a re-entrant
	   base form, then rework inet_ntoa to use inet_ntop FIXME */
	return strcpy(dst, _inet_ntoa(*(uint32_t *)src));
}
Example #10
0
/*
 * This functiom is called once each second.
 */
static void check_dead_gw (void)
{
  char   buf[20];
  static int i = 0;

  if (i >= gate_top)
      i = 0;

  for ( ; i < gate_top; i++)
  {
    struct gate_entry *gw = &gate_list [i];
    eth_address        eth;

    if (!is_on_LAN(gw->gate_ip))
       continue;

    if (!LAN_lookup(gw->gate_ip,&eth))
       continue;

    if (gw->chk_timer == 0UL || !chk_timeout(gw->chk_timer))
    {
      gw->chk_timer = set_timeout (DEAD_GW_TIMEOUT);
      continue;
    }

    if (gw->echo_pending &&
        _chk_ping(gw->gate_ip,NULL) == (DWORD)-1)
    {
      gw->is_dead      = TRUE;
      gw->echo_pending = FALSE;
      TCP_CONSOLE_MSG (1, ("Dead default GW %s (%d) detected\n",
                       _inet_ntoa(NULL,gw->gate_ip), i));
    }

    if (ping_gateway (gw->gate_ip, eth))
       gw->echo_pending = TRUE;

    gw->chk_timer = set_timeout (DEAD_GW_TIMEOUT);
    return;  /* only one ping per interval */
  }
}
Example #11
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 );
}
Example #12
0
static inline void sniff_loop_tcp(session_t *s, int len, const u_char *packet, const struct iphdr *ip, int size_ip) {
	/* XXX here, make some struct with known TCP services, and demangler-function */
	const struct tcphdr *tcp;
	int size_tcp;
	connection_t *hdr;

	const char *payload;
	int size_payload;

	CHECK_LEN(sizeof(struct tcphdr))	tcp = (struct tcphdr*) (packet);
	size_tcp = TH_OFF(tcp)*4;

	if (size_tcp < 20) {
		debug_error("sniff_loop_tcp()	* Invalid TCP header length: %u bytes\n", size_tcp);
		return;
	}

	size_payload = g_ntohs(ip->ip_len) - (size_ip + size_tcp);

	CHECK_LEN(size_tcp + size_payload);

	payload = (char *) (packet + size_tcp);

	hdr = sniff_tcp_find_connection(ip, tcp);

	debug_function("sniff_loop_tcp() IP/TCP %15s:%5d <==> %15s:%5d %s (SEQ: %lx ACK: %lx len: %d)\n", 
			_inet_ntoa(hdr->srcip),		/* src ip */
			hdr->srcport,			/* src port */
			_inet_ntoa(hdr->dstip),		/* dest ip */
			hdr->dstport,			/* dest port */
			tcp_print_flags(tcp->th_flags), /* tcp flags */
			g_htonl(tcp->th_seq),		/* seq */
			g_htonl(tcp->th_ack),		/* ack */
			size_payload);			/* payload len */

	/* XXX check tcp flags */
	if (!size_payload) return;

	/* XXX what proto ? check based on ip + port? */

	if (hdr->dstport == 80 || hdr->srcport == 80) {		/* HTTP		[basic check on magic values, ~80% hit] */
		static const char http_magic11[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ' };	/* HTTP/1.1 */
		static const char http_magic10[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '0', ' ' };	/* HTTP/1.0 */

		static const char http_get_magic[] = { 'G', 'E', 'T', ' ' };				/* GET */
		static const char http_post_magic[] = { 'P', 'O', 'S', 'T', ' ' };			/* POST */

		/* SERVER REPLIES: */

		if (	(size_payload > sizeof(http_magic10) && !memcmp(payload, http_magic10, sizeof(http_magic10))) ||
				(size_payload > sizeof(http_magic11) && !memcmp(payload, http_magic11, sizeof(http_magic11)))
		   ) {
//				debug_error("HTTP DATA FOLLOW\n");
//				tcp_print_payload((u_char *) payload, size_payload);

			return;		/* done */
		}


		/* CLIENT REQUESTs: */

		if (	(size_payload > sizeof(http_get_magic) && !memcmp(payload, http_get_magic, sizeof(http_get_magic))) ||
				(size_payload > sizeof(http_post_magic) && !memcmp(payload, http_post_magic, sizeof(http_post_magic)))

		   ) {
//				debug_error("HTTP DATA FOLLOW?\n");
//				tcp_print_payload((u_char *) payload, size_payload);

			return;		/* done */
		}
	}

	sniff_gg(s, hdr, (gg_header *) payload, size_payload);		/* GG		[no check, ~3% hit] */
}
Example #13
0
/*
 *  Handler for incoming ICMP packets
 */
void icmp_handler (const in_Header *ip, BOOL broadcast)
{
  union icmp_pkt *icmp;
  in_Header      *orig_ip;
  int             len, type, code;
  BOOL            for_me, i_orig;  /* is it for me, did I originate it */
  const char     *msg;

  DEBUG_RX (NULL, ip);

  if (block_icmp)   /* application is handling ICMP; not needed */
     return;

  len    = in_GetHdrLen (ip);
  icmp   = (union icmp_pkt*) ((BYTE*)ip + len);
  len    = intel16 (ip->length) - len;
  for_me = (DWORD) (intel(ip->destination) - my_ip_addr) <= multihomes;

  if (!for_me || broadcast)  /* drop broadcast pings.. */
     return;

  if (len < sizeof(icmp->info))
  {
    STAT (icmpstats.icps_tooshort++);
    return;
  }

  if (checksum(icmp,len) != 0xFFFF)
  {
    STAT (icmpstats.icps_checksum++);
    icmp_print (1, _LANG("bad checksum"), ip->source);
    return;
  }

  type    = icmp->unused.type;
  code    = icmp->unused.code;
  orig_ip = &icmp->ip.ip;
  i_orig  = is_local_addr (intel(orig_ip->source));

  if (type == ICMP_MASKREPLY)
  {
    if (!_domask_req)
       return;
    i_orig = TRUE;
  }

  /* !! this needs work
   */
  if (!i_orig &&
      (type != ICMP_ECHOREPLY && type != ICMP_ECHO &&
       type != ICMP_IREQREPLY && type != ICMP_TSTAMP))
  {
    icmp_bogus (ip, type, NULL);
    return;
  }

  switch (type)
  {
    case ICMP_ECHOREPLY:  /* check if we were waiting for it */
         STAT (icmpstats.icps_inhist[ICMP_ECHOREPLY]++);
         ping_hcache = intel (ip->source);
         ping_tcache = set_timeout (1000) - *(DWORD*)&icmp->echo.identifier;
         if (ping_tcache > 0x7FFFFFFFL)
             ping_tcache += 0x1800B0L;
         ping_number = *(DWORD*)(((BYTE*)&icmp->echo.identifier) + 4);
         return;

    case ICMP_UNREACH:
         STAT (icmpstats.icps_inhist[ICMP_UNREACH]++);
         if (code < DIM(icmp_unreach_str))
         {
           icmp_print (1, msg = icmp_unreach_str[code], ip->source);
#if !defined(USE_UDP_ONLY)
           if (orig_ip->proto == TCP_PROTO)
              _tcp_cancel (orig_ip, type, msg, 0);
           else
#endif
           if (orig_ip->proto == UDP_PROTO)
              _udp_cancel (orig_ip, type, msg, 0);
         }
         else
           STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_SOURCEQUENCH:
         STAT (icmpstats.icps_inhist[ICMP_SOURCEQUENCH]++);
#if !defined(USE_UDP_ONLY)
         if (orig_ip->proto == TCP_PROTO)
         {
           icmp_print (1, _LANG("Source Quench"), ip->source);
           _tcp_cancel (orig_ip, type, NULL, 0);
         }
#endif
         return;

    case ICMP_REDIRECT:
         STAT (icmpstats.icps_inhist[ICMP_REDIRECT]++);
         if (code < 4)
         {
           DWORD new_gw = intel (icmp->ip.ipaddr);

           /* Check if new gateway is on our subnet
            */
           if ((new_gw ^ my_ip_addr) & sin_mask)
           {
             char buf[100], adr[20];
             strcpy (buf, ", GW = ");
             strcat (buf, _inet_ntoa(adr,new_gw));
             icmp_bogus (ip, type, buf);
             return;
           }
           icmp_print (1, msg = icmp_redirect_str[code], ip->source);

           switch (orig_ip->proto)
           {
#if !defined(USE_UDP_ONLY)
             case TCP_PROTO:
                  if (do_redirect.tcp)  /* do it to some socket */
                     _tcp_cancel (orig_ip, type, msg, new_gw);
                  break;
#endif
             case UDP_PROTO:
                  if (do_redirect.udp)
                     _udp_cancel (orig_ip, type, msg, new_gw);
                  break;

             case ICMP_PROTO:
                  if (do_redirect.icmp)
                  {
                    _ip_recursion = 1;
                    _arp_register (new_gw, intel(orig_ip->destination), 0);
                    _ip_recursion = 0;
                  }
                  break;

             case IGMP_PROTO:
                  if (do_redirect.igmp)
                  {
                    _ip_recursion = 1;
                    _arp_register (new_gw, intel(orig_ip->destination), 0);
                    _ip_recursion = 0;
                  }
                  break;
           }
         }
         else
           STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_ECHO:
         STAT (icmpstats.icps_inhist[ICMP_ECHO]++);
         icmp_print (2, _LANG("PING requested of us"), ip->source);
         {
           /* Extract eth-address and create Echo reply packet.
            */
           struct _pkt     *pkt;
           union  icmp_pkt *newicmp;

           if (!icmp_chk_src(ip,ICMP_ECHO))
              return;

           pkt     = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE);
           newicmp = &pkt->icmp;

           /* Don't let a huge reassembled ICMP-packet kill us.
            */
           len = min (len, mtu - sizeof(*ip));
           memcpy (newicmp, icmp, len);
           newicmp->echo.type = ICMP_ECHOREPLY;
           newicmp->echo.code = code;

           /* Use supplied ip values in case we ever multi-home.
            * Note that ip values are still in network order.
            */
           icmp_send (pkt, ip->destination, ip->source, len);
           icmp_print (2, _LANG("PING reply sent"), 0);
         }
         return;

    case ICMP_TIMXCEED:
         if (code >= DIM(icmp_exceed_str))
         {
           STAT (icmpstats.icps_badcode++);
           return;
         }
         STAT (icmpstats.icps_inhist[ICMP_TIMXCEED]++);

         if (code != 1)
            switch (orig_ip->proto)
            {
#if !defined(USE_UDP_ONLY)
              case TCP_PROTO:
                   icmp_print (1, icmp_exceed_str[code], ip->source);
                   _tcp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0);
                   break;
#endif
              case UDP_PROTO:
                   icmp_print (1, icmp_exceed_str[code], ip->source);
                   _udp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0);
                   break;
            }
         return;

    case ICMP_PARAMPROB:
         STAT (icmpstats.icps_inhist[ICMP_PARAMPROB]++);
         switch (orig_ip->proto)
         {
#if !defined(USE_UDP_ONLY)
           case TCP_PROTO:
                icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
                _tcp_cancel (orig_ip, type, NULL, 0);
                break;
#endif
           case UDP_PROTO:
                icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
                _udp_cancel (orig_ip, type, NULL, 0);
                break;
         }
         return;

    case ICMP_ROUTERADVERT:  /* todo !! */
         STAT (icmpstats.icps_inhist[ICMP_ROUTERADVERT]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         return;

    case ICMP_ROUTERSOLICIT: /* todo !! */
         STAT (icmpstats.icps_inhist[ICMP_ROUTERSOLICIT]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         return;

    case ICMP_TSTAMP:
         STAT (icmpstats.icps_inhist[ICMP_TSTAMP]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply? */
         return;

    case ICMP_TSTAMPREPLY:
         STAT (icmpstats.icps_inhist[ICMP_TSTAMPREPLY]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, should store */
         return;

    case ICMP_IREQ:
         STAT (icmpstats.icps_inhist[ICMP_IREQ]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply */
         return;

    case ICMP_IREQREPLY:
         STAT (icmpstats.icps_inhist[ICMP_IREQREPLY]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply upwards */
         return;

    case ICMP_MASKREQ:
         STAT (icmpstats.icps_inhist[ICMP_MASKREQ]++);
         break;

    case ICMP_MASKREPLY:
         STAT (icmpstats.icps_inhist[ICMP_MASKREPLY]++);
         icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
         if ((icmp->mask.identifier == addr_mask_id)    &&
             (icmp->mask.sequence   == addr_mask_seq-1) &&
             sin_mask != intel(icmp->mask.mask))
            outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7");
         addr_mask_id = 0;
         return;
  }
}