16cd6a6acSopenharmony_ci#include <netinet/in.h> 26cd6a6acSopenharmony_ci#include <arpa/inet.h> 36cd6a6acSopenharmony_ci#include <stdlib.h> 46cd6a6acSopenharmony_ci 56cd6a6acSopenharmony_ci#include "debug.h" 66cd6a6acSopenharmony_ci#include "context.h" 76cd6a6acSopenharmony_ci#include "handle.h" 86cd6a6acSopenharmony_ci 96cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 106cd6a6acSopenharmony_ci#include "node_internal.h" 116cd6a6acSopenharmony_ci 126cd6a6acSopenharmony_ci/* Create a low level node structure from 136cd6a6acSopenharmony_ci * a high level representation */ 146cd6a6acSopenharmony_cistatic int node_from_record(sepol_handle_t * handle, 156cd6a6acSopenharmony_ci const policydb_t * policydb, 166cd6a6acSopenharmony_ci ocontext_t ** node, const sepol_node_t * data) 176cd6a6acSopenharmony_ci{ 186cd6a6acSopenharmony_ci 196cd6a6acSopenharmony_ci ocontext_t *tmp_node = NULL; 206cd6a6acSopenharmony_ci context_struct_t *tmp_con = NULL; 216cd6a6acSopenharmony_ci char *addr_buf = NULL, *mask_buf = NULL; 226cd6a6acSopenharmony_ci size_t addr_bsize, mask_bsize; 236cd6a6acSopenharmony_ci int proto; 246cd6a6acSopenharmony_ci 256cd6a6acSopenharmony_ci tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t)); 266cd6a6acSopenharmony_ci if (!tmp_node) 276cd6a6acSopenharmony_ci goto omem; 286cd6a6acSopenharmony_ci 296cd6a6acSopenharmony_ci /* Address and netmask */ 306cd6a6acSopenharmony_ci if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0) 316cd6a6acSopenharmony_ci goto err; 326cd6a6acSopenharmony_ci if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0) 336cd6a6acSopenharmony_ci goto err; 346cd6a6acSopenharmony_ci 356cd6a6acSopenharmony_ci proto = sepol_node_get_proto(data); 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_ci switch (proto) { 386cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 396cd6a6acSopenharmony_ci memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize); 406cd6a6acSopenharmony_ci memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize); 416cd6a6acSopenharmony_ci break; 426cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 436cd6a6acSopenharmony_ci memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize); 446cd6a6acSopenharmony_ci memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize); 456cd6a6acSopenharmony_ci break; 466cd6a6acSopenharmony_ci default: 476cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 486cd6a6acSopenharmony_ci goto err; 496cd6a6acSopenharmony_ci } 506cd6a6acSopenharmony_ci free(addr_buf); 516cd6a6acSopenharmony_ci free(mask_buf); 526cd6a6acSopenharmony_ci addr_buf = NULL; 536cd6a6acSopenharmony_ci mask_buf = NULL; 546cd6a6acSopenharmony_ci 556cd6a6acSopenharmony_ci /* Context */ 566cd6a6acSopenharmony_ci if (context_from_record(handle, policydb, &tmp_con, 576cd6a6acSopenharmony_ci sepol_node_get_con(data)) < 0) 586cd6a6acSopenharmony_ci goto err; 596cd6a6acSopenharmony_ci context_cpy(&tmp_node->context[0], tmp_con); 606cd6a6acSopenharmony_ci context_destroy(tmp_con); 616cd6a6acSopenharmony_ci free(tmp_con); 626cd6a6acSopenharmony_ci tmp_con = NULL; 636cd6a6acSopenharmony_ci 646cd6a6acSopenharmony_ci *node = tmp_node; 656cd6a6acSopenharmony_ci return STATUS_SUCCESS; 666cd6a6acSopenharmony_ci 676cd6a6acSopenharmony_ci omem: 686cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 696cd6a6acSopenharmony_ci 706cd6a6acSopenharmony_ci err: 716cd6a6acSopenharmony_ci if (tmp_node != NULL) { 726cd6a6acSopenharmony_ci context_destroy(&tmp_node->context[0]); 736cd6a6acSopenharmony_ci free(tmp_node); 746cd6a6acSopenharmony_ci } 756cd6a6acSopenharmony_ci context_destroy(tmp_con); 766cd6a6acSopenharmony_ci free(tmp_con); 776cd6a6acSopenharmony_ci free(addr_buf); 786cd6a6acSopenharmony_ci free(mask_buf); 796cd6a6acSopenharmony_ci ERR(handle, "could not create node structure"); 806cd6a6acSopenharmony_ci return STATUS_ERR; 816cd6a6acSopenharmony_ci} 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_cistatic int node_to_record(sepol_handle_t * handle, 846cd6a6acSopenharmony_ci const policydb_t * policydb, 856cd6a6acSopenharmony_ci ocontext_t * node, int proto, sepol_node_t ** record) 866cd6a6acSopenharmony_ci{ 876cd6a6acSopenharmony_ci 886cd6a6acSopenharmony_ci context_struct_t *con = &node->context[0]; 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ci sepol_context_t *tmp_con = NULL; 916cd6a6acSopenharmony_ci sepol_node_t *tmp_record = NULL; 926cd6a6acSopenharmony_ci 936cd6a6acSopenharmony_ci if (sepol_node_create(handle, &tmp_record) < 0) 946cd6a6acSopenharmony_ci goto err; 956cd6a6acSopenharmony_ci 966cd6a6acSopenharmony_ci sepol_node_set_proto(tmp_record, proto); 976cd6a6acSopenharmony_ci 986cd6a6acSopenharmony_ci switch (proto) { 996cd6a6acSopenharmony_ci 1006cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 1016cd6a6acSopenharmony_ci if (sepol_node_set_addr_bytes(handle, tmp_record, 1026cd6a6acSopenharmony_ci (const char *)&node->u.node.addr, 1036cd6a6acSopenharmony_ci 4) < 0) 1046cd6a6acSopenharmony_ci goto err; 1056cd6a6acSopenharmony_ci 1066cd6a6acSopenharmony_ci if (sepol_node_set_mask_bytes(handle, tmp_record, 1076cd6a6acSopenharmony_ci (const char *)&node->u.node.mask, 1086cd6a6acSopenharmony_ci 4) < 0) 1096cd6a6acSopenharmony_ci goto err; 1106cd6a6acSopenharmony_ci break; 1116cd6a6acSopenharmony_ci 1126cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 1136cd6a6acSopenharmony_ci if (sepol_node_set_addr_bytes(handle, tmp_record, 1146cd6a6acSopenharmony_ci (const char *)&node->u.node6.addr, 1156cd6a6acSopenharmony_ci 16) < 0) 1166cd6a6acSopenharmony_ci goto err; 1176cd6a6acSopenharmony_ci 1186cd6a6acSopenharmony_ci if (sepol_node_set_mask_bytes(handle, tmp_record, 1196cd6a6acSopenharmony_ci (const char *)&node->u.node6.mask, 1206cd6a6acSopenharmony_ci 16) < 0) 1216cd6a6acSopenharmony_ci goto err; 1226cd6a6acSopenharmony_ci break; 1236cd6a6acSopenharmony_ci 1246cd6a6acSopenharmony_ci default: 1256cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 1266cd6a6acSopenharmony_ci goto err; 1276cd6a6acSopenharmony_ci } 1286cd6a6acSopenharmony_ci 1296cd6a6acSopenharmony_ci if (context_to_record(handle, policydb, con, &tmp_con) < 0) 1306cd6a6acSopenharmony_ci goto err; 1316cd6a6acSopenharmony_ci 1326cd6a6acSopenharmony_ci if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0) 1336cd6a6acSopenharmony_ci goto err; 1346cd6a6acSopenharmony_ci 1356cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 1366cd6a6acSopenharmony_ci *record = tmp_record; 1376cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1386cd6a6acSopenharmony_ci 1396cd6a6acSopenharmony_ci err: 1406cd6a6acSopenharmony_ci ERR(handle, "could not convert node to record"); 1416cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 1426cd6a6acSopenharmony_ci sepol_node_free(tmp_record); 1436cd6a6acSopenharmony_ci return STATUS_ERR; 1446cd6a6acSopenharmony_ci} 1456cd6a6acSopenharmony_ci 1466cd6a6acSopenharmony_ci/* Return the number of nodes */ 1476cd6a6acSopenharmony_ciextern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)), 1486cd6a6acSopenharmony_ci const sepol_policydb_t * p, unsigned int *response) 1496cd6a6acSopenharmony_ci{ 1506cd6a6acSopenharmony_ci 1516cd6a6acSopenharmony_ci unsigned int count = 0; 1526cd6a6acSopenharmony_ci ocontext_t *c, *head; 1536cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1546cd6a6acSopenharmony_ci 1556cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE]; 1566cd6a6acSopenharmony_ci for (c = head; c != NULL; c = c->next) 1576cd6a6acSopenharmony_ci count++; 1586cd6a6acSopenharmony_ci 1596cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE6]; 1606cd6a6acSopenharmony_ci for (c = head; c != NULL; c = c->next) 1616cd6a6acSopenharmony_ci count++; 1626cd6a6acSopenharmony_ci 1636cd6a6acSopenharmony_ci *response = count; 1646cd6a6acSopenharmony_ci 1656cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1666cd6a6acSopenharmony_ci} 1676cd6a6acSopenharmony_ci 1686cd6a6acSopenharmony_ci/* Check if a node exists */ 1696cd6a6acSopenharmony_ciint sepol_node_exists(sepol_handle_t * handle, 1706cd6a6acSopenharmony_ci const sepol_policydb_t * p, 1716cd6a6acSopenharmony_ci const sepol_node_key_t * key, int *response) 1726cd6a6acSopenharmony_ci{ 1736cd6a6acSopenharmony_ci 1746cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1756cd6a6acSopenharmony_ci ocontext_t *c, *head; 1766cd6a6acSopenharmony_ci 1776cd6a6acSopenharmony_ci int proto; 1786cd6a6acSopenharmony_ci const char *addr, *mask; 1796cd6a6acSopenharmony_ci sepol_node_key_unpack(key, &addr, &mask, &proto); 1806cd6a6acSopenharmony_ci 1816cd6a6acSopenharmony_ci switch (proto) { 1826cd6a6acSopenharmony_ci 1836cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 1846cd6a6acSopenharmony_ci { 1856cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE]; 1866cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1876cd6a6acSopenharmony_ci unsigned int *addr2 = &c->u.node.addr; 1886cd6a6acSopenharmony_ci unsigned int *mask2 = &c->u.node.mask; 1896cd6a6acSopenharmony_ci 1906cd6a6acSopenharmony_ci if (!memcmp(addr, addr2, 4) && 1916cd6a6acSopenharmony_ci !memcmp(mask, mask2, 4)) { 1926cd6a6acSopenharmony_ci 1936cd6a6acSopenharmony_ci *response = 1; 1946cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1956cd6a6acSopenharmony_ci } 1966cd6a6acSopenharmony_ci } 1976cd6a6acSopenharmony_ci break; 1986cd6a6acSopenharmony_ci } 1996cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 2006cd6a6acSopenharmony_ci { 2016cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE6]; 2026cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2036cd6a6acSopenharmony_ci unsigned int *addr2 = c->u.node6.addr; 2046cd6a6acSopenharmony_ci unsigned int *mask2 = c->u.node6.mask; 2056cd6a6acSopenharmony_ci 2066cd6a6acSopenharmony_ci if (!memcmp(addr, addr2, 16) && 2076cd6a6acSopenharmony_ci !memcmp(mask, mask2, 16)) { 2086cd6a6acSopenharmony_ci *response = 1; 2096cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2106cd6a6acSopenharmony_ci } 2116cd6a6acSopenharmony_ci } 2126cd6a6acSopenharmony_ci break; 2136cd6a6acSopenharmony_ci } 2146cd6a6acSopenharmony_ci default: 2156cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 2166cd6a6acSopenharmony_ci goto err; 2176cd6a6acSopenharmony_ci } 2186cd6a6acSopenharmony_ci 2196cd6a6acSopenharmony_ci *response = 0; 2206cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2216cd6a6acSopenharmony_ci 2226cd6a6acSopenharmony_ci err: 2236cd6a6acSopenharmony_ci ERR(handle, "could not check if node %s/%s (%s) exists", 2246cd6a6acSopenharmony_ci addr, mask, sepol_node_get_proto_str(proto)); 2256cd6a6acSopenharmony_ci return STATUS_ERR; 2266cd6a6acSopenharmony_ci} 2276cd6a6acSopenharmony_ci 2286cd6a6acSopenharmony_ci/* Query a node */ 2296cd6a6acSopenharmony_ciint sepol_node_query(sepol_handle_t * handle, 2306cd6a6acSopenharmony_ci const sepol_policydb_t * p, 2316cd6a6acSopenharmony_ci const sepol_node_key_t * key, sepol_node_t ** response) 2326cd6a6acSopenharmony_ci{ 2336cd6a6acSopenharmony_ci 2346cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 2356cd6a6acSopenharmony_ci ocontext_t *c, *head; 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_ci int proto; 2386cd6a6acSopenharmony_ci const char *addr, *mask; 2396cd6a6acSopenharmony_ci sepol_node_key_unpack(key, &addr, &mask, &proto); 2406cd6a6acSopenharmony_ci 2416cd6a6acSopenharmony_ci switch (proto) { 2426cd6a6acSopenharmony_ci 2436cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 2446cd6a6acSopenharmony_ci { 2456cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE]; 2466cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2476cd6a6acSopenharmony_ci unsigned int *addr2 = &c->u.node.addr; 2486cd6a6acSopenharmony_ci unsigned int *mask2 = &c->u.node.mask; 2496cd6a6acSopenharmony_ci 2506cd6a6acSopenharmony_ci if (!memcmp(addr, addr2, 4) && 2516cd6a6acSopenharmony_ci !memcmp(mask, mask2, 4)) { 2526cd6a6acSopenharmony_ci 2536cd6a6acSopenharmony_ci if (node_to_record(handle, policydb, 2546cd6a6acSopenharmony_ci c, SEPOL_PROTO_IP4, 2556cd6a6acSopenharmony_ci response) < 0) 2566cd6a6acSopenharmony_ci goto err; 2576cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2586cd6a6acSopenharmony_ci } 2596cd6a6acSopenharmony_ci } 2606cd6a6acSopenharmony_ci break; 2616cd6a6acSopenharmony_ci } 2626cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 2636cd6a6acSopenharmony_ci { 2646cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE6]; 2656cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2666cd6a6acSopenharmony_ci unsigned int *addr2 = c->u.node6.addr; 2676cd6a6acSopenharmony_ci unsigned int *mask2 = c->u.node6.mask; 2686cd6a6acSopenharmony_ci 2696cd6a6acSopenharmony_ci if (!memcmp(addr, addr2, 16) && 2706cd6a6acSopenharmony_ci !memcmp(mask, mask2, 16)) { 2716cd6a6acSopenharmony_ci 2726cd6a6acSopenharmony_ci if (node_to_record(handle, policydb, 2736cd6a6acSopenharmony_ci c, SEPOL_PROTO_IP6, 2746cd6a6acSopenharmony_ci response) < 0) 2756cd6a6acSopenharmony_ci goto err; 2766cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2776cd6a6acSopenharmony_ci } 2786cd6a6acSopenharmony_ci } 2796cd6a6acSopenharmony_ci break; 2806cd6a6acSopenharmony_ci } 2816cd6a6acSopenharmony_ci default: 2826cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 2836cd6a6acSopenharmony_ci goto err; 2846cd6a6acSopenharmony_ci } 2856cd6a6acSopenharmony_ci *response = NULL; 2866cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2876cd6a6acSopenharmony_ci 2886cd6a6acSopenharmony_ci err: 2896cd6a6acSopenharmony_ci ERR(handle, "could not query node %s/%s (%s)", 2906cd6a6acSopenharmony_ci addr, mask, sepol_node_get_proto_str(proto)); 2916cd6a6acSopenharmony_ci return STATUS_ERR; 2926cd6a6acSopenharmony_ci 2936cd6a6acSopenharmony_ci} 2946cd6a6acSopenharmony_ci 2956cd6a6acSopenharmony_ci/* Load a node into policy */ 2966cd6a6acSopenharmony_ciint sepol_node_modify(sepol_handle_t * handle, 2976cd6a6acSopenharmony_ci sepol_policydb_t * p, 2986cd6a6acSopenharmony_ci const sepol_node_key_t * key, const sepol_node_t * data) 2996cd6a6acSopenharmony_ci{ 3006cd6a6acSopenharmony_ci 3016cd6a6acSopenharmony_ci policydb_t *policydb = &p->p; 3026cd6a6acSopenharmony_ci ocontext_t *node = NULL; 3036cd6a6acSopenharmony_ci 3046cd6a6acSopenharmony_ci int proto; 3056cd6a6acSopenharmony_ci const char *addr, *mask; 3066cd6a6acSopenharmony_ci 3076cd6a6acSopenharmony_ci sepol_node_key_unpack(key, &addr, &mask, &proto); 3086cd6a6acSopenharmony_ci 3096cd6a6acSopenharmony_ci if (node_from_record(handle, policydb, &node, data) < 0) 3106cd6a6acSopenharmony_ci goto err; 3116cd6a6acSopenharmony_ci 3126cd6a6acSopenharmony_ci switch (proto) { 3136cd6a6acSopenharmony_ci 3146cd6a6acSopenharmony_ci case SEPOL_PROTO_IP4: 3156cd6a6acSopenharmony_ci { 3166cd6a6acSopenharmony_ci /* Attach to context list */ 3176cd6a6acSopenharmony_ci node->next = policydb->ocontexts[OCON_NODE]; 3186cd6a6acSopenharmony_ci policydb->ocontexts[OCON_NODE] = node; 3196cd6a6acSopenharmony_ci break; 3206cd6a6acSopenharmony_ci } 3216cd6a6acSopenharmony_ci case SEPOL_PROTO_IP6: 3226cd6a6acSopenharmony_ci { 3236cd6a6acSopenharmony_ci /* Attach to context list */ 3246cd6a6acSopenharmony_ci node->next = policydb->ocontexts[OCON_NODE6]; 3256cd6a6acSopenharmony_ci policydb->ocontexts[OCON_NODE6] = node; 3266cd6a6acSopenharmony_ci break; 3276cd6a6acSopenharmony_ci } 3286cd6a6acSopenharmony_ci default: 3296cd6a6acSopenharmony_ci ERR(handle, "unsupported protocol %u", proto); 3306cd6a6acSopenharmony_ci goto err; 3316cd6a6acSopenharmony_ci } 3326cd6a6acSopenharmony_ci 3336cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3346cd6a6acSopenharmony_ci 3356cd6a6acSopenharmony_ci err: 3366cd6a6acSopenharmony_ci ERR(handle, "could not load node %s/%s (%s)", 3376cd6a6acSopenharmony_ci addr, mask, sepol_node_get_proto_str(proto)); 3386cd6a6acSopenharmony_ci if (node != NULL) { 3396cd6a6acSopenharmony_ci context_destroy(&node->context[0]); 3406cd6a6acSopenharmony_ci free(node); 3416cd6a6acSopenharmony_ci } 3426cd6a6acSopenharmony_ci return STATUS_ERR; 3436cd6a6acSopenharmony_ci} 3446cd6a6acSopenharmony_ci 3456cd6a6acSopenharmony_ciint sepol_node_iterate(sepol_handle_t * handle, 3466cd6a6acSopenharmony_ci const sepol_policydb_t * p, 3476cd6a6acSopenharmony_ci int (*fn) (const sepol_node_t * node, 3486cd6a6acSopenharmony_ci void *fn_arg), void *arg) 3496cd6a6acSopenharmony_ci{ 3506cd6a6acSopenharmony_ci 3516cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 3526cd6a6acSopenharmony_ci ocontext_t *c, *head; 3536cd6a6acSopenharmony_ci sepol_node_t *node = NULL; 3546cd6a6acSopenharmony_ci int status; 3556cd6a6acSopenharmony_ci 3566cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE]; 3576cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 3586cd6a6acSopenharmony_ci if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node) 3596cd6a6acSopenharmony_ci < 0) 3606cd6a6acSopenharmony_ci goto err; 3616cd6a6acSopenharmony_ci 3626cd6a6acSopenharmony_ci /* Invoke handler */ 3636cd6a6acSopenharmony_ci status = fn(node, arg); 3646cd6a6acSopenharmony_ci if (status < 0) 3656cd6a6acSopenharmony_ci goto err; 3666cd6a6acSopenharmony_ci 3676cd6a6acSopenharmony_ci sepol_node_free(node); 3686cd6a6acSopenharmony_ci node = NULL; 3696cd6a6acSopenharmony_ci 3706cd6a6acSopenharmony_ci /* Handler requested exit */ 3716cd6a6acSopenharmony_ci if (status > 0) 3726cd6a6acSopenharmony_ci break; 3736cd6a6acSopenharmony_ci } 3746cd6a6acSopenharmony_ci 3756cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NODE6]; 3766cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 3776cd6a6acSopenharmony_ci if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node) 3786cd6a6acSopenharmony_ci < 0) 3796cd6a6acSopenharmony_ci goto err; 3806cd6a6acSopenharmony_ci 3816cd6a6acSopenharmony_ci /* Invoke handler */ 3826cd6a6acSopenharmony_ci status = fn(node, arg); 3836cd6a6acSopenharmony_ci if (status < 0) 3846cd6a6acSopenharmony_ci goto err; 3856cd6a6acSopenharmony_ci 3866cd6a6acSopenharmony_ci sepol_node_free(node); 3876cd6a6acSopenharmony_ci node = NULL; 3886cd6a6acSopenharmony_ci 3896cd6a6acSopenharmony_ci /* Handler requested exit */ 3906cd6a6acSopenharmony_ci if (status > 0) 3916cd6a6acSopenharmony_ci break; 3926cd6a6acSopenharmony_ci } 3936cd6a6acSopenharmony_ci 3946cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3956cd6a6acSopenharmony_ci 3966cd6a6acSopenharmony_ci err: 3976cd6a6acSopenharmony_ci ERR(handle, "could not iterate over nodes"); 3986cd6a6acSopenharmony_ci sepol_node_free(node); 3996cd6a6acSopenharmony_ci return STATUS_ERR; 4006cd6a6acSopenharmony_ci} 401