net: utils: Add userspace support to net_addr_ntop/pton()

Allow userspace application call net_addr_ntop() and
net_addr_pton() functions.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2019-06-12 14:06:52 +03:00 committed by Andrew Boie
parent eb018f8109
commit 5d13df9c3b
2 changed files with 88 additions and 7 deletions

View file

@ -1173,7 +1173,7 @@ struct sockaddr_can_ptr *net_can_ptr(const struct sockaddr_ptr *addr)
*
* @return 0 if ok, < 0 if error
*/
int net_addr_pton(sa_family_t family, const char *src, void *dst);
__syscall int net_addr_pton(sa_family_t family, const char *src, void *dst);
/**
* @brief Convert IP address to string form.
@ -1186,8 +1186,8 @@ int net_addr_pton(sa_family_t family, const char *src, void *dst);
*
* @return dst pointer if ok, NULL if error
*/
char *net_addr_ntop(sa_family_t family, const void *src,
char *dst, size_t size);
__syscall char *net_addr_ntop(sa_family_t family, const void *src,
char *dst, size_t size);
/**
* @brief Parse a string that contains either IPv4 or IPv6 address
@ -1324,6 +1324,8 @@ static inline u8_t net_priority2vlan(enum net_priority priority)
}
#endif
#include <syscalls/net_ip.h>
/**
* @}
*/

View file

@ -12,7 +12,9 @@
#include <logging/log.h>
LOG_MODULE_REGISTER(net_utils, CONFIG_NET_UTILS_LOG_LEVEL);
#include <kernel.h>
#include <stdlib.h>
#include <syscall_handler.h>
#include <zephyr/types.h>
#include <stdbool.h>
#include <string.h>
@ -137,8 +139,8 @@ static int net_value_to_udec(char *buf, u32_t value, int precision)
return buf - start;
}
char *net_addr_ntop(sa_family_t family, const void *src,
char *dst, size_t size)
char *z_impl_net_addr_ntop(sa_family_t family, const void *src,
char *dst, size_t size)
{
struct in_addr *addr;
struct in6_addr *addr6;
@ -270,8 +272,42 @@ char *net_addr_ntop(sa_family_t family, const void *src,
return dst;
}
int net_addr_pton(sa_family_t family, const char *src,
void *dst)
#if defined(CONFIG_USERSPACE)
Z_SYSCALL_HANDLER(net_addr_ntop, family, src, dst, size)
{
char str[INET6_ADDRSTRLEN];
struct in6_addr addr6;
struct in_addr addr4;
char *out;
const void *addr;
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
if (family == AF_INET) {
Z_OOPS(z_user_from_copy(&addr4, (const void *)src,
sizeof(addr4)));
addr = &addr4;
} else if (family == AF_INET6) {
Z_OOPS(z_user_from_copy(&addr6, (const void *)src,
sizeof(addr6)));
addr = &addr6;
} else {
return 0;
}
out = z_impl_net_addr_ntop(family, addr, str, sizeof(str));
if (!out) {
return 0;
}
Z_OOPS(z_user_to_copy((void *)dst, str, MIN(size, sizeof(str))));
return (int)dst;
}
#endif /* CONFIG_USERSPACE */
int z_impl_net_addr_pton(sa_family_t family, const char *src,
void *dst)
{
if (family == AF_INET) {
struct in_addr *addr = (struct in_addr *)dst;
@ -403,6 +439,49 @@ int net_addr_pton(sa_family_t family, const char *src,
return 0;
}
#if defined(CONFIG_USERSPACE)
Z_SYSCALL_HANDLER(net_addr_pton, family, src, dst)
{
char str[INET6_ADDRSTRLEN];
struct in6_addr addr6;
struct in_addr addr4;
void *addr;
size_t size;
size_t nlen;
int err;
if (family == AF_INET) {
size = sizeof(struct in_addr);
addr = &addr4;
} else if (family == AF_INET6) {
size = sizeof(struct in6_addr);
addr = &addr6;
} else {
return -EINVAL;
}
memset(str, 0, sizeof(str));
nlen = z_user_string_nlen((const char *)src, sizeof(str), &err);
if (err) {
return -EINVAL;
}
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
Z_OOPS(Z_SYSCALL_MEMORY_READ(src, nlen));
Z_OOPS(z_user_from_copy(str, (const void *)src, nlen));
err = z_impl_net_addr_pton(family, str, addr);
if (err) {
return err;
}
Z_OOPS(z_user_to_copy((void *)src, addr, size));
return 0;
}
#endif /* CONFIG_USERSPACE */
static u16_t calc_chksum(u16_t sum, const u8_t *data, size_t len)
{
const u8_t *end;