diff options
Diffstat (limited to 'drivers/interceptor/sshinetencode.c')
-rw-r--r-- | drivers/interceptor/sshinetencode.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/interceptor/sshinetencode.c b/drivers/interceptor/sshinetencode.c new file mode 100644 index 0000000..35b406f --- /dev/null +++ b/drivers/interceptor/sshinetencode.c @@ -0,0 +1,130 @@ +/* Netfilter Driver for IPSec VPN Client + * + * Copyright(c) 2012 Samsung Electronics + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * sshinetencode.c + * + * Implementation of inet API IP address encoding and decoding functions. + * + */ + +#include "sshincludes.h" +#include "sshencode.h" +#include "sshinetencode.h" + +size_t ssh_encode_ipaddr_array(unsigned char *buf, size_t bufsize, + const SshIpAddr ip) +{ + if (!ip || ip->type == SSH_IP_TYPE_NONE) + return ssh_encode_array(buf, bufsize, + SSH_ENCODE_CHAR(SSH_IP_TYPE_NONE), + SSH_FORMAT_END); + return ssh_encode_array(buf, bufsize, + SSH_ENCODE_CHAR(ip->type), + SSH_ENCODE_UINT32(ip->mask_len), + SSH_ENCODE_DATA(ip->addr_data, + SSH_IP_ADDR_LEN(ip)), +#ifdef WITH_IPV6 + SSH_ENCODE_UINT32(ip->scope_id.scope_id_union.ui32), +#endif /* WITH_IPV6 */ + SSH_FORMAT_END); +} + +size_t ssh_encode_ipaddr_array_alloc(unsigned char **buf_return, + const SshIpAddr ip) +{ + size_t req, got; + + if (ip->type == SSH_IP_TYPE_NONE) + req = 1; + else +#ifdef WITH_IPV6 + req = 1 + 8 + SSH_IP_ADDR_LEN(ip); +#else /* WITH_IPV6 */ + req = 1 + 4 + SSH_IP_ADDR_LEN(ip); +#endif /* WITH_IPV6 */ + + if (buf_return == NULL) + return req; + + if ((*buf_return = ssh_malloc(req)) == NULL) + return 0; + + got = ssh_encode_ipaddr_array(*buf_return, req, ip); + + if (got != req) + { + ssh_free(*buf_return); + *buf_return = NULL; + return 0; + } + + return got; +} + +int ssh_decode_ipaddr_array(const unsigned char *buf, size_t len, + void * ipaddr) +{ + size_t point, got; + SshUInt32 mask_len; +#ifdef WITH_IPV6 + SshUInt32 scope_id; +#endif /* WITH_IPV6 */ + unsigned int type; + SshIpAddr ip = (SshIpAddr)ipaddr; + point = 0; + + if ((got = ssh_decode_array(buf + point, len - point, + SSH_DECODE_CHAR(&type), + SSH_FORMAT_END)) != 1) + return 0; + + /* Make sure scope-id (that is not present at the kernel) is + zeroed */ + memset(ip, 0, sizeof(*ip)); + + ip->type = (SshUInt8) type; + + point += got; + + if (ip->type == SSH_IP_TYPE_NONE) + return point; + + if ((got = ssh_decode_array(buf + point, len - point, + SSH_DECODE_UINT32(&mask_len), + SSH_DECODE_DATA(ip->addr_data, + SSH_IP_ADDR_LEN(ip)), +#ifdef WITH_IPV6 + SSH_DECODE_UINT32(&scope_id), + SSH_FORMAT_END)) != ((2 * sizeof(SshUInt32)) + + SSH_IP_ADDR_LEN(ip))) +#else /* WITH_IPV6 */ + SSH_FORMAT_END)) != (4 + SSH_IP_ADDR_LEN(ip))) +#endif /* WITH_IPV6 */ + return 0; + + /* Sanity check */ + if (mask_len > 255) + return 0; + + ip->mask_len = (SshUInt8) mask_len; + + point += got; + +#ifdef WITH_IPV6 + ip->scope_id.scope_id_union.ui32 = scope_id; +#endif /* WITH_IPV6 */ + + /* Sanity check */ + if (!SSH_IP_IS4(ip) && !SSH_IP_IS6(ip)) + return 0; + + return point; +} |