16cd6a6acSopenharmony_ci#include <netinet/in.h> 26cd6a6acSopenharmony_ci#include <stdlib.h> 36cd6a6acSopenharmony_ci 46cd6a6acSopenharmony_ci#include "debug.h" 56cd6a6acSopenharmony_ci#include "context.h" 66cd6a6acSopenharmony_ci#include "handle.h" 76cd6a6acSopenharmony_ci 86cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 96cd6a6acSopenharmony_ci#include "ibendport_internal.h" 106cd6a6acSopenharmony_ci 116cd6a6acSopenharmony_ci/* Create a low level ibendport structure from 126cd6a6acSopenharmony_ci * a high level representation 136cd6a6acSopenharmony_ci */ 146cd6a6acSopenharmony_cistatic int ibendport_from_record(sepol_handle_t *handle, 156cd6a6acSopenharmony_ci const policydb_t *policydb, 166cd6a6acSopenharmony_ci ocontext_t **ibendport, 176cd6a6acSopenharmony_ci const sepol_ibendport_t *data) 186cd6a6acSopenharmony_ci{ 196cd6a6acSopenharmony_ci ocontext_t *tmp_ibendport = NULL; 206cd6a6acSopenharmony_ci context_struct_t *tmp_con = NULL; 216cd6a6acSopenharmony_ci char *ibdev_name = NULL; 226cd6a6acSopenharmony_ci int port = sepol_ibendport_get_port(data); 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t)); 256cd6a6acSopenharmony_ci if (!tmp_ibendport) 266cd6a6acSopenharmony_ci goto omem; 276cd6a6acSopenharmony_ci 286cd6a6acSopenharmony_ci if (sepol_ibendport_alloc_ibdev_name(handle, 296cd6a6acSopenharmony_ci &tmp_ibendport->u.ibendport.dev_name) < 0) 306cd6a6acSopenharmony_ci goto omem; 316cd6a6acSopenharmony_ci 326cd6a6acSopenharmony_ci if (sepol_ibendport_get_ibdev_name(handle, 336cd6a6acSopenharmony_ci data, 346cd6a6acSopenharmony_ci &ibdev_name) < 0) 356cd6a6acSopenharmony_ci goto err; 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_ci strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1); 386cd6a6acSopenharmony_ci 396cd6a6acSopenharmony_ci free(ibdev_name); 406cd6a6acSopenharmony_ci ibdev_name = NULL; 416cd6a6acSopenharmony_ci 426cd6a6acSopenharmony_ci tmp_ibendport->u.ibendport.port = port; 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_ci /* Context */ 456cd6a6acSopenharmony_ci if (context_from_record(handle, policydb, &tmp_con, 466cd6a6acSopenharmony_ci sepol_ibendport_get_con(data)) < 0) 476cd6a6acSopenharmony_ci goto err; 486cd6a6acSopenharmony_ci context_cpy(&tmp_ibendport->context[0], tmp_con); 496cd6a6acSopenharmony_ci context_destroy(tmp_con); 506cd6a6acSopenharmony_ci free(tmp_con); 516cd6a6acSopenharmony_ci tmp_con = NULL; 526cd6a6acSopenharmony_ci 536cd6a6acSopenharmony_ci *ibendport = tmp_ibendport; 546cd6a6acSopenharmony_ci return STATUS_SUCCESS; 556cd6a6acSopenharmony_ci 566cd6a6acSopenharmony_ciomem: 576cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 586cd6a6acSopenharmony_ci 596cd6a6acSopenharmony_cierr: 606cd6a6acSopenharmony_ci if (tmp_ibendport) { 616cd6a6acSopenharmony_ci context_destroy(&tmp_ibendport->context[0]); 626cd6a6acSopenharmony_ci free(tmp_ibendport); 636cd6a6acSopenharmony_ci } 646cd6a6acSopenharmony_ci context_destroy(tmp_con); 656cd6a6acSopenharmony_ci free(tmp_con); 666cd6a6acSopenharmony_ci free(ibdev_name); 676cd6a6acSopenharmony_ci ERR(handle, "could not create ibendport structure"); 686cd6a6acSopenharmony_ci return STATUS_ERR; 696cd6a6acSopenharmony_ci} 706cd6a6acSopenharmony_ci 716cd6a6acSopenharmony_cistatic int ibendport_to_record(sepol_handle_t *handle, 726cd6a6acSopenharmony_ci const policydb_t *policydb, 736cd6a6acSopenharmony_ci ocontext_t *ibendport, 746cd6a6acSopenharmony_ci sepol_ibendport_t **record) 756cd6a6acSopenharmony_ci{ 766cd6a6acSopenharmony_ci int port = ibendport->u.ibendport.port; 776cd6a6acSopenharmony_ci context_struct_t *con = &ibendport->context[0]; 786cd6a6acSopenharmony_ci 796cd6a6acSopenharmony_ci sepol_context_t *tmp_con = NULL; 806cd6a6acSopenharmony_ci sepol_ibendport_t *tmp_record = NULL; 816cd6a6acSopenharmony_ci 826cd6a6acSopenharmony_ci if (sepol_ibendport_create(handle, &tmp_record) < 0) 836cd6a6acSopenharmony_ci goto err; 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_ci if (sepol_ibendport_set_ibdev_name(handle, tmp_record, 866cd6a6acSopenharmony_ci ibendport->u.ibendport.dev_name) < 0) 876cd6a6acSopenharmony_ci goto err; 886cd6a6acSopenharmony_ci 896cd6a6acSopenharmony_ci sepol_ibendport_set_port(tmp_record, port); 906cd6a6acSopenharmony_ci 916cd6a6acSopenharmony_ci if (context_to_record(handle, policydb, con, &tmp_con) < 0) 926cd6a6acSopenharmony_ci goto err; 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0) 956cd6a6acSopenharmony_ci goto err; 966cd6a6acSopenharmony_ci 976cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 986cd6a6acSopenharmony_ci *record = tmp_record; 996cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1006cd6a6acSopenharmony_ci 1016cd6a6acSopenharmony_cierr: 1026cd6a6acSopenharmony_ci ERR(handle, "could not convert ibendport to record"); 1036cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 1046cd6a6acSopenharmony_ci sepol_ibendport_free(tmp_record); 1056cd6a6acSopenharmony_ci return STATUS_ERR; 1066cd6a6acSopenharmony_ci} 1076cd6a6acSopenharmony_ci 1086cd6a6acSopenharmony_ci/* Return the number of ibendports */ 1096cd6a6acSopenharmony_ciextern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)), 1106cd6a6acSopenharmony_ci const sepol_policydb_t *p, unsigned int *response) 1116cd6a6acSopenharmony_ci{ 1126cd6a6acSopenharmony_ci unsigned int count = 0; 1136cd6a6acSopenharmony_ci ocontext_t *c, *head; 1146cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBENDPORT]; 1176cd6a6acSopenharmony_ci for (c = head; c; c = c->next) 1186cd6a6acSopenharmony_ci count++; 1196cd6a6acSopenharmony_ci 1206cd6a6acSopenharmony_ci *response = count; 1216cd6a6acSopenharmony_ci 1226cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1236cd6a6acSopenharmony_ci} 1246cd6a6acSopenharmony_ci 1256cd6a6acSopenharmony_ci/* Check if a ibendport exists */ 1266cd6a6acSopenharmony_ciint sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)), 1276cd6a6acSopenharmony_ci const sepol_policydb_t *p, 1286cd6a6acSopenharmony_ci const sepol_ibendport_key_t *key, int *response) 1296cd6a6acSopenharmony_ci{ 1306cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1316cd6a6acSopenharmony_ci ocontext_t *c, *head; 1326cd6a6acSopenharmony_ci int port; 1336cd6a6acSopenharmony_ci const char *ibdev_name; 1346cd6a6acSopenharmony_ci 1356cd6a6acSopenharmony_ci sepol_ibendport_key_unpack(key, &ibdev_name, &port); 1366cd6a6acSopenharmony_ci 1376cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBENDPORT]; 1386cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1396cd6a6acSopenharmony_ci const char *ibdev_name2 = c->u.ibendport.dev_name; 1406cd6a6acSopenharmony_ci int port2 = c->u.ibendport.port; 1416cd6a6acSopenharmony_ci 1426cd6a6acSopenharmony_ci if (port2 == port && 1436cd6a6acSopenharmony_ci (!strcmp(ibdev_name, ibdev_name2))) { 1446cd6a6acSopenharmony_ci *response = 1; 1456cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1466cd6a6acSopenharmony_ci } 1476cd6a6acSopenharmony_ci } 1486cd6a6acSopenharmony_ci 1496cd6a6acSopenharmony_ci *response = 0; 1506cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1516cd6a6acSopenharmony_ci} 1526cd6a6acSopenharmony_ci 1536cd6a6acSopenharmony_ciint sepol_ibendport_query(sepol_handle_t *handle, 1546cd6a6acSopenharmony_ci const sepol_policydb_t *p, 1556cd6a6acSopenharmony_ci const sepol_ibendport_key_t *key, 1566cd6a6acSopenharmony_ci sepol_ibendport_t **response) 1576cd6a6acSopenharmony_ci{ 1586cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1596cd6a6acSopenharmony_ci ocontext_t *c, *head; 1606cd6a6acSopenharmony_ci int port; 1616cd6a6acSopenharmony_ci const char *ibdev_name; 1626cd6a6acSopenharmony_ci 1636cd6a6acSopenharmony_ci sepol_ibendport_key_unpack(key, &ibdev_name, &port); 1646cd6a6acSopenharmony_ci 1656cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBENDPORT]; 1666cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1676cd6a6acSopenharmony_ci const char *ibdev_name2 = c->u.ibendport.dev_name; 1686cd6a6acSopenharmony_ci int port2 = c->u.ibendport.port; 1696cd6a6acSopenharmony_ci 1706cd6a6acSopenharmony_ci if (port2 == port && 1716cd6a6acSopenharmony_ci (!strcmp(ibdev_name, ibdev_name2))) { 1726cd6a6acSopenharmony_ci if (ibendport_to_record(handle, policydb, c, response) < 0) 1736cd6a6acSopenharmony_ci goto err; 1746cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1756cd6a6acSopenharmony_ci } 1766cd6a6acSopenharmony_ci } 1776cd6a6acSopenharmony_ci 1786cd6a6acSopenharmony_ci *response = NULL; 1796cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1806cd6a6acSopenharmony_ci 1816cd6a6acSopenharmony_cierr: 1826cd6a6acSopenharmony_ci ERR(handle, "could not query ibendport, IB device: %s port %u", 1836cd6a6acSopenharmony_ci ibdev_name, port); 1846cd6a6acSopenharmony_ci return STATUS_ERR; 1856cd6a6acSopenharmony_ci} 1866cd6a6acSopenharmony_ci 1876cd6a6acSopenharmony_ci/* Load a ibendport into policy */ 1886cd6a6acSopenharmony_ciint sepol_ibendport_modify(sepol_handle_t *handle, 1896cd6a6acSopenharmony_ci sepol_policydb_t *p, 1906cd6a6acSopenharmony_ci const sepol_ibendport_key_t *key, 1916cd6a6acSopenharmony_ci const sepol_ibendport_t *data) 1926cd6a6acSopenharmony_ci{ 1936cd6a6acSopenharmony_ci policydb_t *policydb = &p->p; 1946cd6a6acSopenharmony_ci ocontext_t *ibendport = NULL; 1956cd6a6acSopenharmony_ci int port; 1966cd6a6acSopenharmony_ci const char *ibdev_name; 1976cd6a6acSopenharmony_ci 1986cd6a6acSopenharmony_ci sepol_ibendport_key_unpack(key, &ibdev_name, &port); 1996cd6a6acSopenharmony_ci 2006cd6a6acSopenharmony_ci if (ibendport_from_record(handle, policydb, &ibendport, data) < 0) 2016cd6a6acSopenharmony_ci goto err; 2026cd6a6acSopenharmony_ci 2036cd6a6acSopenharmony_ci /* Attach to context list */ 2046cd6a6acSopenharmony_ci ibendport->next = policydb->ocontexts[OCON_IBENDPORT]; 2056cd6a6acSopenharmony_ci policydb->ocontexts[OCON_IBENDPORT] = ibendport; 2066cd6a6acSopenharmony_ci 2076cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2086cd6a6acSopenharmony_ci 2096cd6a6acSopenharmony_cierr: 2106cd6a6acSopenharmony_ci ERR(handle, "could not load ibendport %s/%d", 2116cd6a6acSopenharmony_ci ibdev_name, port); 2126cd6a6acSopenharmony_ci if (ibendport) { 2136cd6a6acSopenharmony_ci context_destroy(&ibendport->context[0]); 2146cd6a6acSopenharmony_ci free(ibendport); 2156cd6a6acSopenharmony_ci } 2166cd6a6acSopenharmony_ci return STATUS_ERR; 2176cd6a6acSopenharmony_ci} 2186cd6a6acSopenharmony_ci 2196cd6a6acSopenharmony_ciint sepol_ibendport_iterate(sepol_handle_t *handle, 2206cd6a6acSopenharmony_ci const sepol_policydb_t *p, 2216cd6a6acSopenharmony_ci int (*fn)(const sepol_ibendport_t *ibendport, 2226cd6a6acSopenharmony_ci void *fn_arg), void *arg) 2236cd6a6acSopenharmony_ci{ 2246cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 2256cd6a6acSopenharmony_ci ocontext_t *c, *head; 2266cd6a6acSopenharmony_ci sepol_ibendport_t *ibendport = NULL; 2276cd6a6acSopenharmony_ci 2286cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBENDPORT]; 2296cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2306cd6a6acSopenharmony_ci int status; 2316cd6a6acSopenharmony_ci 2326cd6a6acSopenharmony_ci if (ibendport_to_record(handle, policydb, c, &ibendport) < 0) 2336cd6a6acSopenharmony_ci goto err; 2346cd6a6acSopenharmony_ci 2356cd6a6acSopenharmony_ci /* Invoke handler */ 2366cd6a6acSopenharmony_ci status = fn(ibendport, arg); 2376cd6a6acSopenharmony_ci if (status < 0) 2386cd6a6acSopenharmony_ci goto err; 2396cd6a6acSopenharmony_ci 2406cd6a6acSopenharmony_ci sepol_ibendport_free(ibendport); 2416cd6a6acSopenharmony_ci ibendport = NULL; 2426cd6a6acSopenharmony_ci 2436cd6a6acSopenharmony_ci /* Handler requested exit */ 2446cd6a6acSopenharmony_ci if (status > 0) 2456cd6a6acSopenharmony_ci break; 2466cd6a6acSopenharmony_ci } 2476cd6a6acSopenharmony_ci 2486cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2496cd6a6acSopenharmony_ci 2506cd6a6acSopenharmony_cierr: 2516cd6a6acSopenharmony_ci ERR(handle, "could not iterate over ibendports"); 2526cd6a6acSopenharmony_ci sepol_ibendport_free(ibendport); 2536cd6a6acSopenharmony_ci return STATUS_ERR; 2546cd6a6acSopenharmony_ci} 255