From 914a0c3905bb06d5cc8cace87578994125cfde72 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 17 Aug 2021 07:00:22 +0000 Subject: [PATCH] adding some code to handle multicast --- hio/bin/t01.c | 2 +- hio/bin/t02.c | 2 +- hio/bin/t06.c | 10 +++++-- hio/configure | 24 +++++++++++++--- hio/configure.ac | 24 +++++++++++++--- hio/lib/dhcp-svr.c | 64 +++++++++++++++++++++++++----------------- hio/lib/dns-cli.c | 4 +-- hio/lib/hio-dhcp.h | 15 ++-------- hio/lib/hio-sck.h | 13 ++++++++- hio/lib/hio-skad.h | 21 ++++++++++---- hio/lib/http-svr.c | 4 +-- hio/lib/sck.c | 37 +++++++++++++++--------- hio/lib/skad.c | 70 +++++++++++++++++++++++++++++++++------------- 13 files changed, 195 insertions(+), 95 deletions(-) diff --git a/hio/bin/t01.c b/hio/bin/t01.c index ad901f9..4f5cd3e 100644 --- a/hio/bin/t01.c +++ b/hio/bin/t01.c @@ -369,7 +369,7 @@ static int arp_sck_on_read (hio_dev_sck_t* dev, const void* data, hio_iolen_t dl eap = (hio_etharp_pkt_t*)data; - printf ("ARP ON IFINDEX %d OPCODE: %d", hio_skad_ifindex(srcaddr), ntohs(eap->arphdr.opcode)); + printf ("ARP ON IFINDEX %d OPCODE: %d", hio_skad_get_ifindex(srcaddr), ntohs(eap->arphdr.opcode)); printf (" SHA: %02X:%02X:%02X:%02X:%02X:%02X", eap->arppld.sha[0], eap->arppld.sha[1], eap->arppld.sha[2], eap->arppld.sha[3], eap->arppld.sha[4], eap->arppld.sha[5]); printf (" SPA: %d.%d.%d.%d", eap->arppld.spa[0], eap->arppld.spa[1], eap->arppld.spa[2], eap->arppld.spa[3]); diff --git a/hio/bin/t02.c b/hio/bin/t02.c index f0362aa..d682602 100644 --- a/hio/bin/t02.c +++ b/hio/bin/t02.c @@ -228,7 +228,7 @@ int main (int argc, char* argv[]) tcp_conn.options = 0; memset (&tcp_make, 0, HIO_SIZEOF(tcp_make)); - tcp_make.type = hio_skad_family(&tcp_conn.remoteaddr) == HIO_AF_INET? HIO_DEV_SCK_TCP4: HIO_DEV_SCK_TCP6; + tcp_make.type = hio_skad_get_family(&tcp_conn.remoteaddr) == HIO_AF_INET? HIO_DEV_SCK_TCP4: HIO_DEV_SCK_TCP6; tcp_make.on_write = tcp_sck_on_write; tcp_make.on_read = tcp_sck_on_read; tcp_make.on_connect = tcp_sck_on_connect; diff --git a/hio/bin/t06.c b/hio/bin/t06.c index 35ce920..e3d883d 100644 --- a/hio/bin/t06.c +++ b/hio/bin/t06.c @@ -465,9 +465,9 @@ static int tcp_sck_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len { /* won't be invoked * invokde if sctp_sp */ +#if 0 hio_iovec_t iov; -#if 0 /* the code here is invoked on a seqpacket socket. .. this part not ready. will rewrite if the core support is done */ printf ("[%.*s] chan %d\n", (int)len, buf, hio_skad_chan(srcaddr)); iov.iov_ptr = buf; @@ -502,7 +502,7 @@ static int add_listener (hio_t* hio, hio_bch_t* addrstr) #endif memset (&mi, 0, HIO_SIZEOF(mi)); - f = hio_skad_family(&bi.localaddr); + f = hio_skad_get_family(&bi.localaddr); if (f == HIO_AF_INET) mi.type = g_dev_type4; else if (f == HIO_AF_INET6) mi.type = g_dev_type6; else if (f == HIO_AF_UNIX) mi.type = HIO_DEV_SCK_UNIX; @@ -645,6 +645,12 @@ int main (int argc, char* argv[]) unlink ("t06.sck"); add_listener(hio, "@t06.sck"); +{ +hio_skad_t skad; +hio_bcstrtoskad(hio, "[::]:3547", &skad); +hio_svc_dhcs_start (hio, &skad, 1); +} + hio_loop (hio); xret = 0; diff --git a/hio/configure b/hio/configure index b802b27..b41a0d0 100755 --- a/hio/configure +++ b/hio/configure @@ -17581,9 +17581,13 @@ else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_in_x))" "ac_cv_sizeof_struct_sockaddr_in_x" " #include #include + struct sockaddr_extra_t + { + unsigned short chan; + } struct sockaddr_in_x { struct sockaddr_in a; - unsigned short chan; + struct sockaddr_extra_t u; }; "; then : @@ -17622,9 +17626,13 @@ else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_in6_x))" "ac_cv_sizeof_struct_sockaddr_in6_x" " #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in6_x { struct sockaddr_in6 a; - unsigned short chan; + struct sockaddr_extra_t u; }; "; then : @@ -18025,9 +18033,13 @@ else #include #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in_x { struct sockaddr_in a; - unsigned short chan; + struct sockaddr_extra_t u; }; "; then : @@ -18067,9 +18079,13 @@ else #include #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in6_x { struct sockaddr_in6 a; - unsigned short chan; + struct sockaddr_extra_t u; }; "; then : diff --git a/hio/configure.ac b/hio/configure.ac index 51b4809..779d657 100644 --- a/hio/configure.ac +++ b/hio/configure.ac @@ -469,17 +469,25 @@ then AC_CHECK_SIZEOF(struct sockaddr_in_x,,[ #include #include + struct sockaddr_extra_t + { + unsigned short chan; + } struct sockaddr_in_x { struct sockaddr_in a; - unsigned short chan; + struct sockaddr_extra_t u; }; ]) AC_CHECK_SIZEOF(struct sockaddr_in6_x,,[ #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in6_x { struct sockaddr_in6 a; - unsigned short chan; + struct sockaddr_extra_t u; }; ]) @@ -539,18 +547,26 @@ else #include #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in_x { struct sockaddr_in a; - unsigned short chan; + struct sockaddr_extra_t u; }; ]) AC_CHECK_SIZEOF(struct sockaddr_in6_x,,[ #include #include #include + struct sockaddr_extra_t + { + unsigned short chan; + }; struct sockaddr_in6_x { struct sockaddr_in6 a; - unsigned short chan; + struct sockaddr_extra_t u; }; ]) diff --git a/hio/lib/dhcp-svr.c b/hio/lib/dhcp-svr.c index d2207fd..d248823 100644 --- a/hio/lib/dhcp-svr.c +++ b/hio/lib/dhcp-svr.c @@ -59,16 +59,16 @@ static hio_dev_sck_t* open_socket (hio_t* hio, hio_svc_dhcs_cfg_t* cfg) hio_dev_sck_t* sck = HIO_NULL; int f; - f = hio_skad_family(&cfg->bind_addr); - if (f != HIO_AF_INET || f != HIO_AF_INET6) + f = hio_skad_get_family(&cfg->bind_addr); + if (f != HIO_AF_INET && f != HIO_AF_INET6) { hio_seterrbfmt (hio, HIO_EINVAL, "invalid bind address family"); goto oops; } HIO_MEMSET (&m, 0, HIO_SIZEOF(m)); - m.type = HIO_DEV_SCK_UDP6; - m.options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR; + m.type = (f == HIO_AF_INET? HIO_DEV_SCK_UDP4: HIO_DEV_SCK_UDP6); + //m.options = HIO_DEV_SCK_MAKE_LENIENT; //m.on_write = //m.on_read = ... //m.on_connect = ... @@ -76,11 +76,29 @@ static hio_dev_sck_t* open_socket (hio_t* hio, hio_svc_dhcs_cfg_t* cfg) sck = hio_dev_sck_make(hio, 0, &m); if (HIO_UNLIKELY(!sck)) goto oops; +/* + #if defined(IPV6_RECVPKTINFO) + hio_dev_sck_setsockopt (dhcs->sck, IPPROTO_IPV6, IPV6_RECVPKTINFO, &v); + #elif defined(IPV6_PKTINFO) + hio_dev_sck_setsockopt (dhcs->sck, IPPROTO_IPV6, IPV6_PKTINFO, &v); + #else + //# error no ipv6 pktinfo + #endif +*/ -#if 0 - if (hio_dev_sck_joingroup(sck, mcast_addr, ifindex) <= -1) goto oops; -#endif +{ +/* TODO: accept hio_dev_sck_bind_t instead of hio_skad_t? */ + hio_dev_sck_bind_t b; + HIO_MEMSET (&b, 0, HIO_SIZEOF(b)); + b.localaddr = cfg->bind_addr; + if (hio_dev_sck_bind(sck, &b) <= -1) goto oops; +} +{ + hio_skad_t mcast_addr; + hio_bcstrtoskad(hio, "[ff02::1:2]:0", &mcast_addr); + if (hio_dev_sck_joinmcastgroup(sck, &mcast_addr, 2) <= -1) goto oops; +} return sck; @@ -98,34 +116,23 @@ hio_svc_dhcs_t* hio_svc_dhcs_start (hio_t* hio, const hio_skad_t* local_binds, h hio_dev_sck_listen_t l; } info; hio_oow_t i; + hio_dev_sck_t* sck; dhcs = (hio_svc_dhcs_t*)hio_callocmem(hio, HIO_SIZEOF(*dhcs)); if (HIO_UNLIKELY(!dhcs)) goto oops; dhcs->hio = hio; - for (i = 0; i < local_nbinds; i++) { - HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); - info.m.type = HIO_DEV_SCK_UDP6; - info.m.options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR; - //info.m.on_write = - //info.m.on_read = ... - //info.m.on_connect = ... - //info.m.on_disconnect = ... - dhcs->sck = hio_dev_sck_make(hio, 0, &info.m); - if (HIO_UNLIKELY(!dhcs->sck)) goto oops; + hio_svc_dhcs_cfg_t cfg; - #if defined(IPV6_RECVPKTINFO) - hio_dev_sck_setsockopt (dhcs->sck, IPPROTO_IPV6, IPV6_RECVPKTINFO, &v); - #elif defined(IPV6_PKTINFO) - hio_dev_sck_setsockopt (dhcs->sck, IPPROTO_IPV6, IPV6_PKTINFO, &v); - #else - //# error no ipv6 pktinfo - #endif + HIO_MEMSET (&cfg, 0, HIO_SIZEOF(cfg)); + cfg.bind_addr = local_binds[i]; - hio_dev_sck_bind(dhcs->sck, &local_binds[i]); + sck = open_socket(hio, &cfg); + if (HIO_UNLIKELY(!sck)) goto oops; +/* TODO: remember this in dhcs... */ } HIO_SVCL_APPEND_SVC (&hio->actsvc, (hio_svc_t*)dhcs); @@ -134,7 +141,12 @@ hio_svc_dhcs_t* hio_svc_dhcs_start (hio_t* hio, const hio_skad_t* local_binds, h oops: if (dhcs) { - if (dhcs->sck) hio_dev_sck_kill (dhcs->sck); + if (sck) hio_dev_sck_kill (sck); +/*TODO: + for (i = 0; i < local_nbinds; i++) + { + if (dhcs->sck[i]) hio_dev_sck_kill(dhcs->sck[i]) + }*/ hio_freemem (hio, dhcs); } return HIO_NULL; diff --git a/hio/lib/dns-cli.c b/hio/lib/dns-cli.c index 2a7e2d6..7915c01 100644 --- a/hio/lib/dns-cli.c +++ b/hio/lib/dns-cli.c @@ -471,7 +471,7 @@ static int switch_reqmsg_transport_to_tcp (hio_svc_dnc_t* dnc, hio_dns_msg_t* re if (!dnc->tcp_sck) { HIO_MEMSET (&mkinfo, 0, HIO_SIZEOF(mkinfo)); - switch (hio_skad_family(&reqmsgxtn->servaddr)) + switch (hio_skad_get_family(&reqmsgxtn->servaddr)) { case HIO_AF_INET: mkinfo.type = HIO_DEV_SCK_TCP4; @@ -736,7 +736,7 @@ hio_svc_dnc_t* hio_svc_dnc_start (hio_t* hio, const hio_skad_t* serv_addr, const dnc->max_tries = max_tries; HIO_MEMSET (&mkinfo, 0, HIO_SIZEOF(mkinfo)); - switch (hio_skad_family(serv_addr)) + switch (hio_skad_get_family(serv_addr)) { case HIO_AF_INET: mkinfo.type = HIO_DEV_SCK_UDP4; diff --git a/hio/lib/hio-dhcp.h b/hio/lib/hio-dhcp.h index 5345300..760c936 100644 --- a/hio/lib/hio-dhcp.h +++ b/hio/lib/hio-dhcp.h @@ -26,7 +26,7 @@ #define _HIO_DHCP_H_ #include -#include +#include #define HIO_DHCP6_SERVER_PORT (547) #define HIO_DHCP6_CLIENT_PORT (546) @@ -97,7 +97,6 @@ typedef struct hio_dhcp6_pktinf_t hio_dhcp6_pktinf_t; /* ---------------------------------------------------------------- */ - typedef struct hio_svc_dhcs_t hio_svc_dhcs_t; /* ---------------------------------------------------------------- */ @@ -110,20 +109,10 @@ HIO_EXPORT hio_svc_dhcs_t* hio_svc_dhcs_start ( hio_t* hio, const hio_skad_t* local_binds, hio_oow_t local_nbinds - - -#if 0 - , - const hio_skad_t* serv_addr, /* required */ - const hio_skad_t* bind_addr, /* optional. can be HIO_NULL */ - const hio_ntime_t* send_tmout, /* required */ - const hio_ntime_t* reply_tmout, /* required */ - hio_oow_t max_tries /* required */ -#endif ); HIO_EXPORT void hio_svc_dhcs_stop ( - hio_svc_dhcs_t* dhcs + hio_svc_dhcs_t* dhcs ); #if defined(HIO_HAVE_INLINE) diff --git a/hio/lib/hio-sck.h b/hio/lib/hio-sck.h index b22bafc..632d378 100644 --- a/hio/lib/hio-sck.h +++ b/hio/lib/hio-sck.h @@ -580,7 +580,6 @@ HIO_EXPORT int hio_dev_sck_getsockopt ( hio_scklen_t* optlen ); - HIO_EXPORT int hio_dev_sck_getsockaddr ( hio_dev_sck_t* dev, hio_skad_t* skad @@ -591,6 +590,18 @@ HIO_EXPORT int hio_dev_sck_getpeeraddr ( hio_skad_t* skad ); +HIO_EXPORT int hio_dev_sck_joinmcastgroup ( + hio_dev_sck_t* dev, + const hio_skad_t* mcast_skad, + int ifindex +); + +HIO_EXPORT int hio_dev_sck_leavemcastgroup ( + hio_dev_sck_t* dev, + const hio_skad_t* mcast_skad, + int ifindex +); + HIO_EXPORT int hio_dev_sck_shutdown ( hio_dev_sck_t* dev, int how /* bitwise-ORed of hio_dev_sck_shutdown_how_t enumerators */ diff --git a/hio/lib/hio-skad.h b/hio/lib/hio-skad.h index 688a081..26821bc 100644 --- a/hio/lib/hio-skad.h +++ b/hio/lib/hio-skad.h @@ -194,23 +194,25 @@ HIO_EXPORT void hio_skad_init_for_qx ( hio_skad_t* skad ); -HIO_EXPORT int hio_skad_family ( +HIO_EXPORT int hio_skad_get_family ( const hio_skad_t* skad ); -HIO_EXPORT int hio_skad_size ( +HIO_EXPORT int hio_skad_get_size ( const hio_skad_t* skad ); -HIO_EXPORT int hio_skad_port ( +HIO_EXPORT int hio_skad_get_port ( const hio_skad_t* skad ); -HIO_EXPORT int hio_skad_ifindex ( +/* for link-level addresses */ +HIO_EXPORT int hio_skad_get_ifindex ( const hio_skad_t* skad ); -HIO_EXPORT int hio_skad_scope_id ( +/* for ipv6 */ +HIO_EXPORT int hio_skad_get_scope_id ( const hio_skad_t* skad ); @@ -219,7 +221,8 @@ HIO_EXPORT void hio_skad_set_scope_id ( int scope_id ); -HIO_EXPORT hio_uint16_t hio_skad_chan ( +/* for sctp */ +HIO_EXPORT hio_uint16_t hio_skad_get_chan ( const hio_skad_t* skad ); @@ -228,6 +231,12 @@ HIO_EXPORT void hio_skad_set_chan ( hio_uint16_t chan ); +HIO_EXPORT hio_oow_t hio_skad_get_ipad_bytes ( + hio_skad_t* skad, + void* buf, + hio_oow_t len +); + HIO_EXPORT void hio_clear_skad ( hio_skad_t* skad ); diff --git a/hio/lib/http-svr.c b/hio/lib/http-svr.c index dabfac8..73cd0ad 100644 --- a/hio/lib/http-svr.c +++ b/hio/lib/http-svr.c @@ -366,7 +366,7 @@ hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* binds, hio_o hio_dev_sck_t* sck; HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); - switch (hio_skad_family(&binds[i].localaddr)) + switch (hio_skad_get_family(&binds[i].localaddr)) { case HIO_AF_INET: info.m.type = HIO_DEV_SCK_TCP4; @@ -388,7 +388,7 @@ hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* binds, hio_o default: /* ignore this */ - HIO_DEBUG3 (hio, "HTTS(%p) - [%zu] unsupported bind address type %d\n", htts, i, (int)hio_skad_family(&binds[i].localaddr)); + HIO_DEBUG3 (hio, "HTTS(%p) - [%zu] unsupported bind address type %d\n", htts, i, (int)hio_skad_get_family(&binds[i].localaddr)); continue; } info.m.options = HIO_DEV_SCK_MAKE_LENIENT; diff --git a/hio/lib/sck.c b/hio/lib/sck.c index c358b89..4677f06 100644 --- a/hio/lib/sck.c +++ b/hio/lib/sck.c @@ -205,7 +205,7 @@ static hio_devaddr_t* skad_to_devaddr (hio_dev_sck_t* dev, const hio_skad_t* sck if (sckaddr) { devaddr->ptr = (void*)sckaddr; - devaddr->len = hio_skad_size(sckaddr); + devaddr->len = hio_skad_get_size(sckaddr); return devaddr; } @@ -1014,7 +1014,7 @@ static int dev_sck_write_sctp_sp (hio_dev_t* dev, const void* data, hio_iolen_t* &iov, 1, dstaddr->ptr, dstaddr->len, 0, /* ppid - opaque */ 0, /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */ - hio_skad_chan(dstaddr->ptr), /* stream number */ + hio_skad_get_chan(dstaddr->ptr), /* stream number */ 0, /* ttl */ 0 /* context*/); if (x <= -1) @@ -1039,7 +1039,7 @@ static int dev_sck_writev_sctp_sp (hio_dev_t* dev, const hio_iovec_t* iov, hio_i iov, *iovcnt, dstaddr->ptr, dstaddr->len, 0, /* ppid - opaque */ 0, /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */ - hio_skad_chan(dstaddr->ptr), /* stream number */ + hio_skad_get_chan(dstaddr->ptr), /* stream number */ 0, /* ttl */ 0 /* context*/); if (x <= -1) @@ -1239,7 +1239,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) return -1; } - if (hio_skad_family(&bnd->localaddr) == HIO_AF_INET6) /* getsockopt(rdev->hnd, SO_DOMAIN, ...) may return the domain but it's kernel specific as well */ + if (hio_skad_get_family(&bnd->localaddr) == HIO_AF_INET6) /* getsockopt(rdev->hnd, SO_DOMAIN, ...) may return the domain but it's kernel specific as well */ { /* TODO: should i make it into bnd->options? HIO_DEV_SCK_BIND_IPV6ONLY? applicable to ipv6 though. */ int v = 1; @@ -1375,7 +1375,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) #endif } - x = bind(rdev->hnd, (struct sockaddr*)&bnd->localaddr, hio_skad_size(&bnd->localaddr)); + x = bind(rdev->hnd, (struct sockaddr*)&bnd->localaddr, hio_skad_get_size(&bnd->localaddr)); if (x <= -1) { hio_seterrwithsyserr (hio, 0, errno); @@ -1859,7 +1859,7 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl { clidev->state |= HIO_DEV_SCK_INTERCEPTED; } - else if (hio_skad_port(&clidev->localaddr) != hio_skad_port(&rdev->localaddr)) + else if (hio_skad_get_port(&clidev->localaddr) != hio_skad_get_port(&rdev->localaddr)) { /* When TPROXY is used, getsockname() and SO_ORIGNAL_DST return * the same addresses. however, the port number may be different @@ -2508,21 +2508,22 @@ int hio_dev_sck_getpeeraddr (hio_dev_sck_t* dev, hio_skad_t* skad) return 0; } -int hio_dev_sck_joinmcastgroup (hio_dev_sck_t* dev, const hio_skad_t* mcast_skad, int ifindex) +static int update_mcast_group (hio_dev_sck_t* dev, int join, const hio_skad_t* mcast_skad, int ifindex) { int f; - f = hio_skad_family(mcast_skad); + f = hio_skad_get_family(mcast_skad); switch (f) { case HIO_AF_INET: { + /* TODO: if ip_mreqn doesn't exist, get the ip address of the index and set to imr_address */ struct ip_mreqn mreq; HIO_MEMSET (&mreq, 0, HIO_SIZEOF(mreq)); - //mreq.imr_multiaddr + hio_skad_get_ipad_bytes (mcast_skad, &mreq.imr_multiaddr, HIO_SIZEOF(mreq.imr_multiaddr)); mreq.imr_ifindex = ifindex; /*mreq.imr_address = */ - if (hio_dev_sck_setsockopt(dev, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, HIO_SIZEOF(mreq)) <= -1) return -1; + if (hio_dev_sck_setsockopt(dev, IPPROTO_IP, (join? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP), &mreq, HIO_SIZEOF(mreq)) <= -1) return -1; return 0; } @@ -2530,9 +2531,9 @@ int hio_dev_sck_joinmcastgroup (hio_dev_sck_t* dev, const hio_skad_t* mcast_skad { struct ipv6_mreq mreq; HIO_MEMSET (&mreq, 0, HIO_SIZEOF(mreq)); - mreq.ipv6mr_interface = ifindex; /* TODO: can reuse the scope id? */ - //mreq.ipv6mr_multiaddr = hio_skad_ip6ad(); - if (hio_dev_sck_setsockopt(dev, IPPROTO_IP, IPV6_JOIN_GROUP, &mreq, HIO_SIZEOF(mreq)) <= -1) return -1; + hio_skad_get_ipad_bytes (mcast_skad, &mreq.ipv6mr_multiaddr, HIO_SIZEOF(mreq.ipv6mr_multiaddr)); + mreq.ipv6mr_interface = ifindex; + if (hio_dev_sck_setsockopt(dev, IPPROTO_IPV6, (join? IPV6_JOIN_GROUP: IPV6_LEAVE_GROUP), &mreq, HIO_SIZEOF(mreq)) <= -1) return -1; return 0; } } @@ -2542,6 +2543,16 @@ int hio_dev_sck_joinmcastgroup (hio_dev_sck_t* dev, const hio_skad_t* mcast_skad return -1; } +int hio_dev_sck_joinmcastgroup (hio_dev_sck_t* dev, const hio_skad_t* mcast_skad, int ifindex) +{ + return update_mcast_group(dev, 1, mcast_skad, ifindex); +} + +int hio_dev_sck_leavemcastgroup (hio_dev_sck_t* dev, const hio_skad_t* mcast_skad, int ifindex) +{ + return update_mcast_group(dev, 0, mcast_skad, ifindex); +} + /* ========================================================================= */ int hio_dev_sck_shutdown (hio_dev_sck_t* dev, int how) diff --git a/hio/lib/skad.c b/hio/lib/skad.c index 20ccd3c..1d42dde 100644 --- a/hio/lib/skad.c +++ b/hio/lib/skad.c @@ -42,6 +42,12 @@ # include #endif +struct sockaddr_extra_t +{ + hio_uint16_t chan; +}; +typedef struct sockaddr_extra_t sockaddr_extra_t; + #if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) /* dirty hack to secure more space at the end of the actual socket address. * the extra fiels must be transparent to unaware parties. @@ -50,12 +56,12 @@ * * extra fields: * chan - used as a stream number for SCTP PACKETSEQ sockets. - * use hio_skad_chan() and hio_skad_setchan() for safe access. + * use hio_skad_get_chan() and hio_skad_set_chan() for safe access. */ struct sockaddr_in_x { struct sockaddr_in a; - hio_uint16_t chan; + sockaddr_extra_t x; }; #endif @@ -63,7 +69,7 @@ struct sockaddr_in_x struct sockaddr_in6_x { struct sockaddr_in6 a; - hio_uint16_t chan; + sockaddr_extra_t x; }; #endif @@ -1002,7 +1008,7 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, /* unsupported types will result in an empty string */ - switch (hio_skad_family(_skad)) + switch (hio_skad_get_family(_skad)) { case HIO_AF_INET: if (flags & HIO_SKAD_TO_UCSTR_ADDR) @@ -1263,7 +1269,7 @@ hio_oow_t hio_skadtobcstr (hio_t* hio, const hio_skad_t* _skad, hio_bch_t* buf, /* unsupported types will result in an empty string */ - switch (hio_skad_family(_skad)) + switch (hio_skad_get_family(_skad)) { case HIO_AF_INET: if (flags & HIO_SKAD_TO_BCSTR_ADDR) @@ -1382,17 +1388,17 @@ done: /* ------------------------------------------------------------------------- */ -int hio_skad_family (const hio_skad_t* _skad) +int hio_skad_get_family (const hio_skad_t* _skad) { const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; /*HIO_STATIC_ASSERT (HIO_SIZEOF(*_skad) >= HIO_SIZEOF(*skad));*/ return skad->sa.sa_family; } -int hio_skad_size (const hio_skad_t* _skad) +int hio_skad_get_size (const hio_skad_t* _skad) { - /* this excludes the size of the 'chan' field. - * the field is not part of the core socket address */ + /* this excludes the size of additiona fields(e.g. chan) + * the fields are not part of the core socket address */ const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; /*HIO_STATIC_ASSERT (HIO_SIZEOF(*_skad) >= HIO_SIZEOF(*skad));*/ @@ -1419,7 +1425,7 @@ int hio_skad_size (const hio_skad_t* _skad) return 0; } -int hio_skad_port (const hio_skad_t* _skad) +int hio_skad_get_port (const hio_skad_t* _skad) { const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; @@ -1435,7 +1441,7 @@ int hio_skad_port (const hio_skad_t* _skad) return 0; } -int hio_skad_ifindex (const hio_skad_t* _skad) +int hio_skad_get_ifindex (const hio_skad_t* _skad) { const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; @@ -1449,7 +1455,7 @@ int hio_skad_ifindex (const hio_skad_t* _skad) return 0; } -int hio_skad_scope_id (const hio_skad_t* _skad) +int hio_skad_get_scope_id (const hio_skad_t* _skad) { const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; @@ -1469,17 +1475,17 @@ void hio_skad_set_scope_id (hio_skad_t* _skad, int scope_id) #endif } -hio_uint16_t hio_skad_chan (const hio_skad_t* _skad) +hio_uint16_t hio_skad_get_chan (const hio_skad_t* _skad) { const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad; switch (skad->sa.sa_family) { #if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) - case AF_INET: return skad->in4.chan; + case AF_INET: return skad->in4.x.chan; #endif #if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) - case AF_INET6: return skad->in6.chan; + case AF_INET6: return skad->in6.x.chan; #endif } return 0; @@ -1492,14 +1498,38 @@ void hio_skad_set_chan (hio_skad_t* _skad, hio_uint16_t chan) switch (skad->sa.sa_family) { #if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) - case AF_INET: skad->in4.chan = chan; break; + case AF_INET: skad->in4.x.chan = chan; break; #endif #if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) - case AF_INET6: skad->in6.chan = chan; break; + case AF_INET6: skad->in6.x.chan = chan; break; #endif } } +hio_oow_t hio_skad_get_ipad_bytes (hio_skad_t* _skad, void* buf, hio_oow_t len) +{ + hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad; + hio_oow_t outlen = 0; + + switch (skad->sa.sa_family) + { + #if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) + case AF_INET: + outlen = len < HIO_SIZEOF(skad->in4.a.sin_addr)? len: HIO_SIZEOF(skad->in4.a.sin_addr); + HIO_MEMCPY (buf, &skad->in4.a.sin_addr, outlen); + break; + #endif + #if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + case AF_INET6: + outlen = len < HIO_SIZEOF(skad->in6.a.sin6_addr)? len: HIO_SIZEOF(skad->in6.a.sin6_addr); + HIO_MEMCPY (buf, &skad->in6.a.sin6_addr, outlen); + break; + #endif + } + + return outlen; +} + void hio_skad_init_for_ip4 (hio_skad_t* skad, hio_uint16_t port, hio_ip4ad_t* ip4ad) { #if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) @@ -1603,8 +1633,8 @@ int hio_equal_skads (const hio_skad_t* addr1, const hio_skad_t* addr2, int stric { int f1; - if ((f1 = hio_skad_family(addr1)) != hio_skad_family(addr2) || - hio_skad_size(addr1) != hio_skad_size(addr2)) return 0; + if ((f1 = hio_skad_get_family(addr1)) != hio_skad_get_family(addr2) || + hio_skad_get_size(addr1) != hio_skad_get_size(addr2)) return 0; switch (f1) { @@ -1637,7 +1667,7 @@ int hio_equal_skads (const hio_skad_t* addr1, const hio_skad_t* addr2, int stric #endif default: - return HIO_MEMCMP(addr1, addr2, hio_skad_size(addr1)) == 0; + return HIO_MEMCMP(addr1, addr2, hio_skad_get_size(addr1)) == 0; } }