mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 06:10:11 +01:00
platform: merge branch 'th/platform-wireguard'
Various cleanups. Also fixes a crash. https://github.com/NetworkManager/NetworkManager/pull/193
This commit is contained in:
commit
ec17242f2e
16 changed files with 1079 additions and 784 deletions
|
|
@ -31,31 +31,6 @@ typedef struct {
|
|||
guint32 to;
|
||||
} NMVlanQosMapping;
|
||||
|
||||
typedef struct {
|
||||
NMIPAddr ip;
|
||||
guint8 family;
|
||||
guint8 mask;
|
||||
} NMWireGuardAllowedIP;
|
||||
|
||||
#define NM_WG_PUBLIC_KEY_LEN 32
|
||||
#define NM_WG_SYMMETRIC_KEY_LEN 32
|
||||
|
||||
typedef struct {
|
||||
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint8 preshared_key[NM_WG_SYMMETRIC_KEY_LEN];
|
||||
union {
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
} endpoint;
|
||||
guint16 persistent_keepalive_interval;
|
||||
struct timespec last_handshake_time;
|
||||
guint64 rx_bytes, tx_bytes;
|
||||
|
||||
gsize allowedips_len;
|
||||
NMWireGuardAllowedIP *allowedips;
|
||||
} NMWireGuardPeer;
|
||||
|
||||
#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \
|
||||
( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \
|
||||
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ _get_keys (NMSettingVpn *setting,
|
|||
if (len) {
|
||||
g_ptr_array_sort (a, nm_strcmp_p);
|
||||
g_ptr_array_add (a, NULL);
|
||||
keys = g_memdup (a->pdata, a->len * sizeof (gpointer));
|
||||
keys = g_malloc (a->len * sizeof (gpointer));
|
||||
memcpy (keys, a->pdata, a->len * sizeof (gpointer));
|
||||
|
||||
/* we need to cache the keys *somewhere*. */
|
||||
g_object_set_qdata_full (G_OBJECT (setting),
|
||||
|
|
|
|||
|
|
@ -57,6 +57,11 @@ nm_hash_update (NMHashState *state, const void *ptr, gsize n)
|
|||
nm_assert (ptr);
|
||||
nm_assert (n > 0);
|
||||
|
||||
/* Note: the data passed in here might be sensitive data (secrets),
|
||||
* that we should nm_explicty_zero() afterwards. However, since
|
||||
* we are using siphash24 with a random key, that is not really
|
||||
* necessary. Something to keep in mind, if we ever move away from
|
||||
* this hash implementation. */
|
||||
c_siphash_append (&state->_state, ptr, n);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
|
|||
retval = g_vsnprintf (p, *len, format, args);
|
||||
va_end (args);
|
||||
|
||||
if (retval >= *len) {
|
||||
if ((gsize) retval >= *len) {
|
||||
*buf = &p[*len];
|
||||
*len = 0;
|
||||
} else {
|
||||
|
|
@ -115,6 +115,88 @@ nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_strbuf_seek_end:
|
||||
* @buf: the input/output buffer
|
||||
* @len: the input/output lenght of the buffer.
|
||||
*
|
||||
* Commonly, one uses nm_utils_strbuf_append*(), to incrementally
|
||||
* append strings to the buffer. However, sometimes we need to use
|
||||
* existing API to write to the buffer.
|
||||
* After doing so, we want to adjust the buffer counter.
|
||||
* Essentially,
|
||||
*
|
||||
* g_snprintf (buf, len, ...);
|
||||
* nm_utils_strbuf_seek_end (&buf, &len);
|
||||
*
|
||||
* is almost the same as
|
||||
*
|
||||
* nm_utils_strbuf_append (&buf, &len, ...);
|
||||
*
|
||||
* They only behave differently, if the string fits exactly
|
||||
* into the buffer without truncation. The former cannot distinguish
|
||||
* the two cases, while the latter can.
|
||||
*/
|
||||
void
|
||||
nm_utils_strbuf_seek_end (char **buf, gsize *len)
|
||||
{
|
||||
gsize l;
|
||||
char *end;
|
||||
|
||||
nm_assert (len);
|
||||
nm_assert (buf && *buf);
|
||||
|
||||
if (*len == 0)
|
||||
return;
|
||||
|
||||
end = memchr (*buf, 0, *len);
|
||||
if (!end) {
|
||||
/* hm, no NUL character within len bytes.
|
||||
* Just NUL terminate the array and consume them
|
||||
* all. */
|
||||
*buf += *len;
|
||||
(*buf)[-1] = '\0';
|
||||
*len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
l = end - *buf;
|
||||
nm_assert (l < *len);
|
||||
|
||||
*buf = end;
|
||||
*len -= l;
|
||||
if (*len == 1) {
|
||||
/* the last character of a buffer is the '\0'. There are two
|
||||
* cases why that may happen:
|
||||
* - but string was truncated
|
||||
* - the string fit exactly into the buffer.
|
||||
* Here we cannot distinguish between the two, so assume the string
|
||||
* was truncated and signal that by setting @len to 0 and pointing the
|
||||
* buffer *past* the end (like all other nm_utils_strbuf_*() functions).
|
||||
*
|
||||
* Note that nm_utils_strbuf_append_str() can distinguish between
|
||||
* the two cases, and leaves @len at 1, if the string was not actually
|
||||
* truncated.
|
||||
*
|
||||
* For consistancy, it might be better not to do this and just
|
||||
* seek to end of the buffer (not past it). However, that would mean,
|
||||
* in a series of
|
||||
* g_snprintf()
|
||||
* nm_utils_strbuf_seek_end()
|
||||
* the length would never reach zero, but stay at 1. With this,
|
||||
* it reaches len 0 early.
|
||||
* It seems better to declare the buffer as fully consumed and set
|
||||
* the length to zero.
|
||||
*
|
||||
* If the caller does not care about truncation, then this behavior
|
||||
* is more sensible. If the caller cares about truncation, it must
|
||||
* check earlier (right when the truncation occures).
|
||||
*/
|
||||
(*buf)++;
|
||||
*len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -190,6 +190,53 @@ nm_ip_addr_set (int addr_family, gpointer dst, const NMIPAddr *src)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
nm_utils_mem_all_zero (gconstpointer mem, gsize len)
|
||||
{
|
||||
const guint8 *p;
|
||||
|
||||
for (p = mem; len-- > 0; p++) {
|
||||
if (*p != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* incidentally, a buffer with len==0, is also *all-zero*. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* like g_memdup(). The difference is that the @size argument is of type
|
||||
* gsize, while g_memdup() has type guint. Since, the size of container types
|
||||
* like GArray is guint as well, this means trying to g_memdup() an
|
||||
* array,
|
||||
* g_memdup (array->data, array->len * sizeof (ElementType))
|
||||
* will lead to integer overflow, if there are more than G_MAXUINT/sizeof(ElementType)
|
||||
* bytes. That seems unnecessarily dangerous to me.
|
||||
* nm_memdup() avoids that, because its size argument is always large enough
|
||||
* to contain all data that a GArray can hold.
|
||||
*
|
||||
* Another minor difference to g_memdup() is that the glib version also
|
||||
* returns %NULL if @data is %NULL. E.g. g_memdup(NULL, 1)
|
||||
* gives %NULL, but nm_memdup(NULL, 1) crashes. I think that
|
||||
* is desirable, because @size MUST be correct at all times. @size
|
||||
* may be zero, but one must not claim to have non-zero bytes when
|
||||
* passing a %NULL @data pointer.
|
||||
*/
|
||||
static inline gpointer
|
||||
nm_memdup (gconstpointer data, gsize size)
|
||||
{
|
||||
gpointer p;
|
||||
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
p = g_malloc (size);
|
||||
memcpy (p, data, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern const void *const _NM_PTRARRAY_EMPTY[1];
|
||||
|
||||
#define NM_PTRARRAY_EMPTY(type) ((type const*) _NM_PTRARRAY_EMPTY)
|
||||
|
|
@ -210,6 +257,7 @@ _nm_utils_strbuf_init (char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
|
|||
void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) _nm_printf (3, 4);
|
||||
void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
|
||||
void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
|
||||
void nm_utils_strbuf_seek_end (char **buf, gsize *len);
|
||||
|
||||
const char *nm_strquote (char *buf, gsize buf_len, const char *str);
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ ck_load_cache (GHashTable *cache)
|
|||
if (error)
|
||||
goto out;
|
||||
|
||||
g_hash_table_insert (cache, GUINT_TO_POINTER (uid), g_memdup (&session, sizeof session));
|
||||
g_hash_table_insert (cache, GUINT_TO_POINTER (uid), nm_memdup (&session, sizeof session));
|
||||
}
|
||||
|
||||
finished = TRUE;
|
||||
|
|
|
|||
|
|
@ -216,8 +216,8 @@ nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP
|
|||
g_assert (b);
|
||||
|
||||
if (ignore_order) {
|
||||
a = c_a = g_memdup (a, sizeof (NMPlatformIP4Route) * len);
|
||||
b = c_b = g_memdup (b, sizeof (NMPlatformIP4Route) * len);
|
||||
a = c_a = nm_memdup (a, sizeof (NMPlatformIP4Route) * len);
|
||||
b = c_b = nm_memdup (b, sizeof (NMPlatformIP4Route) * len);
|
||||
g_qsort_with_data (c_a, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
|
||||
g_qsort_with_data (c_b, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
|
||||
}
|
||||
|
|
@ -269,8 +269,8 @@ nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP
|
|||
g_assert (b);
|
||||
|
||||
if (ignore_order) {
|
||||
a = c_a = g_memdup (a, sizeof (NMPlatformIP6Route) * len);
|
||||
b = c_b = g_memdup (b, sizeof (NMPlatformIP6Route) * len);
|
||||
a = c_a = nm_memdup (a, sizeof (NMPlatformIP6Route) * len);
|
||||
b = c_b = nm_memdup (b, sizeof (NMPlatformIP6Route) * len);
|
||||
g_qsort_with_data (c_a, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
|
||||
g_qsort_with_data (c_b, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -52,7 +52,6 @@ struct nl_msg {
|
|||
struct ucred nm_creds;
|
||||
struct nlmsghdr * nm_nlh;
|
||||
size_t nm_size;
|
||||
int nm_refcnt;
|
||||
};
|
||||
|
||||
struct nl_sock {
|
||||
|
|
@ -259,20 +258,6 @@ nlmsg_reserve (struct nl_msg *n, size_t len, int pad)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
get_default_page_size (void)
|
||||
{
|
||||
static int val = 0;
|
||||
int v;
|
||||
|
||||
if (G_UNLIKELY (val == 0)) {
|
||||
v = getpagesize ();
|
||||
g_assert (v > 0);
|
||||
val = v;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
struct nlattr *
|
||||
nla_reserve (struct nl_msg *msg, int attrtype, int attrlen)
|
||||
{
|
||||
|
|
@ -298,6 +283,22 @@ nla_reserve (struct nl_msg *msg, int attrtype, int attrlen)
|
|||
return nla;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
get_default_page_size (void)
|
||||
{
|
||||
static int val = 0;
|
||||
int v;
|
||||
|
||||
if (G_UNLIKELY (val == 0)) {
|
||||
v = getpagesize ();
|
||||
g_assert (v > 0);
|
||||
val = v;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
struct nl_msg *
|
||||
nlmsg_alloc_size (size_t len)
|
||||
{
|
||||
|
|
@ -308,7 +309,6 @@ nlmsg_alloc_size (size_t len)
|
|||
|
||||
nm = g_slice_new0 (struct nl_msg);
|
||||
|
||||
nm->nm_refcnt = 1;
|
||||
nm->nm_protocol = -1;
|
||||
nm->nm_size = len;
|
||||
nm->nm_nlh = g_malloc0 (len);
|
||||
|
|
@ -331,27 +331,6 @@ nlmsg_alloc (void)
|
|||
return nlmsg_alloc_size (get_default_page_size ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new netlink message with maximum payload size specified.
|
||||
*/
|
||||
struct nl_msg *
|
||||
nlmsg_alloc_inherit (struct nlmsghdr *hdr)
|
||||
{
|
||||
struct nl_msg *nm;
|
||||
|
||||
nm = nlmsg_alloc ();
|
||||
if (hdr) {
|
||||
struct nlmsghdr *new = nm->nm_nlh;
|
||||
|
||||
new->nlmsg_type = hdr->nlmsg_type;
|
||||
new->nlmsg_flags = hdr->nlmsg_flags;
|
||||
new->nlmsg_seq = hdr->nlmsg_seq;
|
||||
new->nlmsg_pid = hdr->nlmsg_pid;
|
||||
}
|
||||
|
||||
return nm;
|
||||
}
|
||||
|
||||
struct nl_msg *
|
||||
nlmsg_alloc_convert (struct nlmsghdr *hdr)
|
||||
{
|
||||
|
|
@ -365,14 +344,27 @@ nlmsg_alloc_convert (struct nlmsghdr *hdr)
|
|||
struct nl_msg *
|
||||
nlmsg_alloc_simple (int nlmsgtype, int flags)
|
||||
{
|
||||
struct nlmsghdr nlh = {
|
||||
.nlmsg_type = nlmsgtype,
|
||||
.nlmsg_flags = flags,
|
||||
};
|
||||
struct nl_msg *nm;
|
||||
struct nlmsghdr *new;
|
||||
|
||||
return nlmsg_alloc_inherit (&nlh);
|
||||
nm = nlmsg_alloc ();
|
||||
new = nm->nm_nlh;
|
||||
new->nlmsg_type = nlmsgtype;
|
||||
new->nlmsg_flags = flags;
|
||||
return nm;
|
||||
}
|
||||
|
||||
void nlmsg_free (struct nl_msg *msg)
|
||||
{
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
g_free (msg->nm_nlh);
|
||||
g_slice_free (struct nl_msg, msg);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
nlmsg_append (struct nl_msg *n, void *data, size_t len, int pad)
|
||||
{
|
||||
|
|
@ -386,6 +378,8 @@ nlmsg_append (struct nl_msg *n, void *data, size_t len, int pad)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
||||
int maxtype, const struct nla_policy *policy)
|
||||
|
|
@ -639,22 +633,6 @@ errout:
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nlmsg_free (struct nl_msg *msg)
|
||||
{
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
if (msg->nm_refcnt < 1)
|
||||
g_return_if_reached ();
|
||||
|
||||
msg->nm_refcnt--;
|
||||
|
||||
if (msg->nm_refcnt <= 0) {
|
||||
g_free (msg->nm_nlh);
|
||||
g_slice_free (struct nl_msg, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nlmsg_get_proto (struct nl_msg *msg)
|
||||
{
|
||||
|
|
@ -813,7 +791,7 @@ int
|
|||
genl_ctrl_resolve (struct nl_sock *sk, const char *name)
|
||||
{
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
int result = -ENOMEM;
|
||||
int nlerr;
|
||||
gint32 response_data = -1;
|
||||
const struct nl_cb cb = {
|
||||
.valid_cb = _genl_parse_getfamily,
|
||||
|
|
@ -824,31 +802,29 @@ genl_ctrl_resolve (struct nl_sock *sk, const char *name)
|
|||
|
||||
if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
|
||||
0, 0, CTRL_CMD_GETFAMILY, 1))
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
|
||||
if (nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name) < 0)
|
||||
goto out;
|
||||
nlerr = nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name);
|
||||
if (nlerr < 0)
|
||||
return nlerr;
|
||||
|
||||
result = nl_send_auto (sk, msg);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
nlerr = nl_send_auto (sk, msg);
|
||||
if (nlerr < 0)
|
||||
return nlerr;
|
||||
|
||||
result = nl_recvmsgs (sk, &cb);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
nlerr = nl_recvmsgs (sk, &cb);
|
||||
if (nlerr < 0)
|
||||
return nlerr;
|
||||
|
||||
/* If search was successful, request may be ACKed after data */
|
||||
result = nl_wait_for_ack (sk, NULL);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
nlerr = nl_wait_for_ack (sk, NULL);
|
||||
if (nlerr < 0)
|
||||
return nlerr;
|
||||
|
||||
if (response_data > 0)
|
||||
result = response_data;
|
||||
else
|
||||
result = -ENOENT;
|
||||
if (response_data < 0)
|
||||
return -NLE_UNSPEC;
|
||||
|
||||
out:
|
||||
return result;
|
||||
return response_data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1131,6 +1107,10 @@ do { \
|
|||
case NL_STOP: \
|
||||
goto stop; \
|
||||
default: \
|
||||
if (err >= 0) { \
|
||||
nm_assert_not_reached (); \
|
||||
err = -NLE_BUG; \
|
||||
} \
|
||||
goto out; \
|
||||
} \
|
||||
} \
|
||||
|
|
@ -1238,11 +1218,12 @@ continue_reading:
|
|||
else if (err == NL_SKIP)
|
||||
goto skip;
|
||||
else if (err == NL_STOP) {
|
||||
err = -e->error;
|
||||
err = -nl_syserr2nlerr (e->error);
|
||||
goto out;
|
||||
}
|
||||
nm_assert (err == NL_OK);
|
||||
} else {
|
||||
err = -e->error;
|
||||
err = -nl_syserr2nlerr (e->error);
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
|
|
@ -1273,6 +1254,7 @@ out:
|
|||
if (interrupted)
|
||||
err = -NLE_DUMP_INTR;
|
||||
|
||||
nm_assert (err <= 0);
|
||||
return err ?: nrecv;
|
||||
}
|
||||
|
||||
|
|
@ -1328,7 +1310,7 @@ nl_send_iovec (struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsign
|
|||
memcpy(CMSG_DATA(cmsg), creds, sizeof (struct ucred));
|
||||
}
|
||||
|
||||
return nl_sendmsg(sk, msg, &hdr);
|
||||
return nl_sendmsg (sk, msg, &hdr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1365,9 +1347,9 @@ nl_send (struct nl_sock *sk, struct nl_msg *msg)
|
|||
|
||||
int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
|
||||
{
|
||||
nl_complete_msg(sk, msg);
|
||||
nl_complete_msg (sk, msg);
|
||||
|
||||
return nl_send(sk, msg);
|
||||
return nl_send (sk, msg);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1470,7 +1452,7 @@ retry:
|
|||
continue;
|
||||
if (cmsg->cmsg_type != SCM_CREDENTIALS)
|
||||
continue;
|
||||
tmpcreds = g_memdup (CMSG_DATA(cmsg), sizeof (*tmpcreds));
|
||||
tmpcreds = nm_memdup (CMSG_DATA(cmsg), sizeof (*tmpcreds));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ nl_errno (int err)
|
|||
* normalizes the error and returns its positive value. */
|
||||
return err >= 0
|
||||
? err
|
||||
: ((err == G_MININT) ? NLE_BUG : -errno);
|
||||
: ((err == G_MININT) ? NLE_BUG : -err);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
@ -314,8 +314,6 @@ struct nl_msg *nlmsg_alloc (void);
|
|||
|
||||
struct nl_msg *nlmsg_alloc_size (size_t max);
|
||||
|
||||
struct nl_msg *nlmsg_alloc_inherit (struct nlmsghdr *hdr);
|
||||
|
||||
struct nl_msg *nlmsg_alloc_convert (struct nlmsghdr *hdr);
|
||||
|
||||
struct nl_msg *nlmsg_alloc_simple (int nlmsgtype, int flags);
|
||||
|
|
|
|||
|
|
@ -5532,67 +5532,57 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize
|
|||
}
|
||||
|
||||
const char *
|
||||
nm_platform_wireguard_peer_to_string (const NMWireGuardPeer *peer, char *buf, gsize len)
|
||||
nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, gsize len)
|
||||
{
|
||||
gs_free char *public_b64 = NULL;
|
||||
char s_address[INET6_ADDRSTRLEN] = {0};
|
||||
char s_endpoint[INET6_ADDRSTRLEN + NI_MAXSERV + sizeof("endpoint []:") + 1] = {0};
|
||||
guint8 nonzero_key = 0;
|
||||
gsize i;
|
||||
gs_free char *public_key_b64 = NULL;
|
||||
char s_endpoint[NM_UTILS_INET_ADDRSTRLEN + 100];
|
||||
char s_addr[NM_UTILS_INET_ADDRSTRLEN];
|
||||
guint i;
|
||||
|
||||
nm_utils_to_string_buffer_init (&buf, &len);
|
||||
|
||||
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) {
|
||||
char s_service[NI_MAXSERV];
|
||||
socklen_t addr_len = 0;
|
||||
if (peer->endpoint_family == AF_INET) {
|
||||
nm_sprintf_buf (s_endpoint,
|
||||
" endpoint %s:%u",
|
||||
nm_utils_inet4_ntop (peer->endpoint_addr.addr4, s_addr),
|
||||
(guint) peer->endpoint_port);
|
||||
} else if (peer->endpoint_family == AF_INET6) {
|
||||
nm_sprintf_buf (s_endpoint,
|
||||
" endpoint [%s]:%u",
|
||||
nm_utils_inet6_ntop (&peer->endpoint_addr.addr6, s_addr),
|
||||
(guint) peer->endpoint_port);
|
||||
} else
|
||||
s_endpoint[0] = '\0';
|
||||
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
addr_len = sizeof (struct sockaddr_in);
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
addr_len = sizeof (struct sockaddr_in6);
|
||||
if (!getnameinfo (&peer->endpoint.addr, addr_len, s_address, sizeof(s_address), s_service, sizeof(s_service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
|
||||
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr (s_address, ':'))
|
||||
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint [%s]:%s ", s_address, s_service);
|
||||
else
|
||||
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint %s:%s ", s_address, s_service);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < sizeof (peer->preshared_key); i++)
|
||||
nonzero_key |= peer->preshared_key[i];
|
||||
|
||||
public_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
|
||||
public_key_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
|
||||
|
||||
nm_utils_strbuf_append (&buf, &len,
|
||||
"{ "
|
||||
"public_key %s "
|
||||
"%s" /* preshared key indicator */
|
||||
"public-key %s"
|
||||
"%s" /* preshared-key */
|
||||
"%s" /* endpoint */
|
||||
"rx %"G_GUINT64_FORMAT" "
|
||||
"tx %"G_GUINT64_FORMAT" "
|
||||
"allowedips (%"G_GSIZE_FORMAT") {",
|
||||
public_b64,
|
||||
nonzero_key ? "preshared_key (hidden) " : "",
|
||||
" rx %"G_GUINT64_FORMAT
|
||||
" tx %"G_GUINT64_FORMAT
|
||||
"%s", /* allowed-ips */
|
||||
public_key_b64,
|
||||
nm_utils_mem_all_zero (peer->preshared_key, sizeof (peer->preshared_key))
|
||||
? ""
|
||||
: " preshared-key (hidden)",
|
||||
s_endpoint,
|
||||
peer->rx_bytes,
|
||||
peer->tx_bytes,
|
||||
peer->allowedips_len);
|
||||
peer->allowed_ips_len > 0
|
||||
? " allowed-ips"
|
||||
: "");
|
||||
|
||||
|
||||
for (i = 0; i < peer->allowedips_len; i++) {
|
||||
NMWireGuardAllowedIP *allowedip = &peer->allowedips[i];
|
||||
const char *ret;
|
||||
|
||||
ret = inet_ntop (allowedip->family, &allowedip->ip, s_address, sizeof(s_address));
|
||||
for (i = 0; i < peer->allowed_ips_len; i++) {
|
||||
const NMPWireGuardAllowedIP *allowed_ip = &peer->allowed_ips[i];
|
||||
|
||||
nm_utils_strbuf_append (&buf, &len,
|
||||
" %s/%u",
|
||||
ret ? s_address : "<EAFNOSUPPORT>",
|
||||
allowedip->mask);
|
||||
nm_utils_inet_ntop (allowed_ip->family, &allowed_ip->addr, s_addr),
|
||||
allowed_ip->mask);
|
||||
}
|
||||
|
||||
nm_utils_strbuf_append_str (&buf, &len, " } }");
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
@ -5600,25 +5590,26 @@ const char *
|
|||
nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len)
|
||||
{
|
||||
gs_free char *public_b64 = NULL;
|
||||
guint8 nonzero_key = 0;
|
||||
gsize i;
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len))
|
||||
return buf;
|
||||
|
||||
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key));
|
||||
|
||||
for (i = 0; i < sizeof (lnk->private_key); i++)
|
||||
nonzero_key |= lnk->private_key[i];
|
||||
if (!nm_utils_mem_all_zero (lnk->public_key, sizeof (lnk->public_key)))
|
||||
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key));
|
||||
|
||||
g_snprintf (buf, len,
|
||||
"wireguard "
|
||||
"public_key %s "
|
||||
"%s" /* private key indicator */
|
||||
"listen_port %u "
|
||||
"fwmark 0x%x",
|
||||
public_b64,
|
||||
nonzero_key ? "private_key (hidden) " : "",
|
||||
"wireguard"
|
||||
"%s%s" /* public-key */
|
||||
"%s" /* private-key */
|
||||
" listen-port %u"
|
||||
" fwmark 0x%x",
|
||||
public_b64
|
||||
? " public-key "
|
||||
: "",
|
||||
public_b64 ?: "",
|
||||
nm_utils_mem_all_zero (lnk->private_key, sizeof (lnk->private_key))
|
||||
? ""
|
||||
: " private-key (hidden)",
|
||||
lnk->listen_port,
|
||||
lnk->fwmark);
|
||||
|
||||
|
|
|
|||
|
|
@ -752,11 +752,14 @@ typedef struct {
|
|||
bool l3miss:1;
|
||||
} NMPlatformLnkVxlan;
|
||||
|
||||
#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32
|
||||
#define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32
|
||||
|
||||
typedef struct {
|
||||
guint8 private_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint16 listen_port;
|
||||
guint32 fwmark;
|
||||
guint16 listen_port;
|
||||
guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
|
||||
guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
|
||||
} NMPlatformLnkWireGuard;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -1463,7 +1466,8 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
|
|||
char *buf,
|
||||
gsize len);
|
||||
|
||||
const char *nm_platform_wireguard_peer_to_string (const NMWireGuardPeer *peer,
|
||||
struct _NMPWireGuardPeer;
|
||||
const char *nm_platform_wireguard_peer_to_string (const struct _NMPWireGuardPeer *peer,
|
||||
char *buf,
|
||||
gsize len);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <libudev.h>
|
||||
|
||||
#include "nm-utils.h"
|
||||
#include "nm-utils/nm-secret-utils.h"
|
||||
|
||||
#include "nm-core-utils.h"
|
||||
#include "nm-platform-utils.h"
|
||||
|
|
@ -340,124 +341,99 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
|
|||
g_clear_pointer (dst_map, g_free);
|
||||
*dst_n_map = src_n_map;
|
||||
if (src_n_map > 0)
|
||||
*dst_map = g_memdup (src_map, sizeof (*src_map) * src_n_map);
|
||||
*dst_map = nm_memdup (src_map, sizeof (*src_map) * src_n_map);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_wireguard_peers_hash_update (gsize n_peers,
|
||||
const NMWireGuardPeer *peers,
|
||||
NMHashState *h)
|
||||
_wireguard_allowed_ip_hash_update (const NMPWireGuardAllowedIP *ip,
|
||||
NMHashState *h)
|
||||
{
|
||||
gsize i, j;
|
||||
nm_hash_update_vals (h, ip->family,
|
||||
ip->mask);
|
||||
|
||||
nm_hash_update_val (h, n_peers);
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
const NMWireGuardPeer *p = &peers[i];
|
||||
|
||||
nm_hash_update (h, p->public_key, sizeof (p->public_key));
|
||||
nm_hash_update (h, p->preshared_key, sizeof (p->preshared_key));
|
||||
nm_hash_update_vals (h,
|
||||
p->persistent_keepalive_interval,
|
||||
p->allowedips_len,
|
||||
p->rx_bytes,
|
||||
p->tx_bytes,
|
||||
p->last_handshake_time.tv_sec,
|
||||
p->last_handshake_time.tv_nsec,
|
||||
p->endpoint.addr.sa_family);
|
||||
|
||||
if (p->endpoint.addr.sa_family == AF_INET)
|
||||
nm_hash_update_val (h, p->endpoint.addr4);
|
||||
else if (p->endpoint.addr.sa_family == AF_INET6)
|
||||
nm_hash_update_val (h, p->endpoint.addr6);
|
||||
else if (p->endpoint.addr.sa_family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
|
||||
for (j = 0; j < p->allowedips_len; j++) {
|
||||
const NMWireGuardAllowedIP *ip = &p->allowedips[j];
|
||||
|
||||
nm_hash_update_vals (h, ip->family, ip->mask);
|
||||
|
||||
if (ip->family == AF_INET)
|
||||
nm_hash_update_val (h, ip->ip.addr4);
|
||||
else if (ip->family == AF_INET6)
|
||||
nm_hash_update_val (h, ip->ip.addr6);
|
||||
else if (ip->family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
if (ip->family == AF_INET)
|
||||
nm_hash_update_val (h, ip->addr.addr4);
|
||||
else if (ip->family == AF_INET6)
|
||||
nm_hash_update_val (h, ip->addr.addr6);
|
||||
}
|
||||
|
||||
static int
|
||||
_wireguard_peers_cmp (gsize n_peers,
|
||||
const NMWireGuardPeer *p1,
|
||||
const NMWireGuardPeer *p2)
|
||||
_wireguard_allowed_ip_cmp (const NMPWireGuardAllowedIP *a,
|
||||
const NMPWireGuardAllowedIP *b)
|
||||
{
|
||||
gsize i, j;
|
||||
NM_CMP_SELF (a, b);
|
||||
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
const NMWireGuardPeer *a = &p1[i];
|
||||
const NMWireGuardPeer *b = &p2[i];
|
||||
NM_CMP_FIELD (a, b, family);
|
||||
NM_CMP_FIELD (a, b, mask);
|
||||
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec);
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec);
|
||||
NM_CMP_FIELD (a, b, rx_bytes);
|
||||
NM_CMP_FIELD (a, b, tx_bytes);
|
||||
NM_CMP_FIELD (a, b, allowedips_len);
|
||||
NM_CMP_FIELD (a, b, persistent_keepalive_interval);
|
||||
NM_CMP_FIELD (a, b, endpoint.addr.sa_family);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, public_key);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
|
||||
|
||||
if (a->endpoint.addr.sa_family == AF_INET)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr4);
|
||||
else if (a->endpoint.addr.sa_family == AF_INET6)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr6);
|
||||
else if (a->endpoint.addr.sa_family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
|
||||
for (j = 0; j < a->allowedips_len; j++) {
|
||||
const NMWireGuardAllowedIP *aip = &a->allowedips[j];
|
||||
const NMWireGuardAllowedIP *bip = &b->allowedips[j];
|
||||
|
||||
NM_CMP_FIELD (aip, bip, family);
|
||||
NM_CMP_FIELD (aip, bip, mask);
|
||||
|
||||
if (aip->family == AF_INET)
|
||||
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr4);
|
||||
else if (aip->family == AF_INET6)
|
||||
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr6);
|
||||
else if (aip->family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
if (a->family == AF_INET)
|
||||
NM_CMP_FIELD (a, b, addr.addr4);
|
||||
else if (a->family == AF_INET6)
|
||||
NM_CMP_FIELD_IN6ADDR (a, b, addr.addr6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_wireguard_peers_cpy (gsize *dst_n_peers,
|
||||
NMWireGuardPeer **dst_peers,
|
||||
gsize src_n_peers,
|
||||
const NMWireGuardPeer *src_peers)
|
||||
_wireguard_peer_hash_update (const NMPWireGuardPeer *peer,
|
||||
NMHashState *h)
|
||||
{
|
||||
if (src_n_peers == 0) {
|
||||
g_clear_pointer (dst_peers, g_free);
|
||||
*dst_n_peers = 0;
|
||||
} else if ( src_n_peers != *dst_n_peers
|
||||
|| _wireguard_peers_cmp (src_n_peers, *dst_peers, src_peers) != 0) {
|
||||
gsize i;
|
||||
g_clear_pointer (dst_peers, g_free);
|
||||
*dst_n_peers = src_n_peers;
|
||||
if (src_n_peers > 0)
|
||||
*dst_peers = g_memdup (src_peers, sizeof (*src_peers) * src_n_peers);
|
||||
for (i = 0; i < src_n_peers; i++) {
|
||||
dst_peers[i]->allowedips = g_memdup (src_peers[i].allowedips, sizeof (src_peers[i].allowedips) * src_peers[i].allowedips_len);
|
||||
dst_peers[i]->allowedips_len = src_peers[i].allowedips_len;
|
||||
}
|
||||
guint i;
|
||||
|
||||
nm_hash_update (h, peer->public_key, sizeof (peer->public_key));
|
||||
nm_hash_update (h, peer->preshared_key, sizeof (peer->preshared_key));
|
||||
nm_hash_update_vals (h,
|
||||
peer->persistent_keepalive_interval,
|
||||
peer->allowed_ips_len,
|
||||
peer->rx_bytes,
|
||||
peer->tx_bytes,
|
||||
peer->last_handshake_time.tv_sec,
|
||||
peer->last_handshake_time.tv_nsec,
|
||||
peer->endpoint_port,
|
||||
peer->endpoint_family);
|
||||
|
||||
if (peer->endpoint_family == AF_INET)
|
||||
nm_hash_update_val (h, peer->endpoint_addr.addr4);
|
||||
else if (peer->endpoint_family == AF_INET6)
|
||||
nm_hash_update_val (h, peer->endpoint_addr.addr6);
|
||||
|
||||
for (i = 0; i < peer->allowed_ips_len; i++)
|
||||
_wireguard_allowed_ip_hash_update (&peer->allowed_ips[i], h);
|
||||
}
|
||||
|
||||
static int
|
||||
_wireguard_peer_cmp (const NMPWireGuardPeer *a,
|
||||
const NMPWireGuardPeer *b)
|
||||
{
|
||||
guint i;
|
||||
|
||||
NM_CMP_SELF (a, b);
|
||||
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec);
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec);
|
||||
NM_CMP_FIELD (a, b, rx_bytes);
|
||||
NM_CMP_FIELD (a, b, tx_bytes);
|
||||
NM_CMP_FIELD (a, b, allowed_ips_len);
|
||||
NM_CMP_FIELD (a, b, persistent_keepalive_interval);
|
||||
NM_CMP_FIELD (a, b, endpoint_port);
|
||||
NM_CMP_FIELD (a, b, endpoint_family);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, public_key);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
|
||||
|
||||
if (a->endpoint_family == AF_INET)
|
||||
NM_CMP_FIELD (a, b, endpoint_addr.addr4);
|
||||
else if (a->endpoint_family == AF_INET6)
|
||||
NM_CMP_FIELD_IN6ADDR (a, b, endpoint_addr.addr6);
|
||||
|
||||
for (i = 0; i < a->allowed_ips_len; i++) {
|
||||
NM_CMP_RETURN (_wireguard_allowed_ip_cmp (&a->allowed_ips[i],
|
||||
&b->allowed_ips[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -586,13 +562,26 @@ _vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj)
|
|||
g_free ((gpointer) obj->_lnk_vlan.egress_qos_map);
|
||||
}
|
||||
|
||||
static void
|
||||
_wireguard_clear (NMPObjectLnkWireGuard *lnk)
|
||||
{
|
||||
guint i;
|
||||
|
||||
nm_explicit_bzero (lnk->_public.private_key,
|
||||
sizeof (lnk->_public.private_key));
|
||||
for (i = 0; i < lnk->peers_len; i++) {
|
||||
NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &lnk->peers[i];
|
||||
|
||||
nm_explicit_bzero (peer->preshared_key, sizeof (peer->preshared_key));
|
||||
}
|
||||
g_free ((gpointer) lnk->peers);
|
||||
g_free ((gpointer) lnk->_allowed_ips_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj)
|
||||
{
|
||||
if (obj->_lnk_wireguard.peers_len)
|
||||
g_free (obj->_lnk_wireguard.peers[0].allowedips);
|
||||
|
||||
g_free (obj->_lnk_wireguard.peers);
|
||||
_wireguard_clear (&obj->_lnk_wireguard);
|
||||
}
|
||||
|
||||
static NMPObject *
|
||||
|
|
@ -760,31 +749,35 @@ static const char *
|
|||
_vt_cmd_obj_to_string_link (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size)
|
||||
{
|
||||
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
char buf2[sizeof (_nm_utils_to_string_buffer)];
|
||||
char buf3[sizeof (_nm_utils_to_string_buffer)];
|
||||
char *b = buf;
|
||||
|
||||
switch (to_string_mode) {
|
||||
case NMP_OBJECT_TO_STRING_ID:
|
||||
return klass->cmd_plobj_to_string_id (&obj->object, buf, buf_size);
|
||||
case NMP_OBJECT_TO_STRING_ALL:
|
||||
g_snprintf (buf, buf_size,
|
||||
"[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; %s]",
|
||||
klass->obj_type_name, obj, obj->parent._ref_count,
|
||||
nmp_object_is_alive (obj) ? '+' : '-',
|
||||
nmp_object_is_visible (obj) ? '+' : '-',
|
||||
obj->_link.netlink.is_in_netlink ? '+' : '-',
|
||||
obj->_link.udev.device,
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)));
|
||||
nm_utils_strbuf_append (&b, &buf_size,
|
||||
"[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ",
|
||||
klass->obj_type_name, obj, obj->parent._ref_count,
|
||||
nmp_object_is_alive (obj) ? '+' : '-',
|
||||
nmp_object_is_visible (obj) ? '+' : '-',
|
||||
obj->_link.netlink.is_in_netlink ? '+' : '-',
|
||||
obj->_link.udev.device);
|
||||
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size);
|
||||
nm_utils_strbuf_seek_end (&b, &buf_size);
|
||||
if (obj->_link.netlink.lnk) {
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, "; ");
|
||||
nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_ALL, b, buf_size);
|
||||
nm_utils_strbuf_seek_end (&b, &buf_size);
|
||||
}
|
||||
nm_utils_strbuf_append_c (&b, &buf_size, ']');
|
||||
return buf;
|
||||
case NMP_OBJECT_TO_STRING_PUBLIC:
|
||||
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size);
|
||||
if (obj->_link.netlink.lnk) {
|
||||
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf2, sizeof (buf2));
|
||||
nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, buf3, sizeof (buf3));
|
||||
g_snprintf (buf, buf_size,
|
||||
"%s; %s",
|
||||
buf2, buf3);
|
||||
} else
|
||||
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size);
|
||||
nm_utils_strbuf_seek_end (&b, &buf_size);
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, "; ");
|
||||
nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, b, buf_size);
|
||||
}
|
||||
return buf;
|
||||
default:
|
||||
g_return_val_if_reached ("ERROR");
|
||||
|
|
@ -855,7 +848,7 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
|
|||
const NMPClass *klass;
|
||||
char buf2[sizeof (_nm_utils_to_string_buffer)];
|
||||
char *b;
|
||||
gsize i, l;
|
||||
guint i;
|
||||
|
||||
klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
|
||||
|
|
@ -867,23 +860,26 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
|
|||
b = buf;
|
||||
|
||||
nm_utils_strbuf_append (&b, &buf_size,
|
||||
"[%s,%p,%u,%calive,%cvisible; %s "
|
||||
"peers (%" G_GSIZE_FORMAT ") {",
|
||||
"[%s,%p,%u,%calive,%cvisible; %s"
|
||||
"%s",
|
||||
klass->obj_type_name, obj, obj->parent._ref_count,
|
||||
nmp_object_is_alive (obj) ? '+' : '-',
|
||||
nmp_object_is_visible (obj) ? '+' : '-',
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)),
|
||||
obj->_lnk_wireguard.peers_len);
|
||||
obj->_lnk_wireguard.peers_len > 0
|
||||
? " peers {"
|
||||
: "");
|
||||
|
||||
for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) {
|
||||
const NMWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i];
|
||||
nm_platform_wireguard_peer_to_string (peer, b, buf_size);
|
||||
l = strlen (b);
|
||||
b += l;
|
||||
buf_size -= l;
|
||||
}
|
||||
const NMPWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i];
|
||||
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, " }");
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, " { ");
|
||||
nm_platform_wireguard_peer_to_string (peer, b, buf_size);
|
||||
nm_utils_strbuf_seek_end (&b, &buf_size);
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, " }");
|
||||
}
|
||||
if (obj->_lnk_wireguard.peers_len)
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, " }");
|
||||
|
||||
return buf;
|
||||
case NMP_OBJECT_TO_STRING_PUBLIC:
|
||||
|
|
@ -943,6 +939,7 @@ _vt_cmd_obj_hash_update_link (const NMPObject *obj, NMHashState *h)
|
|||
nm_platform_link_hash_update (&obj->link, h);
|
||||
nm_hash_update_vals (h,
|
||||
obj->_link.netlink.is_in_netlink,
|
||||
obj->_link.wireguard_family_id,
|
||||
obj->_link.udev.device);
|
||||
if (obj->_link.netlink.lnk)
|
||||
nmp_object_hash_update (obj->_link.netlink.lnk, h);
|
||||
|
|
@ -965,10 +962,15 @@ _vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h)
|
|||
static void
|
||||
_vt_cmd_obj_hash_update_lnk_wireguard (const NMPObject *obj, NMHashState *h)
|
||||
{
|
||||
guint i;
|
||||
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD);
|
||||
|
||||
nm_platform_lnk_wireguard_hash_update (&obj->lnk_wireguard, h);
|
||||
_wireguard_peers_hash_update (obj->_lnk_wireguard.peers_len, obj->_lnk_wireguard.peers, h);
|
||||
|
||||
nm_hash_update_val (h, obj->_lnk_wireguard.peers_len);
|
||||
for (i = 0; i < obj->_lnk_wireguard.peers_len; i++)
|
||||
_wireguard_peer_hash_update (&obj->_lnk_wireguard.peers[i], h);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -976,12 +978,7 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
|
|||
{
|
||||
const NMPClass *klass1, *klass2;
|
||||
|
||||
if (obj1 == obj2)
|
||||
return 0;
|
||||
if (!obj1)
|
||||
return -1;
|
||||
if (!obj2)
|
||||
return 1;
|
||||
NM_CMP_SELF (obj1, obj2);
|
||||
|
||||
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), -1);
|
||||
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj2), 1);
|
||||
|
|
@ -1002,16 +999,11 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
|
|||
static int
|
||||
_vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2)
|
||||
{
|
||||
int i;
|
||||
NM_CMP_RETURN (nm_platform_link_cmp (&obj1->link, &obj2->link));
|
||||
NM_CMP_DIRECT (obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink);
|
||||
NM_CMP_RETURN (nmp_object_cmp (obj1->_link.netlink.lnk, obj2->_link.netlink.lnk));
|
||||
NM_CMP_DIRECT (obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id);
|
||||
|
||||
i = nm_platform_link_cmp (&obj1->link, &obj2->link);
|
||||
if (i)
|
||||
return i;
|
||||
if (obj1->_link.netlink.is_in_netlink != obj2->_link.netlink.is_in_netlink)
|
||||
return obj1->_link.netlink.is_in_netlink ? -1 : 1;
|
||||
i = nmp_object_cmp (obj1->_link.netlink.lnk, obj2->_link.netlink.lnk);
|
||||
if (i)
|
||||
return i;
|
||||
if (obj1->_link.udev.device != obj2->_link.udev.device) {
|
||||
if (!obj1->_link.udev.device)
|
||||
return -1;
|
||||
|
|
@ -1024,6 +1016,7 @@ _vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2)
|
|||
* Have this check as very last. */
|
||||
return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1052,16 +1045,16 @@ _vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2)
|
|||
static int
|
||||
_vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2)
|
||||
{
|
||||
int c;
|
||||
guint i;
|
||||
|
||||
c = nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard);
|
||||
if (c)
|
||||
return c;
|
||||
NM_CMP_RETURN (nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard));
|
||||
|
||||
if (obj1->_lnk_wireguard.peers_len != obj2->_lnk_wireguard.peers_len)
|
||||
return obj1->_lnk_wireguard.peers_len < obj2->_lnk_wireguard.peers_len ? -1 : 1;
|
||||
NM_CMP_FIELD (obj1, obj2, _lnk_wireguard.peers_len);
|
||||
|
||||
return _wireguard_peers_cmp(obj1->_lnk_wireguard.peers_len, obj1->_lnk_wireguard.peers, obj2->_lnk_wireguard.peers);
|
||||
for (i = 0; i < obj1->_lnk_wireguard.peers_len; i++)
|
||||
NM_CMP_RETURN (_wireguard_peer_cmp (&obj1->_lnk_wireguard.peers[i], &obj2->_lnk_wireguard.peers[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @src is a const object, which is not entirely correct for link types, where
|
||||
|
|
@ -1133,9 +1126,36 @@ _vt_cmd_obj_copy_lnk_vlan (NMPObject *dst, const NMPObject *src)
|
|||
static void
|
||||
_vt_cmd_obj_copy_lnk_wireguard (NMPObject *dst, const NMPObject *src)
|
||||
{
|
||||
dst->lnk_wireguard = src->lnk_wireguard;
|
||||
_wireguard_peers_cpy (&dst->_lnk_wireguard.peers_len, &dst->_lnk_wireguard.peers,
|
||||
src->_lnk_wireguard.peers_len, src->_lnk_wireguard.peers);
|
||||
guint i;
|
||||
|
||||
nm_assert (dst != src);
|
||||
|
||||
_wireguard_clear (&dst->_lnk_wireguard);
|
||||
|
||||
dst->_lnk_wireguard = src->_lnk_wireguard;
|
||||
|
||||
dst->_lnk_wireguard.peers = nm_memdup (dst->_lnk_wireguard.peers,
|
||||
sizeof (NMPWireGuardPeer) * dst->_lnk_wireguard.peers_len);
|
||||
dst->_lnk_wireguard._allowed_ips_buf = nm_memdup (dst->_lnk_wireguard._allowed_ips_buf,
|
||||
sizeof (NMPWireGuardAllowedIP) * dst->_lnk_wireguard._allowed_ips_buf_len);
|
||||
|
||||
/* all the peers' pointers point into the buffer. They need to be readjusted. */
|
||||
for (i = 0; i < dst->_lnk_wireguard.peers_len; i++) {
|
||||
NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &dst->_lnk_wireguard.peers[i];
|
||||
|
||||
if (peer->allowed_ips_len == 0) {
|
||||
nm_assert (!peer->allowed_ips);
|
||||
continue;
|
||||
}
|
||||
nm_assert (dst->_lnk_wireguard._allowed_ips_buf_len > 0);
|
||||
nm_assert (src->_lnk_wireguard._allowed_ips_buf);
|
||||
nm_assert (peer->allowed_ips >= src->_lnk_wireguard._allowed_ips_buf);
|
||||
nm_assert (&peer->allowed_ips[peer->allowed_ips_len] <= &src->_lnk_wireguard._allowed_ips_buf[src->_lnk_wireguard._allowed_ips_buf_len]);
|
||||
|
||||
peer->allowed_ips = &dst->_lnk_wireguard._allowed_ips_buf[peer->allowed_ips - src->_lnk_wireguard._allowed_ips_buf];
|
||||
}
|
||||
|
||||
nm_assert (nmp_object_equal (src, dst));
|
||||
}
|
||||
|
||||
#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \
|
||||
|
|
@ -3080,4 +3100,3 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,36 @@
|
|||
|
||||
struct udev_device;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMIPAddr addr;
|
||||
guint8 family;
|
||||
guint8 mask;
|
||||
} NMPWireGuardAllowedIP;
|
||||
|
||||
typedef struct _NMPWireGuardPeer {
|
||||
NMIPAddr endpoint_addr;
|
||||
struct timespec last_handshake_time;
|
||||
guint64 rx_bytes;
|
||||
guint64 tx_bytes;
|
||||
union {
|
||||
const NMPWireGuardAllowedIP *allowed_ips;
|
||||
guint _construct_idx_start;
|
||||
};
|
||||
union {
|
||||
guint allowed_ips_len;
|
||||
guint _construct_idx_end;
|
||||
};
|
||||
guint16 persistent_keepalive_interval;
|
||||
guint16 endpoint_port;
|
||||
guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
|
||||
guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN];
|
||||
guint8 endpoint_family;
|
||||
} NMPWireGuardPeer;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
NMP_OBJECT_TO_STRING_ID,
|
||||
NMP_OBJECT_TO_STRING_PUBLIC,
|
||||
|
|
@ -168,6 +198,9 @@ typedef struct {
|
|||
/* Auxiliary data object for Wi-Fi and WPAN */
|
||||
GObject *ext_data;
|
||||
|
||||
/* FIXME: not every NMPObjectLink should pay the price for tracking
|
||||
* the wireguard family id. This should be tracked via ext_data, which
|
||||
* would be exactly the right place. */
|
||||
int wireguard_family_id;
|
||||
} NMPObjectLink;
|
||||
|
||||
|
|
@ -220,9 +253,10 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
NMPlatformLnkWireGuard _public;
|
||||
|
||||
gsize peers_len;
|
||||
NMWireGuardPeer *peers;
|
||||
const NMPWireGuardPeer *peers;
|
||||
const NMPWireGuardAllowedIP *_allowed_ips_buf;
|
||||
guint peers_len;
|
||||
guint _allowed_ips_buf_len;
|
||||
} NMPObjectLnkWireGuard;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -929,7 +929,7 @@ nm_wifi_utils_nl80211_class_init (NMWifiUtilsNl80211Class *klass)
|
|||
NMWifiUtils *
|
||||
nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl)
|
||||
{
|
||||
NMWifiUtilsNl80211 *nl80211;
|
||||
gs_unref_object NMWifiUtilsNl80211 *nl80211 = NULL;
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
struct nl80211_device_info device_info = {};
|
||||
char ifname[IFNAMSIZ];
|
||||
|
|
@ -951,7 +951,7 @@ nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl)
|
|||
nl80211->id = genl_ctrl_resolve (nl80211->nl_sock, "nl80211");
|
||||
if (nl80211->id < 0) {
|
||||
_LOGD (LOGD_WIFI, "genl_ctrl_resolve: failed to resolve \"nl80211\"");
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nl80211->phy = -1;
|
||||
|
|
@ -963,42 +963,42 @@ nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl)
|
|||
_LOGD (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): NL80211_CMD_GET_WIPHY request failed",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!device_info.success) {
|
||||
_LOGD (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): NL80211_CMD_GET_WIPHY request indicated failure",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!device_info.supported) {
|
||||
_LOGD (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): driver does not fully support nl80211, falling back to WEXT",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!device_info.can_scan_ssid) {
|
||||
_LOGE (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): driver does not support SSID scans",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (device_info.num_freqs == 0 || device_info.freqs == NULL) {
|
||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): driver reports no supported frequencies",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (device_info.caps == 0) {
|
||||
_LOGE (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): driver doesn't report support of any encryption",
|
||||
ifname);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nl80211->phy = device_info.phy;
|
||||
|
|
@ -1010,9 +1010,5 @@ nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl)
|
|||
_LOGI (LOGD_PLATFORM | LOGD_WIFI,
|
||||
"(%s): using nl80211 for WiFi device control",
|
||||
ifname);
|
||||
return (NMWifiUtils *) nl80211;
|
||||
|
||||
error:
|
||||
g_object_unref (nl80211);
|
||||
return NULL;
|
||||
return (NMWifiUtils *) g_steal_pointer (&nl80211);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1445,7 +1445,7 @@ test_nm_utils_strbuf_append (void)
|
|||
t_buf = buf;
|
||||
t_len = buf_len;
|
||||
|
||||
test_mode = nmtst_get_rand_int () % 4;
|
||||
test_mode = nmtst_get_rand_int () % 5;
|
||||
|
||||
switch (test_mode) {
|
||||
case 0:
|
||||
|
|
@ -1466,6 +1466,47 @@ test_nm_utils_strbuf_append (void)
|
|||
case 3:
|
||||
nm_utils_strbuf_append (&t_buf, &t_len, "%s", str);
|
||||
break;
|
||||
case 4:
|
||||
g_snprintf (t_buf, t_len, "%s", str);
|
||||
if ( t_len > 0
|
||||
&& strlen (str) >= buf_len
|
||||
&& (nmtst_get_rand_int () % 2)) {
|
||||
/* the string was truncated by g_snprintf(). That means, at the last position in the
|
||||
* buffer is now NUL.
|
||||
* Replace the NUL by the actual character, and check that nm_utils_strbuf_seek_end()
|
||||
* does the right thing: NUL terminate the buffer and seek past the end of the buffer. */
|
||||
g_assert_cmpmem (t_buf, t_len - 1, str, t_len - 1);
|
||||
g_assert (t_buf[t_len - 1] == '\0');
|
||||
g_assert (str[t_len - 1] != '\0');
|
||||
t_buf[t_len - 1] = str[t_len - 1];
|
||||
nm_utils_strbuf_seek_end (&t_buf, &t_len);
|
||||
g_assert (t_len == 0);
|
||||
g_assert (t_buf == &buf[buf_len]);
|
||||
g_assert (t_buf[-1] == '\0');
|
||||
} else {
|
||||
nm_utils_strbuf_seek_end (&t_buf, &t_len);
|
||||
if (strlen (str) + 1 == buf_len) {
|
||||
/* Special case: we appended a string that fit into the buffer
|
||||
* exactly, without truncation.
|
||||
* If we would append the string via nm_utils_strbuf_append(),
|
||||
* then it would have recognized that the string was not truncated
|
||||
* and leave len==1, and pointing the buffer to the terminating NUL
|
||||
* (at the very end, not past it).
|
||||
*
|
||||
* But nm_utils_strbuf_seek_end() cannot distinguish whether
|
||||
* truncation occured, and assumes the buffer was indeed truncated.
|
||||
*
|
||||
* Assert for that, but also adjust the numbers, so that the assertions
|
||||
* below pass (the assertions below theck for the nm_utils_strbuf_append()
|
||||
* case). */
|
||||
g_assert (t_len == 0);
|
||||
g_assert (t_buf == &buf[buf_len]);
|
||||
g_assert (t_buf[-1] == '\0');
|
||||
t_len = 1;
|
||||
t_buf--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assert that the source-buffer is unmodified. */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue