1/* Copyright (C) 2017 Mellanox Technologies Inc. */
2
3struct semanage_ibpkey;
4struct semanage_ibpkey_key;
5typedef struct semanage_ibpkey_key record_key_t;
6typedef struct semanage_ibpkey record_t;
7#define DBASE_RECORD_DEFINED
8
9#include <stdlib.h>
10#include <string.h>
11#include <netinet/in.h>
12#include "ibpkey_internal.h"
13#include "debug.h"
14#include "handle.h"
15#include "database.h"
16
17int semanage_ibpkey_modify_local(semanage_handle_t *handle,
18				 const semanage_ibpkey_key_t *key,
19				 const semanage_ibpkey_t *data)
20{
21	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
22
23	return dbase_modify(handle, dconfig, key, data);
24}
25
26int semanage_ibpkey_del_local(semanage_handle_t *handle,
27			      const semanage_ibpkey_key_t *key)
28{
29	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
30
31	return dbase_del(handle, dconfig, key);
32}
33
34int semanage_ibpkey_query_local(semanage_handle_t *handle,
35				const semanage_ibpkey_key_t *key,
36				semanage_ibpkey_t **response)
37{
38	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
39
40	return dbase_query(handle, dconfig, key, response);
41}
42
43int semanage_ibpkey_exists_local(semanage_handle_t *handle,
44				 const semanage_ibpkey_key_t *key,
45				 int *response)
46{
47	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
48
49	return dbase_exists(handle, dconfig, key, response);
50}
51
52int semanage_ibpkey_count_local(semanage_handle_t *handle,
53				unsigned int *response)
54{
55	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
56
57	return dbase_count(handle, dconfig, response);
58}
59
60int semanage_ibpkey_iterate_local(semanage_handle_t *handle,
61				  int (*handler)(const semanage_ibpkey_t *record,
62						 void *varg), void *handler_arg)
63{
64	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
65
66	return dbase_iterate(handle, dconfig, handler, handler_arg);
67}
68
69int semanage_ibpkey_list_local(semanage_handle_t *handle,
70			       semanage_ibpkey_t ***records, unsigned int *count)
71{
72	dbase_config_t *dconfig = semanage_ibpkey_dbase_local(handle);
73
74	return dbase_list(handle, dconfig, records, count);
75}
76
77hidden_def(semanage_ibpkey_list_local)
78
79int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle)
80{
81	semanage_ibpkey_t **ibpkeys = NULL;
82	unsigned int nibpkeys = 0;
83	unsigned int i = 0, j = 0;
84	uint64_t subnet_prefix;
85	uint64_t subnet_prefix2;
86	char *subnet_prefix_str;
87	char *subnet_prefix_str2;
88	int low, high;
89	int low2, high2;
90
91	/* List and sort the ibpkeys */
92	if (semanage_ibpkey_list_local(handle, &ibpkeys, &nibpkeys) < 0)
93		goto err;
94
95	qsort(ibpkeys, nibpkeys, sizeof(semanage_ibpkey_t *),
96	      (int (*)(const void *, const void *))
97	      &semanage_ibpkey_compare2_qsort);
98
99	/* Test each ibpkey for overlap */
100	while (i < nibpkeys) {
101		if (STATUS_SUCCESS != semanage_ibpkey_get_subnet_prefix(handle,
102									ibpkeys[i],
103									&subnet_prefix_str)) {
104			ERR(handle, "Couldn't get subnet prefix string");
105			goto err;
106		}
107
108		subnet_prefix = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[i]);
109		low = semanage_ibpkey_get_low(ibpkeys[i]);
110		high = semanage_ibpkey_get_high(ibpkeys[i]);
111
112		/* Find the first ibpkey with matching
113		 * subnet_prefix to compare against
114		 */
115		do {
116			if (j == nibpkeys - 1)
117				goto next;
118			j++;
119
120			if (STATUS_SUCCESS !=
121				semanage_ibpkey_get_subnet_prefix(handle,
122								  ibpkeys[j],
123								  &subnet_prefix_str2)) {
124				ERR(handle, "Couldn't get subnet prefix string");
125				goto err;
126			}
127			subnet_prefix2 = semanage_ibpkey_get_subnet_prefix_bytes(ibpkeys[j]);
128			low2 = semanage_ibpkey_get_low(ibpkeys[j]);
129			high2 = semanage_ibpkey_get_high(ibpkeys[j]);
130		} while (subnet_prefix != subnet_prefix2);
131
132		/* Overlap detected */
133		if (low2 <= high) {
134			ERR(handle, "ibpkey overlap between ranges "
135			    "(%s) %u - %u <--> (%s) %u - %u.",
136			    subnet_prefix_str, low, high,
137			    subnet_prefix_str2, low2, high2);
138			goto invalid;
139		}
140
141		/* If closest ibpkey of matching subnet prefix doesn't overlap
142		 * with test ibpkey, neither do the rest of them, because that's
143		 * how the sort function works on ibpkeys - lower bound
144		 * ibpkeys come first
145		 */
146next:
147		i++;
148		j = i;
149	}
150
151	for (i = 0; i < nibpkeys; i++)
152		semanage_ibpkey_free(ibpkeys[i]);
153	free(ibpkeys);
154	return STATUS_SUCCESS;
155
156err:
157	ERR(handle, "could not complete ibpkeys validity check");
158
159invalid:
160	for (i = 0; i < nibpkeys; i++)
161		semanage_ibpkey_free(ibpkeys[i]);
162	free(ibpkeys);
163	return STATUS_ERR;
164}
165