added stio_checksumip(), stio_iphdr_t, stio_icmphdr_t

This commit is contained in:
hyung-hwan 2016-04-25 14:07:28 +00:00
parent ef4477ea7c
commit 4396006e7a
5 changed files with 526 additions and 201 deletions

View File

@ -40,6 +40,8 @@
#include <netpacket/packet.h> #include <netpacket/packet.h>
#include <net/if.h> #include <net/if.h>
#include <assert.h>
#if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL) #if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL)
# include <openssl/ssl.h> # include <openssl/ssl.h>
# if defined(HAVE_OPENSSL_ERR_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)) switch (STIO_DEV_SCK_GET_PROGRESS(tcp))
{ {
case STIO_DEV_SCK_CONNECTING: 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; break;
case STIO_DEV_SCK_CONNECTING_SSL: 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; break;
case STIO_DEV_SCK_LISTENING: case STIO_DEV_SCK_LISTENING:
@ -150,7 +152,7 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp)
break; break;
default: 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; break;
} }
} }
@ -203,6 +205,8 @@ else
printf ("ENABLING READING..............................\n"); printf ("ENABLING READING..............................\n");
stio_dev_sck_read (tcp, 1); stio_dev_sck_read (tcp, 1);
//stio_dev_sck_timedread (tcp, 1, 1000);
} }
return 0; return 0;
} }
@ -237,12 +241,14 @@ free (xxx);
if (n <= -1) return -1; if (n <= -1) return -1;
} }
printf ("DISABLING READING..............................\n");
stio_dev_sck_read (tcp, 0);
/* post the write finisher */ /* post the write finisher */
n = stio_dev_sck_write (tcp, STIO_NULL, 0, STIO_NULL, STIO_NULL); n = stio_dev_sck_write (tcp, STIO_NULL, 0, STIO_NULL, STIO_NULL);
if (n <= -1) return -1; if (n <= -1) return -1;
printf ("DISABLING READING..............................\n");
stio_dev_sck_read (tcp, 0);
return 0; return 0;
/* return 1; let the main loop to read more greedily without consulting the multiplexer */ /* 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) 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; 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; 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 (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
stio_sckaddr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
memset (&etharp, 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, &etharp, sizeof(etharp), NULL, &ethdst) <= -1)
//if (stio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &ethaddr) <= -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);
} }
static int pro_on_read (stio_dev_pro_t* dev, const void* data, stio_iolen_t dlen, stio_dev_pro_sid_t sid) if (schedule_icmp_wait (dev) <= -1)
{ {
printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data); printf ("CANNOT SCHEDULE ICMP WAIT...\n");
stio_dev_sck_halt (dev);
}
}
static void on_icmp_due (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* tmrjob)
{
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; 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; 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; static stio_t* g_stio;
@ -306,7 +538,6 @@ int main ()
int i; int i;
stio_t* stio; stio_t* stio;
stio_dev_sck_t* sck;
stio_dev_sck_t* tcp[3]; stio_dev_sck_t* tcp[3];
struct sigaction sigact; struct sigaction sigact;
@ -315,7 +546,6 @@ int main ()
stio_dev_sck_bind_t tcp_bind; stio_dev_sck_bind_t tcp_bind;
stio_dev_sck_make_t tcp_make; stio_dev_sck_make_t tcp_make;
stio_dev_sck_make_t sck_make;
tcp_server_t* ts; tcp_server_t* ts;
#if defined(USE_SSL) #if defined(USE_SSL)
@ -363,6 +593,7 @@ int main ()
tcp_make.type = STIO_DEV_SCK_TCP4; tcp_make.type = STIO_DEV_SCK_TCP4;
tcp_make.on_write = tcp_sck_on_write; tcp_make.on_write = tcp_sck_on_write;
tcp_make.on_read = tcp_sck_on_read; 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); tcp[0] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
if (!tcp[0]) if (!tcp[0])
{ {
@ -382,7 +613,6 @@ int main ()
stio_inittime (&tcp_conn.connect_tmout, 5, 0); stio_inittime (&tcp_conn.connect_tmout, 5, 0);
tcp_conn.on_connect = tcp_sck_on_connect; tcp_conn.on_connect = tcp_sck_on_connect;
tcp_conn.on_disconnect = tcp_sck_on_disconnect;
tcp_conn.options = STIO_DEV_SCK_CONNECT_SSL; tcp_conn.options = STIO_DEV_SCK_CONNECT_SSL;
if (stio_dev_sck_connect (tcp[0], &tcp_conn) <= -1) 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.type = STIO_DEV_SCK_TCP4;
tcp_make.on_write = tcp_sck_on_write; tcp_make.on_write = tcp_sck_on_write;
tcp_make.on_read = tcp_sck_on_read; 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); tcp[1] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
if (!tcp[1]) if (!tcp[1])
@ -419,7 +649,6 @@ int main ()
tcp_lstn.backlogs = 100; tcp_lstn.backlogs = 100;
tcp_lstn.on_connect = tcp_sck_on_connect; 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) if (stio_dev_sck_listen (tcp[1], &tcp_lstn) <= -1)
{ {
printf ("stio_dev_sck_listen() failed....\n"); printf ("stio_dev_sck_listen() failed....\n");
@ -431,6 +660,7 @@ int main ()
tcp_make.type = STIO_DEV_SCK_TCP4; tcp_make.type = STIO_DEV_SCK_TCP4;
tcp_make.on_write = tcp_sck_on_write; tcp_make.on_write = tcp_sck_on_write;
tcp_make.on_read = tcp_sck_on_read; 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); tcp[2] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make);
if (!tcp[2]) if (!tcp[2])
@ -456,7 +686,6 @@ int main ()
tcp_lstn.backlogs = 100; tcp_lstn.backlogs = 100;
tcp_lstn.on_connect = tcp_sck_on_connect; 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) if (stio_dev_sck_listen (tcp[2], &tcp_lstn) <= -1)
{ {
printf ("stio_dev_sck_listen() failed....\n"); printf ("stio_dev_sck_listen() failed....\n");
@ -464,49 +693,9 @@ int main ()
} }
//stio_dev_sck_sendfile (tcp[2], fd, offset, count); //stio_dev_sck_sendfile (tcp[2], fd, offset, count);
#if 1
{
stio_sckaddr_t ethdst; if (setup_arp_tester(stio) <= -1) goto oops;
stio_etharp_pkt_t etharp; if (setup_ping4_tester(stio) <= -1) goto oops;
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 (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
stio_sckaddr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
memset (&etharp, 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, &etharp, sizeof(etharp), NULL, &ethdst) <= -1)
//if (stio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &ethaddr) <= -1)
{
printf ("CANNOT WRITE ARP...\n");
}
}
#endif
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)

View File

@ -40,17 +40,6 @@
#define STIO_MEMCMP(dst,src,count) memcmp(dst,src,count) #define STIO_MEMCMP(dst,src,count) memcmp(dst,src,count)
#define STIO_ASSERT assert #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; typedef struct stio_mux_t stio_mux_t;
struct stio_t struct stio_t

View File

@ -116,7 +116,6 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
return STIO_SCKHND_INVALID; return STIO_SCKHND_INVALID;
} }
#endif #endif
return sck; return sck;
@ -249,15 +248,29 @@ struct sck_type_map_t
static struct sck_type_map_t sck_type_map[] = 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 }, { 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 }, { AF_INET6, SOCK_STREAM, 0, STIO_DEV_CAPA_STREAM | STIO_DEV_CAPA_OUT_QUEUED },
/* STIO_DEV_SCK_UPD4 */
{ AF_INET, SOCK_DGRAM, 0, 0 }, { AF_INET, SOCK_DGRAM, 0, 0 },
/* STIO_DEV_SCK_UDP6 */
{ AF_INET6, SOCK_DGRAM, 0, 0 }, { AF_INET6, SOCK_DGRAM, 0, 0 },
{ AF_PACKET, SOCK_RAW, 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_DGRAM, STIO_CONST_HTON16(0x0806), 0 }, { 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->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_write = arg->on_write;
rdev->on_read = arg->on_read; rdev->on_read = arg->on_read;
rdev->on_disconnect = arg->on_disconnect;
rdev->type = arg->type; rdev->type = arg->type;
rdev->tmrjob_index = STIO_TMRIDX_INVALID; rdev->tmrjob_index = STIO_TMRIDX_INVALID;
@ -393,12 +407,12 @@ static int dev_sck_kill (stio_dev_t* dev, int force)
if (IS_STATEFUL(rdev)) 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 /* for STIO_DEV_SCK_CONNECTING, STIO_DEV_SCK_CONNECTING_SSL, and STIO_DEV_ACCEPTING_SSL
* on_disconnect() is called without corresponding on_connect() */ * on_disconnect() is called without corresponding on_connect() */
if (rdev->on_disconnect) rdev->on_disconnect (rdev); if (rdev->on_disconnect) rdev->on_disconnect (rdev);
} /*}*/
if (rdev->tmrjob_index != STIO_TMRIDX_INVALID) 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->state == 0);
STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
if (rdev->on_disconnect) rdev->on_disconnect (rdev);
} }
#if defined(USE_SSL) #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); int err = SSL_get_error ((SSL*)rdev->ssl, x);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0; 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; rdev->stio->errnum = STIO_ESYSERR;
return -1; return -1;
} }
@ -932,7 +946,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
rdev->remoteaddr = conn->remoteaddr; rdev->remoteaddr = conn->remoteaddr;
rdev->on_connect = conn->on_connect; rdev->on_connect = conn->on_connect;
rdev->on_disconnect = conn->on_disconnect;
#if defined(USE_SSL) #if defined(USE_SSL)
rdev->ssl_ctx = ssl_ctx; rdev->ssl_ctx = ssl_ctx;
#endif #endif
@ -960,7 +973,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
/* connected immediately */ /* connected immediately */
rdev->remoteaddr = conn->remoteaddr; rdev->remoteaddr = conn->remoteaddr;
rdev->on_connect = conn->on_connect; rdev->on_connect = conn->on_connect;
rdev->on_disconnect = conn->on_disconnect;
sl = STIO_SIZEOF(localaddr); sl = STIO_SIZEOF(localaddr);
if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = 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); STIO_DEV_SCK_SET_PROGRESS (rdev, STIO_DEV_SCK_LISTENING);
rdev->on_connect = lstn->on_connect; rdev->on_connect = lstn->on_connect;
rdev->on_disconnect = lstn->on_disconnect;
return 0; 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; stio_devaddr_t devaddr;
return stio_dev_timedwrite ((stio_dev_t*)dev, data, dlen, tmout, wrctx, sckaddr_to_devaddr(dev, dstaddr, &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;
}

View File

@ -29,6 +29,188 @@
#include <stio.h> #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; typedef int stio_sckfam_t;
struct stio_sckaddr_t struct stio_sckaddr_t
@ -72,11 +254,6 @@ typedef struct stio_sckaddr_t stio_sckaddr_t;
#endif #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 enum stio_dev_sck_ioctl_cmd_t
@ -127,6 +304,7 @@ typedef int (*stio_dev_sck_on_read_t) (
stio_iolen_t dlen, stio_iolen_t dlen,
const stio_sckaddr_t* srcaddr const stio_sckaddr_t* srcaddr
); );
typedef int (*stio_dev_sck_on_write_t) ( typedef int (*stio_dev_sck_on_write_t) (
stio_dev_sck_t* dev, stio_dev_sck_t* dev,
stio_iolen_t wrlen, stio_iolen_t wrlen,
@ -134,8 +312,13 @@ typedef int (*stio_dev_sck_on_write_t) (
const stio_sckaddr_t* dstaddr 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) (
typedef void (*stio_dev_sck_on_disconnect_t) (stio_dev_sck_t* dev); stio_dev_sck_t* dev
);
typedef int (*stio_dev_sck_on_connect_t) (
stio_dev_sck_t* dev
);
enum stio_dev_sck_type_t enum stio_dev_sck_type_t
{ {
@ -144,10 +327,15 @@ enum stio_dev_sck_type_t
STIO_DEV_SCK_UPD4, STIO_DEV_SCK_UPD4,
STIO_DEV_SCK_UDP6, STIO_DEV_SCK_UDP6,
/* ARP at the ethernet layer */
STIO_DEV_SCK_ARP, STIO_DEV_SCK_ARP,
STIO_DEV_SCK_ARP_DGRAM, 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 #if 0
STIO_DEV_SCK_RAW, /* raw L2-level packet */ 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_type_t type;
stio_dev_sck_on_write_t on_write; stio_dev_sck_on_write_t on_write;
stio_dev_sck_on_read_t on_read; stio_dev_sck_on_read_t on_read;
stio_dev_sck_on_disconnect_t on_disconnect;
}; };
enum stio_dev_sck_bind_option_t 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 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; typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t;
struct 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_sckaddr_t remoteaddr;
stio_ntime_t connect_tmout; stio_ntime_t connect_tmout;
stio_dev_sck_on_connect_t on_connect; 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; typedef struct stio_dev_sck_listen_t stio_dev_sck_listen_t;
@ -211,7 +398,6 @@ struct stio_dev_sck_listen_t
{ {
int backlogs; int backlogs;
stio_dev_sck_on_connect_t on_connect; /* optional, but new connections are dropped immediately without this */ 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; typedef struct stio_dev_sck_accept_t stio_dev_sck_accept_t;
@ -373,7 +559,6 @@ STIO_EXPORT int stio_dev_sck_timedwrite (
static STIO_INLINE void stio_dev_sck_halt (stio_dev_sck_t* sck) static STIO_INLINE void stio_dev_sck_halt (stio_dev_sck_t* sck)
{ {
stio_dev_halt ((stio_dev_t*)sck); stio_dev_halt ((stio_dev_t*)sck);
} }
static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled) 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_halt(sck) stio_dev_halt((stio_dev_t*)sck)
#define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled) #define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled)
#endif #endif
STIO_EXPORT stio_uint16_t stio_checksumip (
const void* hdr,
stio_size_t len
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -125,15 +125,30 @@ enum stio_stopreq_t
}; };
typedef enum stio_stopreq_t 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 stio_size_t stio_tmridx_t;
typedef struct stio_tmrjob_t stio_tmrjob_t;
typedef void (*stio_tmrjob_handler_t) ( typedef void (*stio_tmrjob_handler_t) (
stio_t* stio, stio_t* stio,
const stio_ntime_t* now, const stio_ntime_t* now,
stio_tmrjob_t* tmrjob 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 struct stio_dev_mth_t
{ {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@ -306,102 +321,6 @@ enum stio_dev_event_t
typedef enum stio_dev_event_t 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 #ifdef __cplusplus
@ -504,7 +423,6 @@ STIO_EXPORT void stio_dev_halt (
stio_dev_t* dev stio_dev_t* dev
); );
/* ========================================================================= */ /* ========================================================================= */
#define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns))) #define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns)))