diff --git a/hio/lib/dhcp-svr.c b/hio/lib/dhcp-svr.c index 2fe229b..d2207fd 100644 --- a/hio/lib/dhcp-svr.c +++ b/hio/lib/dhcp-svr.c @@ -34,6 +34,61 @@ struct hio_svc_dhcs_t }; +/* + binding address link address for relay. +lo ip address of lo unspec +lo/::1, [::1]:547 +lo/[::1]:544 [::1]:544 +lo/[::1]:544/xxx [::1]:544 xxx + +join multicast group?? +*/ + +struct hio_svc_dhcs_cfg_t +{ + hio_skad_t bind_addr; /* if this is link local? */ + hio_skad_t link_addr; /* want to use a different link address for relay? << if the peer address is link local, need to set this*/ + const hio_bch_t* ifce_id; /* want to set Interface-ID? */ +}; + +typedef struct hio_svc_dhcs_cfg_t hio_svc_dhcs_cfg_t; + +static hio_dev_sck_t* open_socket (hio_t* hio, hio_svc_dhcs_cfg_t* cfg) +{ + hio_dev_sck_make_t m; + 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) + { + 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.on_write = + //m.on_read = ... + //m.on_connect = ... + //m.on_disconnect = ... + sck = hio_dev_sck_make(hio, 0, &m); + if (HIO_UNLIKELY(!sck)) goto oops; + + +#if 0 + if (hio_dev_sck_joingroup(sck, mcast_addr, ifindex) <= -1) goto oops; +#endif + + + return sck; + +oops: + if (sck) hio_dev_sck_kill (sck); + return HIO_NULL; +} + hio_svc_dhcs_t* hio_svc_dhcs_start (hio_t* hio, const hio_skad_t* local_binds, hio_oow_t local_nbinds) { hio_svc_dhcs_t* dhcs; @@ -49,6 +104,7 @@ hio_svc_dhcs_t* hio_svc_dhcs_start (hio_t* hio, const hio_skad_t* local_binds, h dhcs->hio = hio; + for (i = 0; i < local_nbinds; i++) { HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); diff --git a/hio/lib/sck.c b/hio/lib/sck.c index 55057e9..c358b89 100644 --- a/hio/lib/sck.c +++ b/hio/lib/sck.c @@ -2464,12 +2464,18 @@ int hio_dev_sck_timedwritev (hio_dev_sck_t* dev, hio_iovec_t* iov, hio_iolen_t i /* ========================================================================= */ int hio_dev_sck_setsockopt (hio_dev_sck_t* dev, int level, int optname, void* optval, hio_scklen_t optlen) { - return setsockopt(dev->hnd, level, optname, optval, optlen); + int n; + n = setsockopt(dev->hnd, level, optname, optval, optlen); + if (n <= -1) hio_seterrwithsyserr (dev->hio, 0, errno); + return n; } int hio_dev_sck_getsockopt (hio_dev_sck_t* dev, int level, int optname, void* optval, hio_scklen_t* optlen) { - return getsockopt(dev->hnd, level, optname, optval, optlen); + int n; + n = getsockopt(dev->hnd, level, optname, optval, optlen); + if (n <= -1) hio_seterrwithsyserr (dev->hio, 0, errno); + return n; } int hio_dev_sck_getsockaddr (hio_dev_sck_t* dev, hio_skad_t* skad) @@ -2502,6 +2508,42 @@ 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) +{ + int f; + + f = hio_skad_family(mcast_skad); + switch (f) + { + case HIO_AF_INET: + { + struct ip_mreqn mreq; + HIO_MEMSET (&mreq, 0, HIO_SIZEOF(mreq)); + //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; + return 0; + } + + case HIO_AF_INET6: + { + 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; + return 0; + } + } + + + hio_seterrbfmt (hio_dev_sck_gethio(dev), HIO_EINVAL, "invalid multicast address family"); + return -1; +} + +/* ========================================================================= */ + int hio_dev_sck_shutdown (hio_dev_sck_t* dev, int how) { switch (how & (HIO_DEV_SCK_SHUTDOWN_READ | HIO_DEV_SCK_SHUTDOWN_WRITE))