diff options
| -rw-r--r-- | src/core/options.c | 24 | ||||
| -rw-r--r-- | src/core/options.h | 2 | ||||
| -rw-r--r-- | src/transport/zerotier/zerotier.c | 108 | ||||
| -rw-r--r-- | src/transport/zerotier/zerotier.h | 27 |
4 files changed, 154 insertions, 7 deletions
diff --git a/src/core/options.c b/src/core/options.c index 3e35f44c..843b066d 100644 --- a/src/core/options.c +++ b/src/core/options.c @@ -202,6 +202,30 @@ nni_copyin_u64(uint64_t *up, const void *v, size_t sz, nni_opt_type t) } int +nni_copyin_sockaddr(nng_sockaddr *ap, const void *v, size_t sz, nni_opt_type t) +{ + nng_sockaddr a; + + switch (t) { + case NNI_TYPE_SOCKADDR: + a = *(nng_sockaddr *) v; + break; + case NNI_TYPE_OPAQUE: + if (sz != sizeof(nng_sockaddr)) { + return (NNG_EINVAL); + } + memcpy(&a, v, sz); + break; + default: + return (NNG_EBADTYPE); + } + if (ap != NULL) { + *ap = a; + } + return (0); +} + +int nni_copyout(const void *src, size_t srcsz, void *dst, size_t *dstszp) { int rv = 0; diff --git a/src/core/options.h b/src/core/options.h index 2a21a039..ac64f9e3 100644 --- a/src/core/options.h +++ b/src/core/options.h @@ -32,6 +32,8 @@ extern int nni_copyin_size( extern int nni_copyin_str(char *, const void *, size_t, size_t, nni_opt_type); extern int nni_copyin_ptr(void **, const void *, size_t, nni_opt_type); extern int nni_copyin_u64(uint64_t *, const void *, size_t, nni_opt_type); +extern int nni_copyin_sockaddr( + nng_sockaddr *, const void *, size_t, nni_opt_type); // nni_copyout_xxx copies out a type of the named value. It assumes that // the type is aligned and the size correct, unless NNI_TYPE_OPAQUE is passed. diff --git a/src/transport/zerotier/zerotier.c b/src/transport/zerotier/zerotier.c index 59b9e83b..030d1d82 100644 --- a/src/transport/zerotier/zerotier.c +++ b/src/transport/zerotier/zerotier.c @@ -2723,6 +2723,101 @@ zt_ep_set_deorbit(void *arg, const void *data, size_t sz, nni_opt_type t) } static int +zt_ep_chk_add_local_addr(const void *data, size_t sz, nni_opt_type t) +{ + int rv; + nng_sockaddr sa; + rv = nni_copyin_sockaddr(&sa, data, sz, t); + if (rv == 0) { + switch (sa.s_family) { + case NNG_AF_INET: + case NNG_AF_INET6: + break; + default: + return (NNG_EINVAL); + } + } + return (0); +} + +static int +zt_ep_set_add_local_addr( + void *arg, const void *data, size_t sz, nni_opt_type t) +{ + nng_sockaddr sa; + zt_ep * ep = arg; + enum ZT_ResultCode zrv; + int rv; + ZT_Node * zn; + + if ((rv = nni_copyin_sockaddr(&sa, data, sz, t)) == 0) { + struct sockaddr_storage ss; + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + + memset(&ss, 0, sizeof(ss)); + switch (sa.s_family) { + case NNG_AF_INET: + sin = (void *) &ss; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = sa.s_in.sa_addr; + sin->sin_port = 0; + break; + case NNG_AF_INET6: + sin6 = (void *) &ss; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + memcpy(&sin6->sin6_addr, sa.s_in6.sa_addr, 16); + break; + default: + return (NNG_EINVAL); + } + + nni_mtx_lock(&zt_lk); + if ((ep->ze_ztn == NULL) && ((rv = zt_node_find(ep)) != 0)) { + nni_mtx_unlock(&zt_lk); + return (rv); + } + zn = ep->ze_ztn; + zrv = ZT_Node_addLocalInterfaceAddress(zn, &ss); + nni_mtx_unlock(&zt_lk); + rv = zt_result(zrv); + } + return (rv); +} + +static int +zt_ep_chk_clear_local_addrs(const void *data, size_t sz, nni_opt_type t) +{ + NNI_ARG_UNUSED(data); + NNI_ARG_UNUSED(sz); + NNI_ARG_UNUSED(t); + return (0); +} + +static int +zt_ep_set_clear_local_addrs( + void *arg, const void *data, size_t sz, nni_opt_type t) +{ + zt_ep * ep = arg; + int rv; + ZT_Node *zn; + NNI_ARG_UNUSED(data); + NNI_ARG_UNUSED(sz); + NNI_ARG_UNUSED(t); + + nni_mtx_lock(&zt_lk); + if ((ep->ze_ztn == NULL) && ((rv = zt_node_find(ep)) != 0)) { + nni_mtx_unlock(&zt_lk); + return (rv); + } + zn = ep->ze_ztn; + ZT_Node_clearLocalInterfaceAddresses(zn); + nni_mtx_unlock(&zt_lk); + return (0); +} + +static int zt_ep_get_node(void *arg, void *data, size_t *szp, nni_opt_type t) { zt_ep *ep = arg; @@ -3090,6 +3185,19 @@ static nni_tran_option zt_dialer_options[] = { .o_set = zt_ep_set_deorbit, .o_chk = zt_ep_chk_deorbit, }, + { + .o_name = NNG_OPT_ZT_ADD_LOCAL_ADDR, + .o_type = NNI_TYPE_SOCKADDR, + .o_set = zt_ep_set_add_local_addr, + .o_chk = zt_ep_chk_add_local_addr, + }, + { + .o_name = NNG_OPT_ZT_CLEAR_LOCAL_ADDRS, + .o_type = NNI_TYPE_OPAQUE, + .o_set = zt_ep_set_clear_local_addrs, + .o_chk = zt_ep_chk_clear_local_addrs, + }, + // terminate list { .o_name = NULL, diff --git a/src/transport/zerotier/zerotier.h b/src/transport/zerotier/zerotier.h index 3ba84879..ab4d8511 100644 --- a/src/transport/zerotier/zerotier.h +++ b/src/transport/zerotier/zerotier.h @@ -116,19 +116,32 @@ // node is not already orbiting, then this operation does nothing. #define NNG_OPT_ZT_DEORBIT "zt:deorbit" +// NNG_OPT_ZT_ADD_LOCAL_ADDR adds the local address (IP address) as +// local interface address. This facilitates the local startup and +// discovery. Note that this can be called multiple times to add +// additional address. This is optional, and usually not needed. +// The value is an nng_sockaddr corresponding to an IP (or IPv6) address. +#define NNG_OPT_ZT_ADD_LOCAL_ADDR "zt:add-local-addr" + +// NNG_OPT_ZT_CLEAR_LOCAL_ADDRS clears ZeroTier's notion of all +// local addresses. This may be useful when used on a mobile node, +// to reset the notion of what the local addresses are. This +// option takes no argument really. +#define NNG_OPT_ZT_CLEAR_LOCAL_ADDRS "zt:clear-local-addrs" + // Network status values. // These values are supplied to help folks checking status. They are the // return values from zt_opt_status. We avoid hard coding them as defines, // to keep applications from baking in values that may change if the // underlying ZeroTier transport changes. enum nng_zt_status { - NNG_ZT_STATUS_UP, - NNG_ZT_STATUS_CONFIG, - NNG_ZT_STATUS_DENIED, - NNG_ZT_STATUS_NOTFOUND, - NNG_ZT_STATUS_ERROR, - NNG_ZT_STATUS_OBSOLETE, - NNG_ZT_STATUS_UNKNOWN, + NNG_ZT_STATUS_UP, + NNG_ZT_STATUS_CONFIG, + NNG_ZT_STATUS_DENIED, + NNG_ZT_STATUS_NOTFOUND, + NNG_ZT_STATUS_ERROR, + NNG_ZT_STATUS_OBSOLETE, + NNG_ZT_STATUS_UNKNOWN, }; NNG_DECL int nng_zt_register(void); |
