16cd6a6acSopenharmony_ci#include <stdlib.h> 26cd6a6acSopenharmony_ci#include <stddef.h> 36cd6a6acSopenharmony_ci#include <string.h> 46cd6a6acSopenharmony_ci#include <netinet/in.h> 56cd6a6acSopenharmony_ci#include <arpa/inet.h> 66cd6a6acSopenharmony_ci#include <errno.h> 76cd6a6acSopenharmony_ci 86cd6a6acSopenharmony_ci#include "node_internal.h" 96cd6a6acSopenharmony_ci#include "context_internal.h" 106cd6a6acSopenharmony_ci#include "debug.h" 116cd6a6acSopenharmony_ci 126cd6a6acSopenharmony_cistruct sepol_node { 136cd6a6acSopenharmony_ci 146cd6a6acSopenharmony_ci /* Network address and mask */ 156cd6a6acSopenharmony_ci char *addr; 166cd6a6acSopenharmony_ci size_t addr_sz; 176cd6a6acSopenharmony_ci 186cd6a6acSopenharmony_ci char *mask; 196cd6a6acSopenharmony_ci size_t mask_sz; 206cd6a6acSopenharmony_ci 216cd6a6acSopenharmony_ci /* Protocol */ 226cd6a6acSopenharmony_ci int proto; 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci /* Context */ 256cd6a6acSopenharmony_ci sepol_context_t *con; 266cd6a6acSopenharmony_ci}; 276cd6a6acSopenharmony_ci 286cd6a6acSopenharmony_cistruct sepol_node_key { 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci /* Network address and mask */ 316cd6a6acSopenharmony_ci char *addr; 326cd6a6acSopenharmony_ci size_t addr_sz; 336cd6a6acSopenharmony_ci 346cd6a6acSopenharmony_ci char *mask; 356cd6a6acSopenharmony_ci size_t mask_sz; 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_ci /* Protocol */ 386cd6a6acSopenharmony_ci int proto; 396cd6a6acSopenharmony_ci}; 406cd6a6acSopenharmony_ci 416cd6a6acSopenharmony_ci/* Converts a string represtation (addr_str) 426cd6a6acSopenharmony_ci * to a numeric representation (addr_bytes) */ 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_cistatic int node_parse_addr(sepol_handle_t * handle, 456cd6a6acSopenharmony_ci const char *addr_str, int proto, char *addr_bytes) 466cd6a6acSopenharmony_ci{ 476cd6a6acSopenharmony_ci 486cd6a6acSopenharmony_ci switch (proto) { 496cd6a6acSopenharmony_ci 506cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 516cd6a6acSopenharmony_ci { 526cd6a6acSopenharmony_ci struct in_addr in_addr; 536cd6a6acSopenharmony_ci 546cd6a6acSopenharmony_ci if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) { 556cd6a6acSopenharmony_ci ERR(handle, "could not parse IPv4 address " 566cd6a6acSopenharmony_ci "%s: %m", addr_str); 576cd6a6acSopenharmony_ci return STATUS_ERR; 586cd6a6acSopenharmony_ci } 596cd6a6acSopenharmony_ci 606cd6a6acSopenharmony_ci memcpy(addr_bytes, &in_addr.s_addr, 4); 616cd6a6acSopenharmony_ci break; 626cd6a6acSopenharmony_ci } 636cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 646cd6a6acSopenharmony_ci { 656cd6a6acSopenharmony_ci struct in6_addr in_addr; 666cd6a6acSopenharmony_ci 676cd6a6acSopenharmony_ci if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) { 686cd6a6acSopenharmony_ci ERR(handle, "could not parse IPv6 address " 696cd6a6acSopenharmony_ci "%s: %m", addr_str); 706cd6a6acSopenharmony_ci return STATUS_ERR; 716cd6a6acSopenharmony_ci } 726cd6a6acSopenharmony_ci 736cd6a6acSopenharmony_ci memcpy(addr_bytes, in_addr.s6_addr, 16); 746cd6a6acSopenharmony_ci break; 756cd6a6acSopenharmony_ci } 766cd6a6acSopenharmony_ci default: 776cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u, could not " 786cd6a6acSopenharmony_ci "parse address", proto); 796cd6a6acSopenharmony_ci return STATUS_ERR; 806cd6a6acSopenharmony_ci } 816cd6a6acSopenharmony_ci 826cd6a6acSopenharmony_ci return STATUS_SUCCESS; 836cd6a6acSopenharmony_ci} 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_ci/* Allocates a sufficiently large buffer (addr, addr_sz) 866cd6a6acSopenharmony_ci * according to the protocol */ 876cd6a6acSopenharmony_ci 886cd6a6acSopenharmony_cistatic int node_alloc_addr(sepol_handle_t * handle, 896cd6a6acSopenharmony_ci int proto, char **addr, size_t * addr_sz) 906cd6a6acSopenharmony_ci{ 916cd6a6acSopenharmony_ci 926cd6a6acSopenharmony_ci char *tmp_addr = NULL; 936cd6a6acSopenharmony_ci size_t tmp_addr_sz; 946cd6a6acSopenharmony_ci 956cd6a6acSopenharmony_ci switch (proto) { 966cd6a6acSopenharmony_ci 976cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 986cd6a6acSopenharmony_ci tmp_addr_sz = 4; 996cd6a6acSopenharmony_ci tmp_addr = malloc(4); 1006cd6a6acSopenharmony_ci if (!tmp_addr) 1016cd6a6acSopenharmony_ci goto omem; 1026cd6a6acSopenharmony_ci break; 1036cd6a6acSopenharmony_ci 1046cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 1056cd6a6acSopenharmony_ci tmp_addr_sz = 16; 1066cd6a6acSopenharmony_ci tmp_addr = malloc(16); 1076cd6a6acSopenharmony_ci if (!tmp_addr) 1086cd6a6acSopenharmony_ci goto omem; 1096cd6a6acSopenharmony_ci break; 1106cd6a6acSopenharmony_ci 1116cd6a6acSopenharmony_ci default: 1126cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 1136cd6a6acSopenharmony_ci goto err; 1146cd6a6acSopenharmony_ci } 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ci *addr = tmp_addr; 1176cd6a6acSopenharmony_ci *addr_sz = tmp_addr_sz; 1186cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1196cd6a6acSopenharmony_ci 1206cd6a6acSopenharmony_ci omem: 1216cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 1226cd6a6acSopenharmony_ci 1236cd6a6acSopenharmony_ci err: 1246cd6a6acSopenharmony_ci free(tmp_addr); 1256cd6a6acSopenharmony_ci ERR(handle, "could not allocate address of protocol %s", 1266cd6a6acSopenharmony_ci sepol_node_get_proto_str(proto)); 1276cd6a6acSopenharmony_ci return STATUS_ERR; 1286cd6a6acSopenharmony_ci} 1296cd6a6acSopenharmony_ci 1306cd6a6acSopenharmony_ci/* Converts a numeric representation (addr_bytes) 1316cd6a6acSopenharmony_ci * to a string representation (addr_str), according to 1326cd6a6acSopenharmony_ci * the protocol */ 1336cd6a6acSopenharmony_ci 1346cd6a6acSopenharmony_cistatic int node_expand_addr(sepol_handle_t * handle, 1356cd6a6acSopenharmony_ci char *addr_bytes, int proto, char *addr_str) 1366cd6a6acSopenharmony_ci{ 1376cd6a6acSopenharmony_ci 1386cd6a6acSopenharmony_ci switch (proto) { 1396cd6a6acSopenharmony_ci 1406cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 1416cd6a6acSopenharmony_ci { 1426cd6a6acSopenharmony_ci struct in_addr addr; 1436cd6a6acSopenharmony_ci memset(&addr, 0, sizeof(struct in_addr)); 1446cd6a6acSopenharmony_ci memcpy(&addr.s_addr, addr_bytes, 4); 1456cd6a6acSopenharmony_ci 1466cd6a6acSopenharmony_ci if (inet_ntop(AF_INET, &addr, addr_str, 1476cd6a6acSopenharmony_ci INET_ADDRSTRLEN) == NULL) { 1486cd6a6acSopenharmony_ci 1496cd6a6acSopenharmony_ci ERR(handle, 1506cd6a6acSopenharmony_ci "could not expand IPv4 address to string: %m"); 1516cd6a6acSopenharmony_ci return STATUS_ERR; 1526cd6a6acSopenharmony_ci } 1536cd6a6acSopenharmony_ci break; 1546cd6a6acSopenharmony_ci } 1556cd6a6acSopenharmony_ci 1566cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 1576cd6a6acSopenharmony_ci { 1586cd6a6acSopenharmony_ci struct in6_addr addr; 1596cd6a6acSopenharmony_ci memset(&addr, 0, sizeof(struct in6_addr)); 1606cd6a6acSopenharmony_ci memcpy(&addr.s6_addr[0], addr_bytes, 16); 1616cd6a6acSopenharmony_ci if (inet_ntop(AF_INET6, &addr, addr_str, 1626cd6a6acSopenharmony_ci INET6_ADDRSTRLEN) == NULL) { 1636cd6a6acSopenharmony_ci 1646cd6a6acSopenharmony_ci ERR(handle, 1656cd6a6acSopenharmony_ci "could not expand IPv6 address to string: %m"); 1666cd6a6acSopenharmony_ci return STATUS_ERR; 1676cd6a6acSopenharmony_ci } 1686cd6a6acSopenharmony_ci break; 1696cd6a6acSopenharmony_ci } 1706cd6a6acSopenharmony_ci 1716cd6a6acSopenharmony_ci default: 1726cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u, could not" 1736cd6a6acSopenharmony_ci " expand address to string", proto); 1746cd6a6acSopenharmony_ci return STATUS_ERR; 1756cd6a6acSopenharmony_ci } 1766cd6a6acSopenharmony_ci 1776cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1786cd6a6acSopenharmony_ci} 1796cd6a6acSopenharmony_ci 1806cd6a6acSopenharmony_ci/* Allocates a sufficiently large address string (addr) 1816cd6a6acSopenharmony_ci * according to the protocol */ 1826cd6a6acSopenharmony_ci 1836cd6a6acSopenharmony_cistatic int node_alloc_addr_string(sepol_handle_t * handle, 1846cd6a6acSopenharmony_ci int proto, char **addr) 1856cd6a6acSopenharmony_ci{ 1866cd6a6acSopenharmony_ci 1876cd6a6acSopenharmony_ci char *tmp_addr = NULL; 1886cd6a6acSopenharmony_ci 1896cd6a6acSopenharmony_ci switch (proto) { 1906cd6a6acSopenharmony_ci 1916cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 1926cd6a6acSopenharmony_ci tmp_addr = malloc(INET_ADDRSTRLEN); 1936cd6a6acSopenharmony_ci if (!tmp_addr) 1946cd6a6acSopenharmony_ci goto omem; 1956cd6a6acSopenharmony_ci break; 1966cd6a6acSopenharmony_ci 1976cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 1986cd6a6acSopenharmony_ci tmp_addr = malloc(INET6_ADDRSTRLEN); 1996cd6a6acSopenharmony_ci if (!tmp_addr) 2006cd6a6acSopenharmony_ci goto omem; 2016cd6a6acSopenharmony_ci break; 2026cd6a6acSopenharmony_ci 2036cd6a6acSopenharmony_ci default: 2046cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 2056cd6a6acSopenharmony_ci goto err; 2066cd6a6acSopenharmony_ci } 2076cd6a6acSopenharmony_ci 2086cd6a6acSopenharmony_ci *addr = tmp_addr; 2096cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2106cd6a6acSopenharmony_ci 2116cd6a6acSopenharmony_ci omem: 2126cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 2136cd6a6acSopenharmony_ci 2146cd6a6acSopenharmony_ci err: 2156cd6a6acSopenharmony_ci free(tmp_addr); 2166cd6a6acSopenharmony_ci ERR(handle, "could not allocate string buffer for " 2176cd6a6acSopenharmony_ci "address of protocol %s", sepol_node_get_proto_str(proto)); 2186cd6a6acSopenharmony_ci return STATUS_ERR; 2196cd6a6acSopenharmony_ci} 2206cd6a6acSopenharmony_ci 2216cd6a6acSopenharmony_ci/* Key */ 2226cd6a6acSopenharmony_ciint sepol_node_key_create(sepol_handle_t * handle, 2236cd6a6acSopenharmony_ci const char *addr, 2246cd6a6acSopenharmony_ci const char *mask, 2256cd6a6acSopenharmony_ci int proto, sepol_node_key_t ** key_ptr) 2266cd6a6acSopenharmony_ci{ 2276cd6a6acSopenharmony_ci 2286cd6a6acSopenharmony_ci sepol_node_key_t *tmp_key = 2296cd6a6acSopenharmony_ci (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); 2306cd6a6acSopenharmony_ci if (!tmp_key) 2316cd6a6acSopenharmony_ci goto omem; 2326cd6a6acSopenharmony_ci 2336cd6a6acSopenharmony_ci if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) < 2346cd6a6acSopenharmony_ci 0) 2356cd6a6acSopenharmony_ci goto err; 2366cd6a6acSopenharmony_ci if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0) 2376cd6a6acSopenharmony_ci goto err; 2386cd6a6acSopenharmony_ci 2396cd6a6acSopenharmony_ci if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) < 2406cd6a6acSopenharmony_ci 0) 2416cd6a6acSopenharmony_ci goto err; 2426cd6a6acSopenharmony_ci if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0) 2436cd6a6acSopenharmony_ci goto err; 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci tmp_key->proto = proto; 2466cd6a6acSopenharmony_ci 2476cd6a6acSopenharmony_ci *key_ptr = tmp_key; 2486cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2496cd6a6acSopenharmony_ci 2506cd6a6acSopenharmony_ci omem: 2516cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 2526cd6a6acSopenharmony_ci 2536cd6a6acSopenharmony_ci err: 2546cd6a6acSopenharmony_ci sepol_node_key_free(tmp_key); 2556cd6a6acSopenharmony_ci ERR(handle, "could not create node key for (%s, %s, %s)", 2566cd6a6acSopenharmony_ci addr, mask, sepol_node_get_proto_str(proto)); 2576cd6a6acSopenharmony_ci return STATUS_ERR; 2586cd6a6acSopenharmony_ci} 2596cd6a6acSopenharmony_ci 2606cd6a6acSopenharmony_ci 2616cd6a6acSopenharmony_civoid sepol_node_key_unpack(const sepol_node_key_t * key, 2626cd6a6acSopenharmony_ci const char **addr, const char **mask, int *proto) 2636cd6a6acSopenharmony_ci{ 2646cd6a6acSopenharmony_ci 2656cd6a6acSopenharmony_ci *addr = key->addr; 2666cd6a6acSopenharmony_ci *mask = key->mask; 2676cd6a6acSopenharmony_ci *proto = key->proto; 2686cd6a6acSopenharmony_ci} 2696cd6a6acSopenharmony_ci 2706cd6a6acSopenharmony_ci 2716cd6a6acSopenharmony_ciint sepol_node_key_extract(sepol_handle_t * handle, 2726cd6a6acSopenharmony_ci const sepol_node_t * node, 2736cd6a6acSopenharmony_ci sepol_node_key_t ** key_ptr) 2746cd6a6acSopenharmony_ci{ 2756cd6a6acSopenharmony_ci 2766cd6a6acSopenharmony_ci sepol_node_key_t *tmp_key = 2776cd6a6acSopenharmony_ci (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); 2786cd6a6acSopenharmony_ci if (!tmp_key) 2796cd6a6acSopenharmony_ci goto omem; 2806cd6a6acSopenharmony_ci 2816cd6a6acSopenharmony_ci tmp_key->addr = malloc(node->addr_sz); 2826cd6a6acSopenharmony_ci tmp_key->mask = malloc(node->mask_sz); 2836cd6a6acSopenharmony_ci 2846cd6a6acSopenharmony_ci if (!tmp_key->addr || !tmp_key->mask) 2856cd6a6acSopenharmony_ci goto omem; 2866cd6a6acSopenharmony_ci 2876cd6a6acSopenharmony_ci memcpy(tmp_key->addr, node->addr, node->addr_sz); 2886cd6a6acSopenharmony_ci memcpy(tmp_key->mask, node->mask, node->mask_sz); 2896cd6a6acSopenharmony_ci tmp_key->addr_sz = node->addr_sz; 2906cd6a6acSopenharmony_ci tmp_key->mask_sz = node->mask_sz; 2916cd6a6acSopenharmony_ci tmp_key->proto = node->proto; 2926cd6a6acSopenharmony_ci 2936cd6a6acSopenharmony_ci *key_ptr = tmp_key; 2946cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2956cd6a6acSopenharmony_ci 2966cd6a6acSopenharmony_ci omem: 2976cd6a6acSopenharmony_ci sepol_node_key_free(tmp_key); 2986cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not extract node key"); 2996cd6a6acSopenharmony_ci return STATUS_ERR; 3006cd6a6acSopenharmony_ci} 3016cd6a6acSopenharmony_ci 3026cd6a6acSopenharmony_civoid sepol_node_key_free(sepol_node_key_t * key) 3036cd6a6acSopenharmony_ci{ 3046cd6a6acSopenharmony_ci 3056cd6a6acSopenharmony_ci if (!key) 3066cd6a6acSopenharmony_ci return; 3076cd6a6acSopenharmony_ci 3086cd6a6acSopenharmony_ci free(key->addr); 3096cd6a6acSopenharmony_ci free(key->mask); 3106cd6a6acSopenharmony_ci free(key); 3116cd6a6acSopenharmony_ci} 3126cd6a6acSopenharmony_ci 3136cd6a6acSopenharmony_ci 3146cd6a6acSopenharmony_ciint sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key) 3156cd6a6acSopenharmony_ci{ 3166cd6a6acSopenharmony_ci 3176cd6a6acSopenharmony_ci int rc1, rc2; 3186cd6a6acSopenharmony_ci 3196cd6a6acSopenharmony_ci if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz)) 3206cd6a6acSopenharmony_ci return -1; 3216cd6a6acSopenharmony_ci 3226cd6a6acSopenharmony_ci else if ((node->addr_sz > key->addr_sz) || 3236cd6a6acSopenharmony_ci (node->mask_sz > key->mask_sz)) 3246cd6a6acSopenharmony_ci return 1; 3256cd6a6acSopenharmony_ci 3266cd6a6acSopenharmony_ci rc1 = memcmp(node->addr, key->addr, node->addr_sz); 3276cd6a6acSopenharmony_ci rc2 = memcmp(node->mask, key->mask, node->mask_sz); 3286cd6a6acSopenharmony_ci 3296cd6a6acSopenharmony_ci return (rc2 != 0) ? rc2 : rc1; 3306cd6a6acSopenharmony_ci} 3316cd6a6acSopenharmony_ci 3326cd6a6acSopenharmony_ciint sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2) 3336cd6a6acSopenharmony_ci{ 3346cd6a6acSopenharmony_ci 3356cd6a6acSopenharmony_ci int rc1, rc2; 3366cd6a6acSopenharmony_ci 3376cd6a6acSopenharmony_ci if ((node->addr_sz < node2->addr_sz) || 3386cd6a6acSopenharmony_ci (node->mask_sz < node2->mask_sz)) 3396cd6a6acSopenharmony_ci return -1; 3406cd6a6acSopenharmony_ci 3416cd6a6acSopenharmony_ci else if ((node->addr_sz > node2->addr_sz) || 3426cd6a6acSopenharmony_ci (node->mask_sz > node2->mask_sz)) 3436cd6a6acSopenharmony_ci return 1; 3446cd6a6acSopenharmony_ci 3456cd6a6acSopenharmony_ci rc1 = memcmp(node->addr, node2->addr, node->addr_sz); 3466cd6a6acSopenharmony_ci rc2 = memcmp(node->mask, node2->mask, node->mask_sz); 3476cd6a6acSopenharmony_ci 3486cd6a6acSopenharmony_ci return (rc2 != 0) ? rc2 : rc1; 3496cd6a6acSopenharmony_ci} 3506cd6a6acSopenharmony_ci 3516cd6a6acSopenharmony_ci/* Addr */ 3526cd6a6acSopenharmony_ciint sepol_node_get_addr(sepol_handle_t * handle, 3536cd6a6acSopenharmony_ci const sepol_node_t * node, char **addr) 3546cd6a6acSopenharmony_ci{ 3556cd6a6acSopenharmony_ci 3566cd6a6acSopenharmony_ci char *tmp_addr = NULL; 3576cd6a6acSopenharmony_ci 3586cd6a6acSopenharmony_ci if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0) 3596cd6a6acSopenharmony_ci goto err; 3606cd6a6acSopenharmony_ci 3616cd6a6acSopenharmony_ci if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0) 3626cd6a6acSopenharmony_ci goto err; 3636cd6a6acSopenharmony_ci 3646cd6a6acSopenharmony_ci *addr = tmp_addr; 3656cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3666cd6a6acSopenharmony_ci 3676cd6a6acSopenharmony_ci err: 3686cd6a6acSopenharmony_ci free(tmp_addr); 3696cd6a6acSopenharmony_ci ERR(handle, "could not get node address"); 3706cd6a6acSopenharmony_ci return STATUS_ERR; 3716cd6a6acSopenharmony_ci} 3726cd6a6acSopenharmony_ci 3736cd6a6acSopenharmony_ci 3746cd6a6acSopenharmony_ciint sepol_node_get_addr_bytes(sepol_handle_t * handle, 3756cd6a6acSopenharmony_ci const sepol_node_t * node, 3766cd6a6acSopenharmony_ci char **buffer, size_t * bsize) 3776cd6a6acSopenharmony_ci{ 3786cd6a6acSopenharmony_ci 3796cd6a6acSopenharmony_ci char *tmp_buf = malloc(node->addr_sz); 3806cd6a6acSopenharmony_ci if (!tmp_buf) { 3816cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not get address bytes"); 3826cd6a6acSopenharmony_ci return STATUS_ERR; 3836cd6a6acSopenharmony_ci } 3846cd6a6acSopenharmony_ci 3856cd6a6acSopenharmony_ci memcpy(tmp_buf, node->addr, node->addr_sz); 3866cd6a6acSopenharmony_ci *buffer = tmp_buf; 3876cd6a6acSopenharmony_ci *bsize = node->addr_sz; 3886cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3896cd6a6acSopenharmony_ci} 3906cd6a6acSopenharmony_ci 3916cd6a6acSopenharmony_ci 3926cd6a6acSopenharmony_ciint sepol_node_set_addr(sepol_handle_t * handle, 3936cd6a6acSopenharmony_ci sepol_node_t * node, int proto, const char *addr) 3946cd6a6acSopenharmony_ci{ 3956cd6a6acSopenharmony_ci 3966cd6a6acSopenharmony_ci char *tmp_addr = NULL; 3976cd6a6acSopenharmony_ci size_t tmp_addr_sz; 3986cd6a6acSopenharmony_ci 3996cd6a6acSopenharmony_ci if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0) 4006cd6a6acSopenharmony_ci goto err; 4016cd6a6acSopenharmony_ci 4026cd6a6acSopenharmony_ci if (node_parse_addr(handle, addr, proto, tmp_addr) < 0) 4036cd6a6acSopenharmony_ci goto err; 4046cd6a6acSopenharmony_ci 4056cd6a6acSopenharmony_ci free(node->addr); 4066cd6a6acSopenharmony_ci node->addr = tmp_addr; 4076cd6a6acSopenharmony_ci node->addr_sz = tmp_addr_sz; 4086cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4096cd6a6acSopenharmony_ci 4106cd6a6acSopenharmony_ci err: 4116cd6a6acSopenharmony_ci free(tmp_addr); 4126cd6a6acSopenharmony_ci ERR(handle, "could not set node address to %s", addr); 4136cd6a6acSopenharmony_ci return STATUS_ERR; 4146cd6a6acSopenharmony_ci} 4156cd6a6acSopenharmony_ci 4166cd6a6acSopenharmony_ci 4176cd6a6acSopenharmony_ciint sepol_node_set_addr_bytes(sepol_handle_t * handle, 4186cd6a6acSopenharmony_ci sepol_node_t * node, 4196cd6a6acSopenharmony_ci const char *addr, size_t addr_sz) 4206cd6a6acSopenharmony_ci{ 4216cd6a6acSopenharmony_ci 4226cd6a6acSopenharmony_ci char *tmp_addr = malloc(addr_sz); 4236cd6a6acSopenharmony_ci if (!tmp_addr) { 4246cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not " "set node address"); 4256cd6a6acSopenharmony_ci return STATUS_ERR; 4266cd6a6acSopenharmony_ci } 4276cd6a6acSopenharmony_ci 4286cd6a6acSopenharmony_ci memcpy(tmp_addr, addr, addr_sz); 4296cd6a6acSopenharmony_ci free(node->addr); 4306cd6a6acSopenharmony_ci node->addr = tmp_addr; 4316cd6a6acSopenharmony_ci node->addr_sz = addr_sz; 4326cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4336cd6a6acSopenharmony_ci} 4346cd6a6acSopenharmony_ci 4356cd6a6acSopenharmony_ci 4366cd6a6acSopenharmony_ci/* Mask */ 4376cd6a6acSopenharmony_ciint sepol_node_get_mask(sepol_handle_t * handle, 4386cd6a6acSopenharmony_ci const sepol_node_t * node, char **mask) 4396cd6a6acSopenharmony_ci{ 4406cd6a6acSopenharmony_ci 4416cd6a6acSopenharmony_ci char *tmp_mask = NULL; 4426cd6a6acSopenharmony_ci 4436cd6a6acSopenharmony_ci if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0) 4446cd6a6acSopenharmony_ci goto err; 4456cd6a6acSopenharmony_ci 4466cd6a6acSopenharmony_ci if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0) 4476cd6a6acSopenharmony_ci goto err; 4486cd6a6acSopenharmony_ci 4496cd6a6acSopenharmony_ci *mask = tmp_mask; 4506cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4516cd6a6acSopenharmony_ci 4526cd6a6acSopenharmony_ci err: 4536cd6a6acSopenharmony_ci free(tmp_mask); 4546cd6a6acSopenharmony_ci ERR(handle, "could not get node netmask"); 4556cd6a6acSopenharmony_ci return STATUS_ERR; 4566cd6a6acSopenharmony_ci} 4576cd6a6acSopenharmony_ci 4586cd6a6acSopenharmony_ci 4596cd6a6acSopenharmony_ciint sepol_node_get_mask_bytes(sepol_handle_t * handle, 4606cd6a6acSopenharmony_ci const sepol_node_t * node, 4616cd6a6acSopenharmony_ci char **buffer, size_t * bsize) 4626cd6a6acSopenharmony_ci{ 4636cd6a6acSopenharmony_ci 4646cd6a6acSopenharmony_ci char *tmp_buf = malloc(node->mask_sz); 4656cd6a6acSopenharmony_ci if (!tmp_buf) { 4666cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not get netmask bytes"); 4676cd6a6acSopenharmony_ci return STATUS_ERR; 4686cd6a6acSopenharmony_ci } 4696cd6a6acSopenharmony_ci 4706cd6a6acSopenharmony_ci memcpy(tmp_buf, node->mask, node->mask_sz); 4716cd6a6acSopenharmony_ci *buffer = tmp_buf; 4726cd6a6acSopenharmony_ci *bsize = node->mask_sz; 4736cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4746cd6a6acSopenharmony_ci} 4756cd6a6acSopenharmony_ci 4766cd6a6acSopenharmony_ci 4776cd6a6acSopenharmony_ciint sepol_node_set_mask(sepol_handle_t * handle, 4786cd6a6acSopenharmony_ci sepol_node_t * node, int proto, const char *mask) 4796cd6a6acSopenharmony_ci{ 4806cd6a6acSopenharmony_ci 4816cd6a6acSopenharmony_ci char *tmp_mask = NULL; 4826cd6a6acSopenharmony_ci size_t tmp_mask_sz; 4836cd6a6acSopenharmony_ci 4846cd6a6acSopenharmony_ci if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0) 4856cd6a6acSopenharmony_ci goto err; 4866cd6a6acSopenharmony_ci 4876cd6a6acSopenharmony_ci if (node_parse_addr(handle, mask, proto, tmp_mask) < 0) 4886cd6a6acSopenharmony_ci goto err; 4896cd6a6acSopenharmony_ci 4906cd6a6acSopenharmony_ci free(node->mask); 4916cd6a6acSopenharmony_ci node->mask = tmp_mask; 4926cd6a6acSopenharmony_ci node->mask_sz = tmp_mask_sz; 4936cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4946cd6a6acSopenharmony_ci 4956cd6a6acSopenharmony_ci err: 4966cd6a6acSopenharmony_ci free(tmp_mask); 4976cd6a6acSopenharmony_ci ERR(handle, "could not set node netmask to %s", mask); 4986cd6a6acSopenharmony_ci return STATUS_ERR; 4996cd6a6acSopenharmony_ci} 5006cd6a6acSopenharmony_ci 5016cd6a6acSopenharmony_ci 5026cd6a6acSopenharmony_ciint sepol_node_set_mask_bytes(sepol_handle_t * handle, 5036cd6a6acSopenharmony_ci sepol_node_t * node, 5046cd6a6acSopenharmony_ci const char *mask, size_t mask_sz) 5056cd6a6acSopenharmony_ci{ 5066cd6a6acSopenharmony_ci 5076cd6a6acSopenharmony_ci char *tmp_mask = malloc(mask_sz); 5086cd6a6acSopenharmony_ci if (!tmp_mask) { 5096cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not " "set node netmask"); 5106cd6a6acSopenharmony_ci return STATUS_ERR; 5116cd6a6acSopenharmony_ci } 5126cd6a6acSopenharmony_ci memcpy(tmp_mask, mask, mask_sz); 5136cd6a6acSopenharmony_ci free(node->mask); 5146cd6a6acSopenharmony_ci node->mask = tmp_mask; 5156cd6a6acSopenharmony_ci node->mask_sz = mask_sz; 5166cd6a6acSopenharmony_ci return STATUS_SUCCESS; 5176cd6a6acSopenharmony_ci} 5186cd6a6acSopenharmony_ci 5196cd6a6acSopenharmony_ci 5206cd6a6acSopenharmony_ci/* Protocol */ 5216cd6a6acSopenharmony_ciint sepol_node_get_proto(const sepol_node_t * node) 5226cd6a6acSopenharmony_ci{ 5236cd6a6acSopenharmony_ci 5246cd6a6acSopenharmony_ci return node->proto; 5256cd6a6acSopenharmony_ci} 5266cd6a6acSopenharmony_ci 5276cd6a6acSopenharmony_ci 5286cd6a6acSopenharmony_civoid sepol_node_set_proto(sepol_node_t * node, int proto) 5296cd6a6acSopenharmony_ci{ 5306cd6a6acSopenharmony_ci 5316cd6a6acSopenharmony_ci node->proto = proto; 5326cd6a6acSopenharmony_ci} 5336cd6a6acSopenharmony_ci 5346cd6a6acSopenharmony_ci 5356cd6a6acSopenharmony_ciconst char *sepol_node_get_proto_str(int proto) 5366cd6a6acSopenharmony_ci{ 5376cd6a6acSopenharmony_ci 5386cd6a6acSopenharmony_ci switch (proto) { 5396cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 5406cd6a6acSopenharmony_ci return "ipv4"; 5416cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 5426cd6a6acSopenharmony_ci return "ipv6"; 5436cd6a6acSopenharmony_ci default: 5446cd6a6acSopenharmony_ci return "???"; 5456cd6a6acSopenharmony_ci } 5466cd6a6acSopenharmony_ci} 5476cd6a6acSopenharmony_ci 5486cd6a6acSopenharmony_ci 5496cd6a6acSopenharmony_ci/* Create */ 5506cd6a6acSopenharmony_ciint sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node) 5516cd6a6acSopenharmony_ci{ 5526cd6a6acSopenharmony_ci 5536cd6a6acSopenharmony_ci sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t)); 5546cd6a6acSopenharmony_ci 5556cd6a6acSopenharmony_ci if (!tmp_node) { 5566cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not create " "node record"); 5576cd6a6acSopenharmony_ci return STATUS_ERR; 5586cd6a6acSopenharmony_ci } 5596cd6a6acSopenharmony_ci 5606cd6a6acSopenharmony_ci tmp_node->addr = NULL; 5616cd6a6acSopenharmony_ci tmp_node->addr_sz = 0; 5626cd6a6acSopenharmony_ci tmp_node->mask = NULL; 5636cd6a6acSopenharmony_ci tmp_node->mask_sz = 0; 5646cd6a6acSopenharmony_ci tmp_node->proto = SEPOL_PROTO_IP4; 5656cd6a6acSopenharmony_ci tmp_node->con = NULL; 5666cd6a6acSopenharmony_ci *node = tmp_node; 5676cd6a6acSopenharmony_ci 5686cd6a6acSopenharmony_ci return STATUS_SUCCESS; 5696cd6a6acSopenharmony_ci} 5706cd6a6acSopenharmony_ci 5716cd6a6acSopenharmony_ci 5726cd6a6acSopenharmony_ci/* Deep copy clone */ 5736cd6a6acSopenharmony_ciint sepol_node_clone(sepol_handle_t * handle, 5746cd6a6acSopenharmony_ci const sepol_node_t * node, sepol_node_t ** node_ptr) 5756cd6a6acSopenharmony_ci{ 5766cd6a6acSopenharmony_ci 5776cd6a6acSopenharmony_ci sepol_node_t *new_node = NULL; 5786cd6a6acSopenharmony_ci if (sepol_node_create(handle, &new_node) < 0) 5796cd6a6acSopenharmony_ci goto err; 5806cd6a6acSopenharmony_ci 5816cd6a6acSopenharmony_ci /* Copy address, mask, protocol */ 5826cd6a6acSopenharmony_ci new_node->addr = malloc(node->addr_sz); 5836cd6a6acSopenharmony_ci new_node->mask = malloc(node->mask_sz); 5846cd6a6acSopenharmony_ci if (!new_node->addr || !new_node->mask) 5856cd6a6acSopenharmony_ci goto omem; 5866cd6a6acSopenharmony_ci 5876cd6a6acSopenharmony_ci memcpy(new_node->addr, node->addr, node->addr_sz); 5886cd6a6acSopenharmony_ci memcpy(new_node->mask, node->mask, node->mask_sz); 5896cd6a6acSopenharmony_ci new_node->addr_sz = node->addr_sz; 5906cd6a6acSopenharmony_ci new_node->mask_sz = node->mask_sz; 5916cd6a6acSopenharmony_ci new_node->proto = node->proto; 5926cd6a6acSopenharmony_ci 5936cd6a6acSopenharmony_ci /* Copy context */ 5946cd6a6acSopenharmony_ci if (node->con && 5956cd6a6acSopenharmony_ci (sepol_context_clone(handle, node->con, &new_node->con) < 0)) 5966cd6a6acSopenharmony_ci goto err; 5976cd6a6acSopenharmony_ci 5986cd6a6acSopenharmony_ci *node_ptr = new_node; 5996cd6a6acSopenharmony_ci return STATUS_SUCCESS; 6006cd6a6acSopenharmony_ci 6016cd6a6acSopenharmony_ci omem: 6026cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 6036cd6a6acSopenharmony_ci 6046cd6a6acSopenharmony_ci err: 6056cd6a6acSopenharmony_ci ERR(handle, "could not clone node record"); 6066cd6a6acSopenharmony_ci sepol_node_free(new_node); 6076cd6a6acSopenharmony_ci return STATUS_ERR; 6086cd6a6acSopenharmony_ci} 6096cd6a6acSopenharmony_ci 6106cd6a6acSopenharmony_ci/* Destroy */ 6116cd6a6acSopenharmony_civoid sepol_node_free(sepol_node_t * node) 6126cd6a6acSopenharmony_ci{ 6136cd6a6acSopenharmony_ci 6146cd6a6acSopenharmony_ci if (!node) 6156cd6a6acSopenharmony_ci return; 6166cd6a6acSopenharmony_ci 6176cd6a6acSopenharmony_ci sepol_context_free(node->con); 6186cd6a6acSopenharmony_ci free(node->addr); 6196cd6a6acSopenharmony_ci free(node->mask); 6206cd6a6acSopenharmony_ci free(node); 6216cd6a6acSopenharmony_ci} 6226cd6a6acSopenharmony_ci 6236cd6a6acSopenharmony_ci 6246cd6a6acSopenharmony_ci/* Context */ 6256cd6a6acSopenharmony_cisepol_context_t *sepol_node_get_con(const sepol_node_t * node) 6266cd6a6acSopenharmony_ci{ 6276cd6a6acSopenharmony_ci 6286cd6a6acSopenharmony_ci return node->con; 6296cd6a6acSopenharmony_ci} 6306cd6a6acSopenharmony_ci 6316cd6a6acSopenharmony_ci 6326cd6a6acSopenharmony_ciint sepol_node_set_con(sepol_handle_t * handle, 6336cd6a6acSopenharmony_ci sepol_node_t * node, sepol_context_t * con) 6346cd6a6acSopenharmony_ci{ 6356cd6a6acSopenharmony_ci 6366cd6a6acSopenharmony_ci sepol_context_t *newcon; 6376cd6a6acSopenharmony_ci 6386cd6a6acSopenharmony_ci if (sepol_context_clone(handle, con, &newcon) < 0) { 6396cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not set node context"); 6406cd6a6acSopenharmony_ci return STATUS_ERR; 6416cd6a6acSopenharmony_ci } 6426cd6a6acSopenharmony_ci 6436cd6a6acSopenharmony_ci sepol_context_free(node->con); 6446cd6a6acSopenharmony_ci node->con = newcon; 6456cd6a6acSopenharmony_ci return STATUS_SUCCESS; 6466cd6a6acSopenharmony_ci} 6476cd6a6acSopenharmony_ci 648