/* ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net This code is covered by the GNU GPL licence */ #pragma once #if defined(ACTIVEGS_ANDROID) // not tester yet! #define NO_MARINETTI_SUPPORT #endif #ifndef NO_MARINETTI_SUPPORT #ifdef WIN32 #include #include #include #pragma comment(lib, "Ws2_32.lib") #else #include #include #include #include #include #include #include #endif #endif // NO MARINETTI SUPPORT #define MAX_TCP_QUEUE 32 #define MAX_ETH_QUEUE 64 #define MAX_TCP_SIZE 2048 #define MAX_UDP_SIZE 2048 #define MTU 1500 #define TCPIP_ERR_NO_DEVICE 1 // No network device found #define TCPIP_ERR_NO_CONNECTION 2 // Unable to connect to network device #define TCPIP_ERR_STARTUP_FAILED 3 // Unable to initiate network access #define TCPIP_ERR_UNSUPPORTED 4 // An unsupported operation was attempted #define TCPIP_ERR_MEMORY 5 // Unable to allocate buffer memory #define TCPIP_ERR_SEND 6 // Error sending packet extern void marinetti_init(); extern void marinetti_shutdown(); #ifndef NO_MARINETTI_SUPPORT // helpers typedef unsigned short u16; typedef unsigned long u32; #pragma pack(push) #pragma pack(1) #ifdef WIN32 #define SockLastError() WSAGetLastError() #define SockClose(X) if (X>=0) { closesocket(X); printf("\n sock %d closed\n",X); X=-1; } #else #define SockLastError() -1 #define SockClose(X) if (X>=0) { close(X); X=-1; } #define SOCKET_ERROR -1 #endif #define _LOG(...) do {} while(0) #ifndef _DEBUG #undef printf #define printf(...) do {} while(0) #endif enum enum_response_type { RT_NA=0, RT_UDP=100, RT_ARP=101, RT_DHCP=102, RT_DNS=103, RT_TCP=104 }; // ETH/IP/UDP/ARP/TCP/DHCP HEADER #define dhcpdiscover 1 #define dhcpoffer 2 #define dhcprequest 3 #define dhcpdecline 4 #define dhcppack 5 #define dhcpnack 6 #define dhcprelease 7 #define dhcpinform 8 // DNS STRUCT typedef in_addr IP_STRUCT; #ifdef WIN32 #define GET_INT_FROM_IP(X) X.S_un.S_addr #else #define GET_INT_FROM_IP(X) X.s_addr #endif struct MAC_STRUCT { byte addr[6]; MAC_STRUCT& operator=(const byte* _ptr) { memcpy(addr,_ptr,6); return *this; }; void SetFromIP(IP_STRUCT _ip) { memset(addr,0x88,6); *(int*)&addr[0]=GET_INT_FROM_IP(_ip); }; } ; #define IP_SET(i,d,c,b,a) GET_INT_FROM_IP(i) = ((a << 24) + (b << 16) + (c << 8) + d) #define MAC_SET(m,a,b,c,d,e,f) m.addr[0]=a;m.addr[1]=b;m.addr[2]=c;m.addr[3]=d;m.addr[4]=e;m.addr[5]=f; typedef struct { MAC_STRUCT dest_mac; MAC_STRUCT source_mac; unsigned short int type; } ETH_HEADER; #define FLAG_MF 0x2000 #define GET_OFFSET(X) ((X & 0x1FFF)*8) typedef struct { unsigned char ihl:4; unsigned char ver:4; unsigned char tos; unsigned short int length; unsigned short int identification; unsigned short int flag_offset; // unsigned short int offset:13; unsigned char ttl; unsigned char protocol; unsigned short int checksum; IP_STRUCT ucSource; IP_STRUCT ucDestination; } IP_HEADER; #define DHCP_SNAME_LEN 64 #define DHCP_FILE_LEN 128 #define DHCP_FIXED_NON_UDP 236 #define DHCP_OPTION_LEN 1500 typedef struct { byte op; /* 0: Message opcode/type */ byte htype; /* 1: Hardware addr type (net/if_types.h) */ byte hlen; /* 2: Hardware addr length */ byte hops; /* 3: Number of relay agent hops from client */ u32 xid; /* 4: Transaction ID */ u16 secs; /* 8: Seconds since client started looking */ u16 flags; /* 10: Flag bits */ IP_STRUCT ciaddr; /* 12: Client IP address (if already in use) */ IP_STRUCT yiaddr; /* 16: Client IP address */ IP_STRUCT siaddr; /* 18: IP address of next server to talk to */ IP_STRUCT giaddr; /* 20: DHCP relay agent IP address */ unsigned char chaddr [16]; /* 24: Client hardware address */ char sname [DHCP_SNAME_LEN]; /* 40: Server name */ char file [DHCP_FILE_LEN]; /* 104: Boot filename */ unsigned char options [DHCP_OPTION_LEN]; /* 212: Optional parameters (actual length dependent on MTU). */ } DHCP_HEADER; typedef struct { unsigned short src_port; unsigned short dest_port; unsigned int seq_number; unsigned int ack_number; unsigned char padding1:4; unsigned char data_offset:4; unsigned char flags; #define TCP_FIN (1 << 0) #define TCP_SYN (1 << 1) #define TCP_RST (1 << 2) #define TCP_PSH (1 << 3) #define TCP_ACK (1 << 4) #define TCP_URG (1 << 5) unsigned short window; unsigned short checksum; unsigned short urgent_pointer; unsigned int options; } TCP_HEADER; typedef struct { u16 udp_src; u16 udp_dst; u16 udp_len; u16 udp_chk; } UDP_HEADER; typedef struct { unsigned short id; // identification number unsigned char rd :1; // recursion desired unsigned char tc :1; // truncated message unsigned char aa :1; // authoritive answer unsigned char opcode :4; // purpose of message unsigned char qr :1; // query/response flag unsigned char rcode :4; // response code unsigned char cd :1; // checking disabled unsigned char ad :1; // authenticated data unsigned char z :1; // its z! reserved unsigned char ra :1; // recursion available unsigned short q_count; // number of question entries unsigned short ans_count; // number of answer entries unsigned short auth_count; // number of authority entries unsigned short add_count; // number of resource entries } DNS_HEADER; typedef struct { unsigned short qtype; unsigned short qclass; } QUESTION; typedef struct { unsigned short type; unsigned short _class; unsigned int ttl; unsigned short data_len; } R_DATA; typedef struct { char name[256]; R_DATA *resource; char rdata[256]; } RES_RECORD; typedef struct { char name[256]; QUESTION *ques; } QUERY; #define TCPIP_CMD_STARTUP 1 // Initializes the network module #define TCPIP_CMD_GET_DATAGRAM 2 // Called by GS to get a datagram from the network // XXXXYYYY = pointer to buffer to receive datagram #define TCPIP_CMD_SEND_DATAGRAM 3 // Called by GS to send a datagram // XXXXYYYY = pointer to parameters: // LONG pointer to data // WORD datagram length in bytes #define TCPIP_CMD_CONNECT 4 // Connects to the network #define TCPIP_CMD_DISCONNECT 5 // Disconnects from the network #define TCPIP_CMD_SHUTDOWN 6 // Shuts down the network support #define TCPIP_SET_IP_ADDRESS 7 // Pass in XXXXYYYY a pointerto the // six byte MAC address of the LL #define TCPIP_GETIPADDRESS 9 // returns the Macs IP Address in X and Y // if IP Address could not be obtained will return 0 u16 ip_sum_calc(u16 len_ip_header,const byte* _buf); u16 udp_sum_calc(u16 proto,u16 len_udp, const byte* src_addr,const byte* dest_addr, const byte* buff); int dns_readname(const byte* reader,const byte* buffer,char outname[] ); extern IP_STRUCT client_ip_addr; extern MAC_STRUCT client_mac_addr; extern MAC_STRUCT gateway_mac_addr; extern IP_STRUCT gateway_dns_addr; extern const MAC_STRUCT broadcast_mac_addr; extern IP_STRUCT local_ip_addr; extern IP_STRUCT host_ip_addr; struct tcp_queue; enum PConnectionState { PCS_INITIALIZED=300, PCS_SYNSENT, PCS_SYNCHING, PCS_BEINGESTABLISHED, PCS_ESTABLISHED, PCS_CLOSING, PCS_CLEARINGQUEUE, PCS_LASTACK, PCS_CLOSED }; enum PConnectionType { PCT_SERVER, PCT_CLIENT, PCT_HOST }; struct PConnection { int type; // UDP, TCP, //ARP int dest_port; int source_port; IP_STRUCT dest_ip; MAC_STRUCT dest_mac; int window; int already_sent; int send_seq; int last_ack; int state_seq; int tcpsocket; enum PConnectionState state; enum PConnectionType socktype; PConnection(); ~PConnection(); void Reset(); tcp_queue* sendtcppacket(int _flags, int len, byte* data); int sendudppacket(int len,const byte* data); }; struct ARP_HEADER { u16 hwaddr_format; // Ethernet, Token Ring, etc u16 protoaddr_format; // Same as Ether Type field byte hwaddr_length; // Lenght of hardware address byte protoaddr_length; // Length of protocol address u16 opcode; // Request or Response MAC_STRUCT src_hwaddr; IP_STRUCT src_protoaddr; MAC_STRUCT dst_hwaddr; IP_STRUCT dst_protoaddr; }; #define MAX_TCP_CONNECTION 100 extern PConnection PConnections[MAX_TCP_CONNECTION]; PConnection* init_connection( enum PConnectionType _socktype,int _type,int _srcport,IP_STRUCT _destip, int _destport, MAC_STRUCT _destmac, int _window); void reset_connection( enum PConnectionType _socktype,int _type, int _srcport,IP_STRUCT _destip, int _destport); PConnection* find_connection( enum PConnectionType _socktype,int _type, int _srcport,IP_STRUCT _destip, int _destport); enum QUEUE_STATE { QS_TOSEND=1000, QS_TOSENDANDRETRY, QS_SENT, QS_WAITACK, QS_IDLE, QS_FRAGMENT }; struct eth_queue { // ne rien avoir ici! struct { ETH_HEADER eth; union { ARP_HEADER arp; IP_HEADER ip; byte padding[MTU]; }; }; int queuelen; void print(); }; #define ETH_MAX_SIZE ((MTU - sizeof(ETH_HEADER) - sizeof(IP_HEADER))&~7) struct tcp_queue { int queuelen; int queueseq; double timeout; int tcplen; // taille des donnée tcp int iplen; // taille du packet ip défragmenté enum QUEUE_STATE state; PConnection* connection; struct { ETH_HEADER eth; IP_HEADER ip; union { UDP_HEADER udp; TCP_HEADER tcp; byte padding[16384]; }; }; void print(); void Reset() { state=QS_IDLE; }; int isDNS() { return (GET_INT_FROM_IP(gateway_dns_addr)== GET_INT_FROM_IP(this->ip.ucDestination)) || (GET_INT_FROM_IP(gateway_dns_addr)== GET_INT_FROM_IP(this->ip.ucSource)) ; }; int isDHCP() { if ( ip.protocol == 17 // UDP && ntohs(udp.udp_dst) == 67 && !memcmp(eth.dest_mac.addr, broadcast_mac_addr.addr,6) ) return 1; else return 0; }; int check_tcp(); }; eth_queue* findETHQueue(); extern eth_queue ethqueues[MAX_ETH_QUEUE]; tcp_queue* findTCPQueue(); tcp_queue* findTCPQueueByFragment(eth_queue* q); extern tcp_queue tcpqueues[MAX_TCP_QUEUE]; void print_ip(const IP_STRUCT p); void print_mac(const MAC_STRUCT mac); void print_dns(const byte* _ptr); void print_udp(const UDP_HEADER *p); void print_arp(const ARP_HEADER * p); void print_tcp(TCP_HEADER* p); void print_dhcp(const byte *); void print_ip_packet( const IP_HEADER* _header); int init_server(void); void server_loop(void); int add_fragment(eth_queue* p); int process_unfragmented(tcp_queue* p); void reset_fragments(); #pragma pack(pop) #endif