added stio_checksumip(), stio_iphdr_t, stio_icmphdr_t
This commit is contained in:
		
							
								
								
									
										309
									
								
								stio/lib/main.c
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								stio/lib/main.c
									
									
									
									
									
								
							@ -40,6 +40,8 @@
 | 
			
		||||
#include <netpacket/packet.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL)
 | 
			
		||||
#	include <openssl/ssl.h>
 | 
			
		||||
#	if defined(HAVE_OPENSSL_ERR_H)
 | 
			
		||||
@ -126,11 +128,11 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp)
 | 
			
		||||
	switch (STIO_DEV_SCK_GET_PROGRESS(tcp))
 | 
			
		||||
	{
 | 
			
		||||
		case STIO_DEV_SCK_CONNECTING:
 | 
			
		||||
			printf ("OUTGOING TCP DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck);
 | 
			
		||||
			printf ("OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case STIO_DEV_SCK_CONNECTING_SSL:
 | 
			
		||||
			printf ("OUTGOING TCP DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck);
 | 
			
		||||
			printf ("OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case STIO_DEV_SCK_LISTENING:
 | 
			
		||||
@ -150,7 +152,7 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			printf ("TCP DISCONNECTED - THIS MUST NOT HAPPEN (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state);
 | 
			
		||||
			printf ("SOCKET DEVICE DISCONNECTED (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state);
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -203,6 +205,8 @@ else
 | 
			
		||||
 | 
			
		||||
printf ("ENABLING READING..............................\n");
 | 
			
		||||
	stio_dev_sck_read (tcp, 1);
 | 
			
		||||
 | 
			
		||||
	//stio_dev_sck_timedread (tcp, 1, 1000);
 | 
			
		||||
}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -237,12 +241,14 @@ free (xxx);
 | 
			
		||||
	if (n <= -1) return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
printf ("DISABLING READING..............................\n");
 | 
			
		||||
	stio_dev_sck_read (tcp, 0);
 | 
			
		||||
 | 
			
		||||
	/* post the write finisher */
 | 
			
		||||
	n = stio_dev_sck_write  (tcp, STIO_NULL, 0, STIO_NULL, STIO_NULL);
 | 
			
		||||
	if (n <= -1) return -1;
 | 
			
		||||
 | 
			
		||||
printf ("DISABLING READING..............................\n");
 | 
			
		||||
	stio_dev_sck_read (tcp, 0);
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
/* return 1; let the main loop to read more greedily without consulting the multiplexer */
 | 
			
		||||
@ -250,6 +256,26 @@ printf ("DISABLING READING..............................\n");
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
static void pro_on_close (stio_dev_pro_t* dev, stio_dev_pro_sid_t sid)
 | 
			
		||||
{
 | 
			
		||||
printf (">>>>>>>>>>>>> ON CLOSE OF SLAVE %d.\n", sid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pro_on_read (stio_dev_pro_t* dev, const void* data, stio_iolen_t dlen, stio_dev_pro_sid_t sid)
 | 
			
		||||
{
 | 
			
		||||
printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int pro_on_write (stio_dev_pro_t* dev, stio_iolen_t wrlen, void* wrctx)
 | 
			
		||||
{
 | 
			
		||||
printf ("PROCESS WROTE DATA...\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckaddr_t* srcaddr)
 | 
			
		||||
{
 | 
			
		||||
	stio_etharp_pkt_t* eap;
 | 
			
		||||
@ -272,26 +298,232 @@ static int arp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrct
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arp_sck_on_disconnect (stio_dev_sck_t* dev)
 | 
			
		||||
{
 | 
			
		||||
printf ("SHUTTING DOWN ARP SOCKET %d...\n", dev->sck);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int setup_arp_tester (stio_t* stio)
 | 
			
		||||
{
 | 
			
		||||
	stio_sckaddr_t ethdst;
 | 
			
		||||
	stio_etharp_pkt_t etharp;
 | 
			
		||||
	stio_dev_sck_make_t sck_make;
 | 
			
		||||
	stio_dev_sck_t* sck;
 | 
			
		||||
 | 
			
		||||
	memset (&sck_make, 0, STIO_SIZEOF(sck_make));
 | 
			
		||||
	sck_make.type = STIO_DEV_SCK_ARP;
 | 
			
		||||
	//sck_make.type = STIO_DEV_SCK_ARP_DGRAM;
 | 
			
		||||
	sck_make.on_write = arp_sck_on_write;
 | 
			
		||||
	sck_make.on_read = arp_sck_on_read;
 | 
			
		||||
	sck_make.on_disconnect = arp_sck_on_disconnect;
 | 
			
		||||
	sck = stio_dev_sck_make (stio, 0, &sck_make);
 | 
			
		||||
	if (!sck)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("Cannot make socket device\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
 | 
			
		||||
	stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
 | 
			
		||||
 | 
			
		||||
	memset (ðarp, 0, sizeof(etharp));
 | 
			
		||||
 | 
			
		||||
	memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
 | 
			
		||||
	//memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADDR_LEN);
 | 
			
		||||
	memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADDR_LEN);
 | 
			
		||||
	etharp.ethhdr.proto = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP);
 | 
			
		||||
 | 
			
		||||
	etharp.arphdr.htype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH);
 | 
			
		||||
	etharp.arphdr.ptype = STIO_CONST_HTON16(STIO_ARPHDR_PTYPE_IP4);
 | 
			
		||||
	etharp.arphdr.hlen = STIO_ETHADDR_LEN;
 | 
			
		||||
	etharp.arphdr.plen = STIO_IP4ADDR_LEN;
 | 
			
		||||
	etharp.arphdr.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST);
 | 
			
		||||
 | 
			
		||||
	memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
 | 
			
		||||
 | 
			
		||||
	if (stio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, ðdst) <= -1)
 | 
			
		||||
	//if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("CANNOT WRITE ARP...\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
static void pro_on_close (stio_dev_pro_t* dev, stio_dev_pro_sid_t sid)
 | 
			
		||||
struct icmpxtn_t
 | 
			
		||||
{
 | 
			
		||||
printf (">>>>>>>>>>>>> ON CLOSE OF SLAVE %d.\n", sid);
 | 
			
		||||
	stio_uint16_t icmp_seq;
 | 
			
		||||
	stio_tmridx_t tmout_jobidx;
 | 
			
		||||
	int reply_received;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct icmpxtn_t icmpxtn_t;
 | 
			
		||||
 | 
			
		||||
static int schedule_icmp_wait (stio_dev_sck_t* dev);
 | 
			
		||||
 | 
			
		||||
static void send_icmp (stio_dev_sck_t* dev, stio_uint16_t seq)
 | 
			
		||||
{
 | 
			
		||||
	stio_sckaddr_t dstaddr;
 | 
			
		||||
	stio_ip4addr_t ia;
 | 
			
		||||
	stio_icmphdr_t* icmphdr;
 | 
			
		||||
	stio_uint8_t buf[512];
 | 
			
		||||
 | 
			
		||||
	inet_pton (AF_INET, "192.168.1.131", &ia);
 | 
			
		||||
	stio_sckaddr_initforip4 (&dstaddr, 0, &ia);
 | 
			
		||||
 | 
			
		||||
	memset(buf, 0, STIO_SIZEOF(buf));
 | 
			
		||||
	icmphdr = (stio_icmphdr_t*)buf;
 | 
			
		||||
	icmphdr->type = STIO_ICMP_ECHO_REQUEST;
 | 
			
		||||
	icmphdr->u.echo.id = STIO_CONST_HTON16(100);
 | 
			
		||||
	icmphdr->u.echo.seq = stio_hton16(seq);
 | 
			
		||||
 | 
			
		||||
	memset (&buf[STIO_SIZEOF(*icmphdr)], 'A', STIO_SIZEOF(buf) - STIO_SIZEOF(*icmphdr));
 | 
			
		||||
	icmphdr->checksum = stio_checksumip (icmphdr, STIO_SIZEOF(buf));
 | 
			
		||||
 | 
			
		||||
	if (stio_dev_sck_write (dev, buf, STIO_SIZEOF(buf), NULL, &dstaddr) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("CANNOT WRITE ICMP...\n");
 | 
			
		||||
		stio_dev_sck_halt (dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (schedule_icmp_wait (dev) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("CANNOT SCHEDULE ICMP WAIT...\n");
 | 
			
		||||
		stio_dev_sck_halt (dev);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pro_on_read (stio_dev_pro_t* dev, const void* data, stio_iolen_t dlen, stio_dev_pro_sid_t sid)
 | 
			
		||||
static void on_icmp_due (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* tmrjob)
 | 
			
		||||
{
 | 
			
		||||
printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data);
 | 
			
		||||
	stio_dev_sck_t* dev;
 | 
			
		||||
	icmpxtn_t* icmpxtn;
 | 
			
		||||
 | 
			
		||||
	dev = tmrjob->ctx;
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(dev + 1);
 | 
			
		||||
 | 
			
		||||
	if (icmpxtn->reply_received)
 | 
			
		||||
		icmpxtn->reply_received = 0;
 | 
			
		||||
	else
 | 
			
		||||
		printf ("NO ICMP REPLY RECEIVED....\n");
 | 
			
		||||
 | 
			
		||||
	send_icmp (dev, ++icmpxtn->icmp_seq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int schedule_icmp_wait (stio_dev_sck_t* dev)
 | 
			
		||||
{
 | 
			
		||||
	icmpxtn_t* icmpxtn;
 | 
			
		||||
	stio_tmrjob_t tmrjob;
 | 
			
		||||
	stio_ntime_t fire_after;
 | 
			
		||||
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(dev + 1);
 | 
			
		||||
	stio_inittime (&fire_after, 2, 0);
 | 
			
		||||
 | 
			
		||||
	memset (&tmrjob, 0, STIO_SIZEOF(tmrjob));
 | 
			
		||||
	tmrjob.ctx = dev;
 | 
			
		||||
	stio_gettime (&tmrjob.when);
 | 
			
		||||
	stio_addtime (&tmrjob.when, &fire_after, &tmrjob.when);
 | 
			
		||||
	tmrjob.handler = on_icmp_due;
 | 
			
		||||
	tmrjob.idxptr = &icmpxtn->tmout_jobidx;
 | 
			
		||||
 | 
			
		||||
	assert (icmpxtn->tmout_jobidx == STIO_TMRIDX_INVALID);
 | 
			
		||||
 | 
			
		||||
	return (stio_instmrjob (dev->stio, &tmrjob) == STIO_TMRIDX_INVALID)? -1: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int icmp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckaddr_t* srcaddr)
 | 
			
		||||
{
 | 
			
		||||
	icmpxtn_t* icmpxtn;
 | 
			
		||||
	stio_iphdr_t* iphdr;
 | 
			
		||||
	stio_icmphdr_t* icmphdr;
 | 
			
		||||
 | 
			
		||||
	/* when received, the data contains the IP header.. */
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(dev + 1);
 | 
			
		||||
 | 
			
		||||
	if (dlen < STIO_SIZEOF(*iphdr) + STIO_SIZEOF(*icmphdr))
 | 
			
		||||
	{
 | 
			
		||||
		printf ("INVALID ICMP PACKET.. TOO SHORT...%d\n", (int)dlen);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* TODO: consider IP options... */
 | 
			
		||||
		iphdr = (stio_iphdr_t*)data;
 | 
			
		||||
		icmphdr = (stio_icmphdr_t*)((stio_uint8_t*)data + (iphdr->ihl * 4));
 | 
			
		||||
 | 
			
		||||
		/* TODO": check srcaddr against target */
 | 
			
		||||
 | 
			
		||||
		if (icmphdr->type == STIO_ICMP_ECHO_REPLY && 
 | 
			
		||||
		    stio_ntoh16(icmphdr->u.echo.seq) == icmpxtn->icmp_seq) /* TODO: more check.. echo.id.. */
 | 
			
		||||
		{
 | 
			
		||||
			icmpxtn->reply_received = 1;
 | 
			
		||||
			printf ("ICMP REPLY RECEIVED...ID %d SEQ %d\n", (int)stio_ntoh16(icmphdr->u.echo.id), (int)stio_ntoh16(icmphdr->u.echo.seq));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			printf ("GARBAGE ICMP PACKET...LEN %d SEQ %d,%d\n", (int)dlen, (int)icmpxtn->icmp_seq, (int)stio_ntoh16(icmphdr->u.echo.seq));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int pro_on_write (stio_dev_pro_t* dev, stio_iolen_t wrlen, void* wrctx)
 | 
			
		||||
static int icmp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_sckaddr_t* dstaddr)
 | 
			
		||||
{
 | 
			
		||||
printf ("PROCESS WROTE DATA...\n");
 | 
			
		||||
	/*icmpxtn_t* icmpxtn;
 | 
			
		||||
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(dev + 1); */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void icmp_sck_on_disconnect (stio_dev_sck_t* dev)
 | 
			
		||||
{
 | 
			
		||||
	icmpxtn_t* icmpxtn;
 | 
			
		||||
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(dev + 1);
 | 
			
		||||
 | 
			
		||||
printf ("SHUTTING DOWN ICMP SOCKET %d...\n", dev->sck);
 | 
			
		||||
	if (icmpxtn->tmout_jobidx != STIO_TMRIDX_INVALID)
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		stio_deltmrjob (dev->stio, icmpxtn->tmout_jobidx);
 | 
			
		||||
		icmpxtn->tmout_jobidx = STIO_TMRIDX_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int setup_ping4_tester (stio_t* stio)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_sck_make_t sck_make;
 | 
			
		||||
	stio_dev_sck_t* sck;
 | 
			
		||||
	icmpxtn_t* icmpxtn;
 | 
			
		||||
 | 
			
		||||
	memset (&sck_make, 0, STIO_SIZEOF(sck_make));
 | 
			
		||||
	sck_make.type = STIO_DEV_SCK_ICMP4;
 | 
			
		||||
	sck_make.on_write = icmp_sck_on_write;
 | 
			
		||||
	sck_make.on_read = icmp_sck_on_read;
 | 
			
		||||
	sck_make.on_disconnect = icmp_sck_on_disconnect;
 | 
			
		||||
 | 
			
		||||
	sck = stio_dev_sck_make (stio, STIO_SIZEOF(icmpxtn_t), &sck_make);
 | 
			
		||||
	if (!sck)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("Cannot make ICMP4 socket device\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	icmpxtn = (icmpxtn_t*)(sck + 1);
 | 
			
		||||
	icmpxtn->tmout_jobidx = STIO_TMRIDX_INVALID;
 | 
			
		||||
	icmpxtn->icmp_seq = 0;
 | 
			
		||||
 | 
			
		||||
	/*TODO: stio_dev_sck_setbroadcast (sck, 1);*/
 | 
			
		||||
 | 
			
		||||
	send_icmp (sck, ++icmpxtn->icmp_seq);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
static stio_t* g_stio;
 | 
			
		||||
@ -306,7 +538,6 @@ int main ()
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	stio_t* stio;
 | 
			
		||||
	stio_dev_sck_t* sck;
 | 
			
		||||
	stio_dev_sck_t* tcp[3];
 | 
			
		||||
 | 
			
		||||
	struct sigaction sigact;
 | 
			
		||||
@ -314,8 +545,7 @@ int main ()
 | 
			
		||||
	stio_dev_sck_listen_t tcp_lstn;
 | 
			
		||||
	stio_dev_sck_bind_t tcp_bind;
 | 
			
		||||
	stio_dev_sck_make_t tcp_make;
 | 
			
		||||
	
 | 
			
		||||
	stio_dev_sck_make_t sck_make;
 | 
			
		||||
 | 
			
		||||
	tcp_server_t* ts;
 | 
			
		||||
 | 
			
		||||
#if defined(USE_SSL)
 | 
			
		||||
@ -363,6 +593,7 @@ int main ()
 | 
			
		||||
	tcp_make.type = STIO_DEV_SCK_TCP4;
 | 
			
		||||
	tcp_make.on_write = tcp_sck_on_write;
 | 
			
		||||
	tcp_make.on_read = tcp_sck_on_read;
 | 
			
		||||
	tcp_make.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
	tcp[0] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
 | 
			
		||||
	if (!tcp[0])
 | 
			
		||||
	{
 | 
			
		||||
@ -382,7 +613,6 @@ int main ()
 | 
			
		||||
 | 
			
		||||
	stio_inittime (&tcp_conn.connect_tmout, 5, 0);
 | 
			
		||||
	tcp_conn.on_connect = tcp_sck_on_connect;
 | 
			
		||||
	tcp_conn.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
	tcp_conn.options = STIO_DEV_SCK_CONNECT_SSL;
 | 
			
		||||
	if (stio_dev_sck_connect (tcp[0], &tcp_conn) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
@ -395,7 +625,7 @@ int main ()
 | 
			
		||||
	tcp_make.type = STIO_DEV_SCK_TCP4;
 | 
			
		||||
	tcp_make.on_write = tcp_sck_on_write;
 | 
			
		||||
	tcp_make.on_read = tcp_sck_on_read;
 | 
			
		||||
 | 
			
		||||
	tcp_make.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
 | 
			
		||||
	tcp[1] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
 | 
			
		||||
	if (!tcp[1])
 | 
			
		||||
@ -419,7 +649,6 @@ int main ()
 | 
			
		||||
 | 
			
		||||
	tcp_lstn.backlogs = 100;
 | 
			
		||||
	tcp_lstn.on_connect = tcp_sck_on_connect;
 | 
			
		||||
	tcp_lstn.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
	if (stio_dev_sck_listen (tcp[1], &tcp_lstn) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("stio_dev_sck_listen() failed....\n");
 | 
			
		||||
@ -431,6 +660,7 @@ int main ()
 | 
			
		||||
	tcp_make.type = STIO_DEV_SCK_TCP4;
 | 
			
		||||
	tcp_make.on_write = tcp_sck_on_write;
 | 
			
		||||
	tcp_make.on_read = tcp_sck_on_read;
 | 
			
		||||
	tcp_make.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
 | 
			
		||||
	tcp[2] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
 | 
			
		||||
	if (!tcp[2])
 | 
			
		||||
@ -456,7 +686,6 @@ int main ()
 | 
			
		||||
 | 
			
		||||
	tcp_lstn.backlogs = 100;
 | 
			
		||||
	tcp_lstn.on_connect = tcp_sck_on_connect;
 | 
			
		||||
	tcp_lstn.on_disconnect = tcp_sck_on_disconnect;
 | 
			
		||||
	if (stio_dev_sck_listen (tcp[2], &tcp_lstn) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("stio_dev_sck_listen() failed....\n");
 | 
			
		||||
@ -464,49 +693,9 @@ int main ()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//stio_dev_sck_sendfile (tcp[2], fd, offset, count);
 | 
			
		||||
#if 1
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	stio_sckaddr_t ethdst;
 | 
			
		||||
	stio_etharp_pkt_t etharp;
 | 
			
		||||
 | 
			
		||||
	memset (&sck_make, 0, STIO_SIZEOF(sck_make));
 | 
			
		||||
	sck_make.type = STIO_DEV_SCK_ARP;
 | 
			
		||||
	//sck_make.type = STIO_DEV_SCK_ARP_DGRAM;
 | 
			
		||||
	sck_make.on_write = arp_sck_on_write;
 | 
			
		||||
	sck_make.on_read = arp_sck_on_read;
 | 
			
		||||
	sck = stio_dev_sck_make (stio, 0, &sck_make);
 | 
			
		||||
	if (!sck)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("Cannot make socket device\n");
 | 
			
		||||
		goto oops;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
 | 
			
		||||
	stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
 | 
			
		||||
 | 
			
		||||
	memset (ðarp, 0, sizeof(etharp));
 | 
			
		||||
 | 
			
		||||
	memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
 | 
			
		||||
	//memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADDR_LEN);
 | 
			
		||||
	memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADDR_LEN);
 | 
			
		||||
	etharp.ethhdr.proto = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP);
 | 
			
		||||
 | 
			
		||||
	etharp.arphdr.htype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH);
 | 
			
		||||
	etharp.arphdr.ptype = STIO_CONST_HTON16(STIO_ARPHDR_PTYPE_IP4);
 | 
			
		||||
	etharp.arphdr.hlen = STIO_ETHADDR_LEN;
 | 
			
		||||
	etharp.arphdr.plen = STIO_IP4ADDR_LEN;
 | 
			
		||||
	etharp.arphdr.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST);
 | 
			
		||||
 | 
			
		||||
	memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
 | 
			
		||||
 | 
			
		||||
	if (stio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, ðdst) <= -1)
 | 
			
		||||
	//if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("CANNOT WRITE ARP...\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
	if (setup_arp_tester(stio) <= -1) goto oops;
 | 
			
		||||
	if (setup_ping4_tester(stio) <= -1) goto oops;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for (i = 0; i < 5; i++)
 | 
			
		||||
 | 
			
		||||
@ -40,17 +40,6 @@
 | 
			
		||||
#define STIO_MEMCMP(dst,src,count) memcmp(dst,src,count)
 | 
			
		||||
#define STIO_ASSERT assert
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct stio_tmrjob_t
 | 
			
		||||
{
 | 
			
		||||
	void*                  ctx;
 | 
			
		||||
	stio_ntime_t           when;
 | 
			
		||||
	stio_tmrjob_handler_t  handler;
 | 
			
		||||
	stio_tmridx_t*         idxptr; /* pointer to the index holder */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1)
 | 
			
		||||
 | 
			
		||||
typedef struct stio_mux_t stio_mux_t;
 | 
			
		||||
 | 
			
		||||
struct stio_t
 | 
			
		||||
 | 
			
		||||
@ -116,7 +116,6 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
 | 
			
		||||
		return STIO_SCKHND_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return sck;
 | 
			
		||||
@ -249,15 +248,29 @@ struct sck_type_map_t
 | 
			
		||||
 | 
			
		||||
static struct sck_type_map_t sck_type_map[] =
 | 
			
		||||
{
 | 
			
		||||
	/* STIO_DEV_SCK_TCP4 */
 | 
			
		||||
	{ AF_INET,    SOCK_STREAM,    0,                         STIO_DEV_CAPA_STREAM  | STIO_DEV_CAPA_OUT_QUEUED },
 | 
			
		||||
 | 
			
		||||
	/* STIO_DEV_SCK_TCP6 */
 | 
			
		||||
	{ AF_INET6,   SOCK_STREAM,    0,                         STIO_DEV_CAPA_STREAM  | STIO_DEV_CAPA_OUT_QUEUED },
 | 
			
		||||
 | 
			
		||||
	/* STIO_DEV_SCK_UPD4 */
 | 
			
		||||
	{ AF_INET,    SOCK_DGRAM,     0,                         0                                                },
 | 
			
		||||
 | 
			
		||||
	/* STIO_DEV_SCK_UDP6 */
 | 
			
		||||
	{ AF_INET6,   SOCK_DGRAM,     0,                         0                                                },
 | 
			
		||||
 | 
			
		||||
	{ AF_PACKET,  SOCK_RAW,       STIO_CONST_HTON16(0x0806), 0                                                },
 | 
			
		||||
	{ AF_PACKET,  SOCK_DGRAM,     STIO_CONST_HTON16(0x0806), 0                                                },
 | 
			
		||||
	/* STIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */
 | 
			
		||||
	{ AF_PACKET,  SOCK_RAW,       STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP), 0                                 },
 | 
			
		||||
 | 
			
		||||
	{ AF_INET,    SOCK_RAW,       IPPROTO_ICMP,              0,                                               }
 | 
			
		||||
	/* STIO_DEV_SCK_DGRAM */
 | 
			
		||||
	{ AF_PACKET,  SOCK_DGRAM,     STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP), 0                                 },
 | 
			
		||||
 | 
			
		||||
	/* STIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */
 | 
			
		||||
	{ AF_INET,    SOCK_RAW,       IPPROTO_ICMP,              0,                                               },
 | 
			
		||||
 | 
			
		||||
	/* STIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */
 | 
			
		||||
	{ AF_INET6,   SOCK_RAW,       IPPROTO_ICMP,              0,                                               }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ======================================================================== */
 | 
			
		||||
@ -346,6 +359,7 @@ static int dev_sck_make (stio_dev_t* dev, void* ctx)
 | 
			
		||||
	rdev->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | sck_type_map[arg->type].extra_dev_capa;
 | 
			
		||||
	rdev->on_write = arg->on_write;
 | 
			
		||||
	rdev->on_read = arg->on_read;
 | 
			
		||||
	rdev->on_disconnect = arg->on_disconnect;
 | 
			
		||||
	rdev->type = arg->type;
 | 
			
		||||
	rdev->tmrjob_index = STIO_TMRIDX_INVALID;
 | 
			
		||||
 | 
			
		||||
@ -365,7 +379,7 @@ static int dev_sck_make_client (stio_dev_t* dev, void* ctx)
 | 
			
		||||
	stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
			
		||||
	stio_syshnd_t* sck = (stio_syshnd_t*)ctx;
 | 
			
		||||
 | 
			
		||||
	/* nothing special is done here except setting the socket handle.
 | 
			
		||||
	/* nothing special is done here except setting the sock et handle.
 | 
			
		||||
	 * most of the initialization is done by the listening socket device
 | 
			
		||||
	 * after a client socket has been created. */
 | 
			
		||||
 | 
			
		||||
@ -393,12 +407,12 @@ static int dev_sck_kill (stio_dev_t* dev, int force)
 | 
			
		||||
 | 
			
		||||
	if (IS_STATEFUL(rdev))
 | 
			
		||||
	{
 | 
			
		||||
		if (STIO_DEV_SCK_GET_PROGRESS(rdev))
 | 
			
		||||
		{
 | 
			
		||||
		/*if (STIO_DEV_SCK_GET_PROGRESS(rdev))
 | 
			
		||||
		{*/
 | 
			
		||||
			/* for STIO_DEV_SCK_CONNECTING, STIO_DEV_SCK_CONNECTING_SSL, and STIO_DEV_ACCEPTING_SSL
 | 
			
		||||
			 * on_disconnect() is called without corresponding on_connect() */
 | 
			
		||||
			if (rdev->on_disconnect) rdev->on_disconnect (rdev);
 | 
			
		||||
		}
 | 
			
		||||
		/*}*/
 | 
			
		||||
 | 
			
		||||
		if (rdev->tmrjob_index != STIO_TMRIDX_INVALID)
 | 
			
		||||
		{
 | 
			
		||||
@ -410,6 +424,8 @@ static int dev_sck_kill (stio_dev_t* dev, int force)
 | 
			
		||||
	{
 | 
			
		||||
		STIO_ASSERT (rdev->state == 0);
 | 
			
		||||
		STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
 | 
			
		||||
 | 
			
		||||
		if (rdev->on_disconnect) rdev->on_disconnect (rdev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if defined(USE_SSL)
 | 
			
		||||
@ -533,8 +549,6 @@ static int dev_sck_write_stateful (stio_dev_t* dev, const void* data, stio_iolen
 | 
			
		||||
		{
 | 
			
		||||
			int err = SSL_get_error ((SSL*)rdev->ssl, x);
 | 
			
		||||
			if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0;
 | 
			
		||||
			/*else if (err == SSL_ERROR_SYSCALL)
 | 
			
		||||
				rdev->stio->errnum = stio_syserrtoerrnum(errno); */
 | 
			
		||||
			rdev->stio->errnum = STIO_ESYSERR;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
@ -932,7 +946,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
 | 
			
		||||
 | 
			
		||||
						rdev->remoteaddr = conn->remoteaddr;
 | 
			
		||||
						rdev->on_connect = conn->on_connect;
 | 
			
		||||
						rdev->on_disconnect = conn->on_disconnect;
 | 
			
		||||
					#if defined(USE_SSL)
 | 
			
		||||
						rdev->ssl_ctx = ssl_ctx;
 | 
			
		||||
					#endif
 | 
			
		||||
@ -960,7 +973,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
 | 
			
		||||
				/* connected immediately */
 | 
			
		||||
				rdev->remoteaddr = conn->remoteaddr;
 | 
			
		||||
				rdev->on_connect = conn->on_connect;
 | 
			
		||||
				rdev->on_disconnect = conn->on_disconnect;
 | 
			
		||||
 | 
			
		||||
				sl = STIO_SIZEOF(localaddr);
 | 
			
		||||
				if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = localaddr;
 | 
			
		||||
@ -1055,7 +1067,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
 | 
			
		||||
 | 
			
		||||
			STIO_DEV_SCK_SET_PROGRESS (rdev, STIO_DEV_SCK_LISTENING);
 | 
			
		||||
			rdev->on_connect = lstn->on_connect;
 | 
			
		||||
			rdev->on_disconnect = lstn->on_disconnect;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -1598,3 +1609,29 @@ int stio_dev_sck_timedwrite (stio_dev_sck_t* dev, const void* data, stio_iolen_t
 | 
			
		||||
	stio_devaddr_t devaddr;
 | 
			
		||||
	return stio_dev_timedwrite ((stio_dev_t*)dev, data, dlen, tmout, wrctx, sckaddr_to_devaddr(dev, dstaddr, &devaddr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
stio_uint16_t stio_checksumip (const void* hdr, stio_size_t len)
 | 
			
		||||
{
 | 
			
		||||
	stio_uint32_t sum = 0;
 | 
			
		||||
	stio_uint16_t *ptr = (stio_uint16_t*)hdr;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	while (len > 1)
 | 
			
		||||
	{
 | 
			
		||||
		sum += *ptr++;
 | 
			
		||||
		if (sum & 0x80000000)
 | 
			
		||||
		sum = (sum & 0xFFFF) + (sum >> 16);
 | 
			
		||||
		len -= 2;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
	while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16);
 | 
			
		||||
 | 
			
		||||
	return (stio_uint16_t)~sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,188 @@
 | 
			
		||||
 | 
			
		||||
#include <stio.h>
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
/* TOOD: move these to a separte file */
 | 
			
		||||
 | 
			
		||||
#define STIO_ETHHDR_PROTO_IP4   0x0800
 | 
			
		||||
#define STIO_ETHHDR_PROTO_ARP   0x0806
 | 
			
		||||
#define STIO_ETHHDR_PROTO_8021Q 0x8100 /* 802.1Q VLAN */
 | 
			
		||||
#define STIO_ETHHDR_PROTO_IP6   0x86DD
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define STIO_ARPHDR_OPCODE_REQUEST 1
 | 
			
		||||
#define STIO_ARPHDR_OPCODE_REPLY   2
 | 
			
		||||
 | 
			
		||||
#define STIO_ARPHDR_HTYPE_ETH 0x0001
 | 
			
		||||
#define STIO_ARPHDR_PTYPE_IP4 0x0800
 | 
			
		||||
 | 
			
		||||
#define STIO_ETHADDR_LEN 6
 | 
			
		||||
#define STIO_IP4ADDR_LEN 4
 | 
			
		||||
#define STIO_IP6ADDR_LEN 16 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
#	define STIO_PACKED __attribute__((__packed__))
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#	define STIO_PACKED 
 | 
			
		||||
#	STIO_PACK_PUSH pack(push)
 | 
			
		||||
#	STIO_PACK_PUSH pack(push)
 | 
			
		||||
#	STIO_PACK(x) pack(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
	/* nothing */
 | 
			
		||||
#else
 | 
			
		||||
	#pragma pack(push)
 | 
			
		||||
	#pragma pack(1)
 | 
			
		||||
#endif
 | 
			
		||||
struct STIO_PACKED stio_ethaddr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_ETHADDR_LEN]; 
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ethaddr_t stio_ethaddr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ip4addr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_IP4ADDR_LEN];
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ip4addr_t stio_ip4addr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ip6addr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_IP6ADDR_LEN]; 
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ip6addr_t stio_ip6addr_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ethhdr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t  dest[STIO_ETHADDR_LEN];
 | 
			
		||||
	stio_uint8_t  source[STIO_ETHADDR_LEN];
 | 
			
		||||
	stio_uint16_t proto;
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ethhdr_t stio_ethhdr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_arphdr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint16_t htype;   /* hardware type (ethernet: 0x0001) */
 | 
			
		||||
	stio_uint16_t ptype;   /* protocol type (ipv4: 0x0800) */
 | 
			
		||||
	stio_uint8_t  hlen;    /* hardware address length (ethernet: 6) */
 | 
			
		||||
	stio_uint8_t  plen;    /* protocol address length (ipv4 :4) */
 | 
			
		||||
	stio_uint16_t opcode;  /* operation code */
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_arphdr_t stio_arphdr_t;
 | 
			
		||||
 | 
			
		||||
/* arp payload for ipv4 over ethernet */
 | 
			
		||||
struct STIO_PACKED stio_etharp_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t sha[STIO_ETHADDR_LEN];   /* source hardware address */
 | 
			
		||||
	stio_uint8_t spa[STIO_IP4ADDR_LEN];   /* source protocol address */
 | 
			
		||||
	stio_uint8_t tha[STIO_ETHADDR_LEN];   /* target hardware address */
 | 
			
		||||
	stio_uint8_t tpa[STIO_IP4ADDR_LEN];   /* target protocol address */
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_etharp_t stio_etharp_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_etharp_pkt_t
 | 
			
		||||
{
 | 
			
		||||
	stio_ethhdr_t ethhdr;
 | 
			
		||||
	stio_arphdr_t arphdr;
 | 
			
		||||
	stio_etharp_t arppld;
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_etharp_pkt_t stio_etharp_pkt_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct stio_iphdr_t
 | 
			
		||||
{
 | 
			
		||||
#if defined(STIO_ENDIAN_LITTLE)
 | 
			
		||||
	stio_uint8_t ihl:4;
 | 
			
		||||
	stio_uint8_t version:4;
 | 
			
		||||
#elif defined(STIO_ENDIAN_BIG)
 | 
			
		||||
	stio_uint8_t version:4;
 | 
			
		||||
	stio_uint8_t ihl:4;
 | 
			
		||||
#else
 | 
			
		||||
#	UNSUPPORTED ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
	stio_int8_t tos;
 | 
			
		||||
	stio_int16_t tot_len;
 | 
			
		||||
	stio_int16_t id;
 | 
			
		||||
	stio_int16_t frag_off;
 | 
			
		||||
	stio_int8_t ttl;
 | 
			
		||||
	stio_int8_t protocol;
 | 
			
		||||
	stio_int16_t check;
 | 
			
		||||
	stio_int32_t saddr;
 | 
			
		||||
	stio_int32_t daddr;
 | 
			
		||||
	/*The options start here. */
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_iphdr_t stio_iphdr_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_icmphdr_t 
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t type; /* message type */
 | 
			
		||||
	stio_uint8_t code; /* subcode */
 | 
			
		||||
	stio_uint16_t checksum;
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
		struct
 | 
			
		||||
		{
 | 
			
		||||
			stio_uint16_t id;
 | 
			
		||||
			stio_uint16_t seq;
 | 
			
		||||
		} echo;
 | 
			
		||||
 | 
			
		||||
		stio_uint32_t gateway;
 | 
			
		||||
 | 
			
		||||
		struct
 | 
			
		||||
		{
 | 
			
		||||
			stio_uint16_t frag_unused;
 | 
			
		||||
			stio_uint16_t mtu;
 | 
			
		||||
		} frag; /* path mut discovery */
 | 
			
		||||
	} u;
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_icmphdr_t stio_icmphdr_t;
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
	/* nothing */
 | 
			
		||||
#else
 | 
			
		||||
	#pragma pack(pop)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ICMP types */
 | 
			
		||||
#define STIO_ICMP_ECHO_REPLY        0
 | 
			
		||||
#define STIO_ICMP_UNREACH           3 /* destination unreachable */
 | 
			
		||||
#define STIO_ICMP_SOURCE_QUENCE     4
 | 
			
		||||
#define STIO_ICMP_REDIRECT          5
 | 
			
		||||
#define STIO_ICMP_ECHO_REQUEST      8
 | 
			
		||||
#define STIO_ICMP_TIME_EXCEEDED     11
 | 
			
		||||
#define STIO_ICMP_PARAM_PROBLEM     12
 | 
			
		||||
#define STIO_ICMP_TIMESTAMP_REQUEST 13
 | 
			
		||||
#define STIO_ICMP_TIMESTAMP_REPLY   14
 | 
			
		||||
#define STIO_ICMP_INFO_REQUEST      15
 | 
			
		||||
#define STIO_ICMP_INFO_REPLY        16
 | 
			
		||||
#define STIO_ICMP_ADDR_MASK_REQUEST 17
 | 
			
		||||
#define STIO_ICMP_ADDR_MASK_REPLY   18
 | 
			
		||||
 | 
			
		||||
/* Subcode for STIO_ICMP_UNREACH */
 | 
			
		||||
#define STIO_ICMP_UNREACH_NET          0
 | 
			
		||||
#define STIO_ICMP_UNREACH_HOST         1
 | 
			
		||||
#define STIO_ICMP_UNREACH_PROTOCOL     2
 | 
			
		||||
#define STIO_ICMP_UNREACH_PORT         3
 | 
			
		||||
#define STIO_ICMP_UNREACH_FRAG_NEEDED  4
 | 
			
		||||
 | 
			
		||||
/* Subcode for STIO_ICMP_REDIRECT */
 | 
			
		||||
#define STIO_ICMP_REDIRECT_NET      0
 | 
			
		||||
#define STIO_ICMP_REDIRECT_HOST     1
 | 
			
		||||
#define STIO_ICMP_REDIRECT_NETTOS   2
 | 
			
		||||
#define STIO_ICMP_REDIRECT_HOSTTOS  3
 | 
			
		||||
 | 
			
		||||
/* Subcode for STIO_ICMP_TIME_EXCEEDED */
 | 
			
		||||
#define STIO_ICMP_TIME_EXCEEDED_TTL       0
 | 
			
		||||
#define STIO_ICMP_TIME_EXCEEDED_FRAGTIME  1
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
typedef int stio_sckfam_t;
 | 
			
		||||
 | 
			
		||||
struct stio_sckaddr_t
 | 
			
		||||
@ -72,11 +254,6 @@ typedef struct stio_sckaddr_t stio_sckaddr_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define STIO_SCK_ETH_PROTO_IP4   0x0800 
 | 
			
		||||
#define STIO_SCK_ETH_PROTO_ARP   0x0806
 | 
			
		||||
#define STIO_SCK_ETH_PROTO_8021Q 0x8100 /* 802.1Q VLAN */
 | 
			
		||||
#define STIO_SCK_ETH_PROTO_IP6   0x86DD
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
enum stio_dev_sck_ioctl_cmd_t
 | 
			
		||||
@ -127,6 +304,7 @@ typedef int (*stio_dev_sck_on_read_t) (
 | 
			
		||||
	stio_iolen_t          dlen,
 | 
			
		||||
	const stio_sckaddr_t* srcaddr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
typedef int (*stio_dev_sck_on_write_t) (
 | 
			
		||||
	stio_dev_sck_t*       dev,
 | 
			
		||||
	stio_iolen_t          wrlen,
 | 
			
		||||
@ -134,8 +312,13 @@ typedef int (*stio_dev_sck_on_write_t) (
 | 
			
		||||
	const stio_sckaddr_t* dstaddr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
typedef int (*stio_dev_sck_on_connect_t) (stio_dev_sck_t* dev);
 | 
			
		||||
typedef void (*stio_dev_sck_on_disconnect_t) (stio_dev_sck_t* dev);
 | 
			
		||||
typedef void (*stio_dev_sck_on_disconnect_t) (
 | 
			
		||||
	stio_dev_sck_t* dev
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
typedef int (*stio_dev_sck_on_connect_t) (
 | 
			
		||||
	stio_dev_sck_t* dev
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
enum stio_dev_sck_type_t
 | 
			
		||||
{
 | 
			
		||||
@ -144,10 +327,15 @@ enum stio_dev_sck_type_t
 | 
			
		||||
	STIO_DEV_SCK_UPD4,
 | 
			
		||||
	STIO_DEV_SCK_UDP6,
 | 
			
		||||
 | 
			
		||||
	/* ARP at the ethernet layer */
 | 
			
		||||
	STIO_DEV_SCK_ARP,
 | 
			
		||||
	STIO_DEV_SCK_ARP_DGRAM,
 | 
			
		||||
 | 
			
		||||
	STIO_DEV_SCK_ICMP4
 | 
			
		||||
	/* ICMP at the IPv4 layer */
 | 
			
		||||
	STIO_DEV_SCK_ICMP4,
 | 
			
		||||
 | 
			
		||||
	/* ICMP at the IPv6 layer */
 | 
			
		||||
	STIO_DEV_SCK_ICMP6
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	STIO_DEV_SCK_RAW,  /* raw L2-level packet */
 | 
			
		||||
@ -161,6 +349,7 @@ struct stio_dev_sck_make_t
 | 
			
		||||
	stio_dev_sck_type_t type;
 | 
			
		||||
	stio_dev_sck_on_write_t on_write;
 | 
			
		||||
	stio_dev_sck_on_read_t on_read;
 | 
			
		||||
	stio_dev_sck_on_disconnect_t on_disconnect;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum stio_dev_sck_bind_option_t
 | 
			
		||||
@ -195,7 +384,6 @@ enum stio_def_sck_connect_option_t
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_sck_connect_option_t stio_dev_sck_connect_option_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t;
 | 
			
		||||
struct stio_dev_sck_connect_t
 | 
			
		||||
{
 | 
			
		||||
@ -203,7 +391,6 @@ struct stio_dev_sck_connect_t
 | 
			
		||||
	stio_sckaddr_t remoteaddr;
 | 
			
		||||
	stio_ntime_t connect_tmout;
 | 
			
		||||
	stio_dev_sck_on_connect_t on_connect;
 | 
			
		||||
	stio_dev_sck_on_disconnect_t on_disconnect;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_sck_listen_t stio_dev_sck_listen_t;
 | 
			
		||||
@ -211,7 +398,6 @@ struct stio_dev_sck_listen_t
 | 
			
		||||
{
 | 
			
		||||
	int backlogs;
 | 
			
		||||
	stio_dev_sck_on_connect_t on_connect; /* optional, but new connections are dropped immediately without this */
 | 
			
		||||
	stio_dev_sck_on_disconnect_t on_disconnect; /* should on_discconneted be part of on_accept_t??? */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_sck_accept_t stio_dev_sck_accept_t;
 | 
			
		||||
@ -352,10 +538,10 @@ STIO_EXPORT int stio_dev_sck_listen (
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
STIO_EXPORT int stio_dev_sck_write (
 | 
			
		||||
	stio_dev_sck_t*       dev,
 | 
			
		||||
	const void*           data,
 | 
			
		||||
	stio_iolen_t          len,
 | 
			
		||||
	void*                 wrctx,
 | 
			
		||||
	stio_dev_sck_t*        dev,
 | 
			
		||||
	const void*            data,
 | 
			
		||||
	stio_iolen_t           len,
 | 
			
		||||
	void*                  wrctx,
 | 
			
		||||
	const stio_sckaddr_t*  dstaddr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -373,7 +559,6 @@ STIO_EXPORT int stio_dev_sck_timedwrite (
 | 
			
		||||
static STIO_INLINE void stio_dev_sck_halt (stio_dev_sck_t* sck)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_halt ((stio_dev_t*)sck);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled)
 | 
			
		||||
@ -386,10 +571,17 @@ static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled)
 | 
			
		||||
#define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck)
 | 
			
		||||
#define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
STIO_EXPORT stio_uint16_t stio_checksumip (
 | 
			
		||||
	const void* hdr,
 | 
			
		||||
	stio_size_t len
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										118
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							@ -125,15 +125,30 @@ enum stio_stopreq_t
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_stopreq_t stio_stopreq_t;
 | 
			
		||||
 | 
			
		||||
typedef struct stio_tmrjob_t stio_tmrjob_t;
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1)
 | 
			
		||||
 | 
			
		||||
typedef stio_size_t stio_tmridx_t;
 | 
			
		||||
 | 
			
		||||
typedef struct stio_tmrjob_t stio_tmrjob_t;
 | 
			
		||||
 | 
			
		||||
typedef void (*stio_tmrjob_handler_t) (
 | 
			
		||||
	stio_t*             stio,
 | 
			
		||||
	const stio_ntime_t* now, 
 | 
			
		||||
	stio_tmrjob_t*      tmrjob
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
struct stio_tmrjob_t
 | 
			
		||||
{
 | 
			
		||||
	void*                  ctx;
 | 
			
		||||
	stio_ntime_t           when;
 | 
			
		||||
	stio_tmrjob_handler_t  handler;
 | 
			
		||||
	stio_tmridx_t*         idxptr; /* pointer to the index holder */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
struct stio_dev_mth_t
 | 
			
		||||
{
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
@ -306,102 +321,6 @@ enum stio_dev_event_t
 | 
			
		||||
typedef enum stio_dev_event_t stio_dev_event_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
/* TOOD: move these to a separte file */
 | 
			
		||||
 | 
			
		||||
#define STIO_ETHHDR_PROTO_IP4 0x0800
 | 
			
		||||
#define STIO_ETHHDR_PROTO_ARP 0x0806
 | 
			
		||||
 | 
			
		||||
#define STIO_ARPHDR_OPCODE_REQUEST 1
 | 
			
		||||
#define STIO_ARPHDR_OPCODE_REPLY   2
 | 
			
		||||
 | 
			
		||||
#define STIO_ARPHDR_HTYPE_ETH 0x0001
 | 
			
		||||
#define STIO_ARPHDR_PTYPE_IP4 0x0800
 | 
			
		||||
 | 
			
		||||
#define STIO_ETHADDR_LEN 6
 | 
			
		||||
#define STIO_IP4ADDR_LEN 4
 | 
			
		||||
#define STIO_IP6ADDR_LEN 16 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
#	define STIO_PACKED __attribute__((__packed__))
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#	define STIO_PACKED 
 | 
			
		||||
#	STIO_PACK_PUSH pack(push)
 | 
			
		||||
#	STIO_PACK_PUSH pack(push)
 | 
			
		||||
#	STIO_PACK(x) pack(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
	/* nothing */
 | 
			
		||||
#else
 | 
			
		||||
	#pragma pack(push)
 | 
			
		||||
	#pragma pack(1)
 | 
			
		||||
#endif
 | 
			
		||||
struct STIO_PACKED stio_ethaddr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_ETHADDR_LEN]; 
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ethaddr_t stio_ethaddr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ip4addr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_IP4ADDR_LEN];
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ip4addr_t stio_ip4addr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ip6addr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t v[STIO_IP6ADDR_LEN]; 
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ip6addr_t stio_ip6addr_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_ethhdr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t  dest[STIO_ETHADDR_LEN];
 | 
			
		||||
	stio_uint8_t  source[STIO_ETHADDR_LEN];
 | 
			
		||||
	stio_uint16_t proto;
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_ethhdr_t stio_ethhdr_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_arphdr_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint16_t htype;   /* hardware type (ethernet: 0x0001) */
 | 
			
		||||
	stio_uint16_t ptype;   /* protocol type (ipv4: 0x0800) */
 | 
			
		||||
	stio_uint8_t  hlen;    /* hardware address length (ethernet: 6) */
 | 
			
		||||
	stio_uint8_t  plen;    /* protocol address length (ipv4 :4) */
 | 
			
		||||
	stio_uint16_t opcode;  /* operation code */
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_arphdr_t stio_arphdr_t;
 | 
			
		||||
 | 
			
		||||
/* arp payload for ipv4 over ethernet */
 | 
			
		||||
struct STIO_PACKED stio_etharp_t
 | 
			
		||||
{
 | 
			
		||||
	stio_uint8_t sha[STIO_ETHADDR_LEN];   /* source hardware address */
 | 
			
		||||
	stio_uint8_t spa[STIO_IP4ADDR_LEN];   /* source protocol address */
 | 
			
		||||
	stio_uint8_t tha[STIO_ETHADDR_LEN];   /* target hardware address */
 | 
			
		||||
	stio_uint8_t tpa[STIO_IP4ADDR_LEN];   /* target protocol address */
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_etharp_t stio_etharp_t;
 | 
			
		||||
 | 
			
		||||
struct STIO_PACKED stio_etharp_pkt_t
 | 
			
		||||
{
 | 
			
		||||
	stio_ethhdr_t ethhdr;
 | 
			
		||||
	stio_arphdr_t arphdr;
 | 
			
		||||
	stio_etharp_t arppld;
 | 
			
		||||
};
 | 
			
		||||
typedef struct stio_etharp_pkt_t stio_etharp_pkt_t;
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
	/* nothing */
 | 
			
		||||
#else
 | 
			
		||||
	#pragma pack(pop)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
@ -469,8 +388,8 @@ STIO_EXPORT int stio_dev_watch (
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
STIO_EXPORT int stio_dev_read (
 | 
			
		||||
	stio_dev_t*   dev,
 | 
			
		||||
	int           enabled
 | 
			
		||||
	stio_dev_t*         dev,
 | 
			
		||||
	int                 enabled
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -504,7 +423,6 @@ STIO_EXPORT void stio_dev_halt (
 | 
			
		||||
	stio_dev_t* dev
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
#define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns)))
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user