diff --git a/mio/bin/t01.c b/mio/bin/t01.c index 650580b..c5c46dc 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -419,7 +419,9 @@ static int setup_arp_tester (mio_t* mio) //mio_bcstrtoifindex (mio, "enp0s25.3", &ifindex); //mio_skad_init_for_eth (ðdst, ifindex, (mio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF"); //mio_skad_init_for_eth (ðdst, ifindex, (mio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); - mio_bcstrtoifindex (mio, "eno1", &ifindex); + //mio_bcstrtoifindex (mio, "eno1", &ifindex); + //mio_skad_init_for_eth (ðdst, ifindex, (mio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); + mio_bcstrtoifindex (mio, "bce0", &ifindex); mio_skad_init_for_eth (ðdst, ifindex, (mio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); memset (ðarp, 0, MIO_SIZEOF(etharp)); @@ -467,7 +469,8 @@ static void send_icmp (mio_dev_sck_t* dev, mio_uint16_t seq) mio_icmphdr_t* icmphdr; mio_uint8_t buf[512]; - mio_bcstrtoskad (mio, "192.168.9.1", &dstaddr); + //mio_bcstrtoskad (mio, "192.168.9.1", &dstaddr); + mio_bcstrtoskad (mio, "192.168.1.1", &dstaddr); memset(buf, 0, MIO_SIZEOF(buf)); icmphdr = (mio_icmphdr_t*)buf; diff --git a/mio/lib/mio-sck.h b/mio/lib/mio-sck.h index 4ad0ae0..b675041 100644 --- a/mio/lib/mio-sck.h +++ b/mio/lib/mio-sck.h @@ -31,7 +31,7 @@ #include /* ========================================================================= */ -/* TOOD: move these to a separte file */ +/* TOOD: move these to a separate file */ #define MIO_ETHHDR_PROTO_IP4 0x0800 #define MIO_ETHHDR_PROTO_ARP 0x0806 @@ -269,18 +269,21 @@ enum mio_dev_sck_type_t MIO_DEV_SCK_UDP4, MIO_DEV_SCK_UDP6, - /* ARP at the ethernet layer */ - MIO_DEV_SCK_ARP, - MIO_DEV_SCK_ARP_DGRAM, - /* ICMP at the IPv4 layer */ MIO_DEV_SCK_ICMP4, /* ICMP at the IPv6 layer */ MIO_DEV_SCK_ICMP6, + /* ARP at the ethernet layer */ + MIO_DEV_SCK_ARP, + MIO_DEV_SCK_ARP_DGRAM, + /* raw L2-level packet */ - MIO_DEV_SCK_PACKET + MIO_DEV_SCK_PACKET, + + /* bpf socket */ + MIO_DEV_SCK_BPF }; typedef enum mio_dev_sck_type_t mio_dev_sck_type_t; diff --git a/mio/lib/sck.c b/mio/lib/sck.c index 0113d98..84104d6 100644 --- a/mio/lib/sck.c +++ b/mio/lib/sck.c @@ -51,6 +51,12 @@ # include #endif +#if defined(HAVE_SYS_IOCTL_H) +# include +#endif + +#include + #if defined(__linux__) # include # if defined(HAVE_LINUX_NETFILTER_IPV4_H) @@ -78,7 +84,6 @@ # define USE_SSL #endif - /* ========================================================================= */ static mio_syshnd_t open_async_socket (mio_t* mio, int domain, int type, int proto) @@ -116,8 +121,8 @@ done: return sck; oops: - if (sck != MIO_SYSHND_INVALID) close (sck); mio_seterrwithsyserr (mio, 0, errno); + if (sck != MIO_SYSHND_INVALID) close (sck); return MIO_SYSHND_INVALID; } @@ -139,6 +144,7 @@ open_socket: goto open_socket; } #endif + mio_seterrwithsyserr (mio, 0, errno); return MIO_SYSHND_INVALID; } else @@ -153,6 +159,7 @@ open_socket: mio_makesyshndcloexec(mio, fd[0]) <= -1 || mio_makesyshndcloexec(mio, fd[1]) <= -1) { + mio_seterrwithsyserr (mio, 0, errno); close (fd[0]); close (fd[1]); return MIO_SYSHND_INVALID; @@ -163,6 +170,25 @@ done: return fd[0]; /* read end of the pipe */ } +static mio_syshnd_t open_async_bpf (mio_t* mio) +{ + mio_syshnd_t fd = MIO_SYSHND_INVALID; + int tmp; + unsigned int bufsize; + + fd = open("/dev/bpf", O_RDWR); + if (fd == MIO_SYSHND_INVALID) goto oops; + + if (ioctl(fd, BIOCIMMEDIATE, &tmp) == -1) goto oops; + if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) goto oops; + + return fd; +oops: + mio_seterrwithsyserr (mio, 0, errno); + if (fd != MIO_SYSHND_INVALID) close (fd); + return MIO_SYSHND_INVALID; +} + /* ========================================================================= */ static mio_devaddr_t* skad_to_devaddr (mio_dev_sck_t* dev, const mio_skad_t* sckaddr, mio_devaddr_t* devaddr) @@ -195,6 +221,7 @@ struct sck_type_map_t }; #define __AF_QX 999999 +#define __AF_BPF 999998 static struct sck_type_map_t sck_type_map[] = { @@ -213,12 +240,17 @@ static struct sck_type_map_t sck_type_map[] = /* MIO_DEV_SCK_UDP6 */ { AF_INET6, SOCK_DGRAM, 0, 0 }, + /* MIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ + { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, }, + + /* MIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ + { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0, }, #if defined(AF_PACKET) && (MIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) /* MIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */ { AF_PACKET, SOCK_RAW, MIO_CONST_HTON16(MIO_ETHHDR_PROTO_ARP), 0 }, - /* MIO_DEV_SCK_ARP_DGRAM */ + /* MIO_DEV_SCK_ARP_DGRAM - link-level header removed*/ { AF_PACKET, SOCK_DGRAM, MIO_CONST_HTON16(MIO_ETHHDR_PROTO_ARP), 0 }, #elif defined(AF_LINK) && (MIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) @@ -232,22 +264,19 @@ static struct sck_type_map_t sck_type_map[] = { -1, 0, 0, 0 }, #endif - /* MIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ - { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, }, - - /* MIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ - { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0, }, - - #if defined(AF_PACKET) && (MIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) /* MIO_DEV_SCK_PACKET */ - { AF_PACKET, SOCK_RAW, MIO_CONST_HTON16(ETH_P_ALL), 0 }, + { AF_PACKET, SOCK_RAW, MIO_CONST_HTON16(ETH_P_ALL), 0 }, #elif defined(AF_LINK) && (MIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) /* MIO_DEV_SCK_PACKET */ - { AF_PACKET, SOCK_RAW, MIO_CONST_HTON16(ETH_P_ALL), 0 }, + { AF_LINK, SOCK_RAW, MIO_CONST_HTON16(0), 0 }, #else { -1, 0, 0, 0 }, #endif + + + /* MIO_DEV_SCK_BPF - arp */ + { __AF_BPF, 0, 0, 0 } /* not implemented yet */ }; /* ======================================================================== */ @@ -571,6 +600,14 @@ static int dev_sck_read_stateless (mio_dev_t* dev, void* buf, mio_iolen_t* len, return 1; } +static int dev_sck_read_bpf (mio_dev_t* dev, void* buf, mio_iolen_t* len, mio_devaddr_t* srcaddr) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrwithsyserr (mio, 0, MIO_ENOIMPL); + return -1; +} + /* ------------------------------------------------------------------------------ */ static int dev_sck_write_stateful (mio_dev_t* dev, const void* data, mio_iolen_t* len, const mio_devaddr_t* dstaddr) @@ -801,6 +838,24 @@ static int dev_sck_writev_stateless (mio_dev_t* dev, const mio_iovec_t* iov, mio return 1; } +/* ------------------------------------------------------------------------------ */ +static int dev_sck_write_bpf (mio_dev_t* dev, const void* data, mio_iolen_t* len, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrwithsyserr (mio, 0, MIO_ENOIMPL); + return -1; +} + +static int dev_sck_writev_bpf (mio_dev_t* dev, const mio_iovec_t* iov, mio_iolen_t* iovcnt, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrwithsyserr (mio, 0, MIO_ENOIMPL); + return -1; +} + + /* ------------------------------------------------------------------------------ */ static int dev_sck_sendfile_stateful (mio_dev_t* dev, mio_syshnd_t in_fd, mio_foff_t foff, mio_iolen_t* len) @@ -1317,7 +1372,7 @@ fcntl (rdev->hnd, F_SETFL, flags | O_NONBLOCK); return 0; } -static mio_dev_mth_t dev_sck_methods_stateless = +static mio_dev_mth_t dev_mth_sck_stateless = { dev_sck_make, dev_sck_kill, @@ -1332,7 +1387,7 @@ static mio_dev_mth_t dev_sck_methods_stateless = }; -static mio_dev_mth_t dev_sck_methods_stateful = +static mio_dev_mth_t dev_mth_sck_stateful = { dev_sck_make, dev_sck_kill, @@ -1360,6 +1415,20 @@ static mio_dev_mth_t dev_mth_clisck = dev_sck_ioctl }; +static mio_dev_mth_t dev_mth_sck_bpf = +{ + dev_sck_make, + dev_sck_kill, + MIO_NULL, + dev_sck_getsyshnd, + + dev_sck_read_bpf, + dev_sck_write_bpf, + dev_sck_writev_bpf, + MIO_NULL, /* sendfile */ + dev_sck_ioctl, /* ioctl */ +}; + /* ========================================================================= */ static int harvest_outgoing_connection (mio_dev_sck_t* rdev) @@ -1969,6 +2038,39 @@ static mio_dev_evcb_t dev_sck_event_callbacks_qx = /* ========================================================================= */ +static int dev_evcb_sck_ready_bpf (mio_dev_t* dev, int events) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrnum (mio, MIO_ENOIMPL); + return -1; +} + +static int dev_evcb_sck_on_read_bpf (mio_dev_t* dev, const void* data, mio_iolen_t dlen, const mio_devaddr_t* srcaddr) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrnum (mio, MIO_ENOIMPL); + return -1; +} + +static int dev_evcb_sck_on_write_bpf (mio_dev_t* dev, mio_iolen_t wrlen, void* wrctx, const mio_devaddr_t* dstaddr) +{ + mio_t* mio = dev->mio; + mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; + mio_seterrnum (mio, MIO_ENOIMPL); + return -1; +} + +static mio_dev_evcb_t dev_sck_event_callbacks_bpf = +{ + dev_evcb_sck_ready_bpf, + dev_evcb_sck_on_read_bpf, + dev_evcb_sck_on_write_bpf +}; + +/* ========================================================================= */ + mio_dev_sck_t* mio_dev_sck_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_sck_make_t* info) { mio_dev_sck_t* rdev; @@ -1983,19 +2085,25 @@ mio_dev_sck_t* mio_dev_sck_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_sc { rdev = (mio_dev_sck_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, - &dev_sck_methods_stateless, &dev_sck_event_callbacks_qx, (void*)info); + &dev_mth_sck_stateless, &dev_sck_event_callbacks_qx, (void*)info); + } + else if (info->type == MIO_DEV_SCK_BPF) + { + rdev = (mio_dev_sck_t*)mio_dev_make( + mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, + &dev_mth_sck_bpf, &dev_sck_event_callbacks_bpf, (void*)info); } else if (sck_type_map[info->type].extra_dev_cap & MIO_DEV_CAP_STREAM) /* can't use the IS_STATEFUL() macro yet */ { rdev = (mio_dev_sck_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, - &dev_sck_methods_stateful, &dev_sck_event_callbacks_stateful, (void*)info); + &dev_mth_sck_stateful, &dev_sck_event_callbacks_stateful, (void*)info); } else { rdev = (mio_dev_sck_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, - &dev_sck_methods_stateless, &dev_sck_event_callbacks_stateless, (void*)info); + &dev_mth_sck_stateless, &dev_sck_event_callbacks_stateless, (void*)info); } return rdev;