add osmo_sockaddr_from/to_octets()

Shorthand for the INET/INET6 switch() to get/put the addr part, useful
for encoding and decoding message buffers.

Related: OS#5599
Change-Id: Ie9e33bfac525c59c30714663d2bfcc62ec9eeb81
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index 6d11e6f..fffc25c 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -127,6 +127,9 @@
 int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
 		      const struct osmo_sockaddr *b);
 
+int osmo_sockaddr_to_octets(uint8_t *dst, size_t dst_maxlen, const struct osmo_sockaddr *os);
+int osmo_sockaddr_from_octets(struct osmo_sockaddr *os, const void *src, size_t src_len);
+
 const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr);
 char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
 			       const struct osmo_sockaddr *sockaddr);
diff --git a/src/socket.c b/src/socket.c
index 2d19fdf..6e5bb46 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1733,6 +1733,65 @@
 	return rc;
 }
 
+/*! Copy the addr part, the IP address octets in network byte order, to a buffer.
+ * Useful for encoding network protocols.
+ * \param[out] dst  Write octets to this buffer.
+ * \param[in] dst_maxlen  Space available in buffer.
+ * \param[in] os  Sockaddr to copy IP of.
+ * \return nr of octets written on success, negative on error.
+ */
+int osmo_sockaddr_to_octets(uint8_t *dst, size_t dst_maxlen, const struct osmo_sockaddr *os)
+{
+	const void *addr;
+	size_t len;
+	switch (os->u.sin.sin_family) {
+	case AF_INET:
+		addr = &os->u.sin.sin_addr;
+		len = sizeof(os->u.sin.sin_addr);
+		break;
+	case AF_INET6:
+		addr = &os->u.sin6.sin6_addr;
+		len = sizeof(os->u.sin6.sin6_addr);
+		break;
+	default:
+		return -ENOTSUP;
+	}
+	if (dst_maxlen < len)
+		return -ENOSPC;
+	memcpy(dst, addr, len);
+	return len;
+}
+
+/*! Copy the addr part, the IP address octets in network byte order, from a buffer.
+ * Useful for decoding network protocols.
+ * \param[out] os  Write IP address to this sockaddr.
+ * \param[in] src  Source buffer to read IP address octets from.
+ * \param[in] src_len  Number of octets to copy.
+ * \return number of octets read on success, negative on error.
+ */
+int osmo_sockaddr_from_octets(struct osmo_sockaddr *os, const void *src, size_t src_len)
+{
+	void *addr;
+	size_t len;
+	*os = (struct osmo_sockaddr){0};
+	switch (src_len) {
+	case sizeof(os->u.sin.sin_addr):
+		os->u.sin.sin_family = AF_INET;
+		addr = &os->u.sin.sin_addr;
+		len = sizeof(os->u.sin.sin_addr);
+		break;
+	case sizeof(os->u.sin6.sin6_addr):
+		os->u.sin6.sin6_family = AF_INET6;
+		addr = &os->u.sin6.sin6_addr;
+		len = sizeof(os->u.sin6.sin6_addr);
+		break;
+	default:
+		return -ENOTSUP;
+	}
+	memcpy(addr, src, len);
+	return len;
+}
+
 /*! Compare two osmo_sockaddr.
  * \param[in] a
  * \param[in] b