47 |
|
|
48 |
/************************* ADDRESS GROUP HANDLER *************************/ |
/************************* ADDRESS GROUP HANDLER *************************/ |
49 |
|
|
50 |
static ADDRESS_GROUP_ENTRY *group_list = NULL; |
static struct address_group_entry *group_list = NULL; |
51 |
|
|
52 |
static int AddAddressGroupEntry(const char *group_name, const u8 is_ipv6, const u16 *min_address, const u16 *max_address, const int is_delete) |
static int AddAddressGroupEntry(const char *group_name, const u8 is_ipv6, const u16 *min_address, const u16 *max_address, const int is_delete) |
53 |
{ |
{ |
54 |
static DECLARE_MUTEX(lock); |
static DECLARE_MUTEX(lock); |
55 |
ADDRESS_GROUP_ENTRY *new_group, *group; |
struct address_group_entry *new_group, *group; |
56 |
ADDRESS_GROUP_MEMBER *new_member, *member; |
struct address_group_member *new_member, *member; |
57 |
const struct path_info *saved_group_name; |
const struct path_info *saved_group_name; |
58 |
int error = -ENOMEM; |
int error = -ENOMEM; |
59 |
if (!IsCorrectPath(group_name, 0, 0, 0, __FUNCTION__) || !group_name[0]) return -EINVAL; |
if (!IsCorrectPath(group_name, 0, 0, 0, __FUNCTION__) || !group_name[0]) return -EINVAL; |
79 |
goto out; |
goto out; |
80 |
} |
} |
81 |
if (!group) { |
if (!group) { |
82 |
if ((new_group = (ADDRESS_GROUP_ENTRY *) alloc_element(sizeof(ADDRESS_GROUP_ENTRY))) == NULL) goto out; |
if ((new_group = alloc_element(sizeof(*new_group))) == NULL) goto out; |
83 |
new_group->group_name = saved_group_name; |
new_group->group_name = saved_group_name; |
84 |
mb(); /* Instead of using spinlock. */ |
mb(); /* Instead of using spinlock. */ |
85 |
if ((group = group_list) != NULL) { |
if ((group = group_list) != NULL) { |
89 |
} |
} |
90 |
group = new_group; |
group = new_group; |
91 |
} |
} |
92 |
if ((new_member = (ADDRESS_GROUP_MEMBER *) alloc_element(sizeof(ADDRESS_GROUP_MEMBER))) == NULL) goto out; |
if ((new_member = alloc_element(sizeof(*new_member))) == NULL) goto out; |
93 |
new_member->is_ipv6 = is_ipv6; |
new_member->is_ipv6 = is_ipv6; |
94 |
if (is_ipv6) { |
if (is_ipv6) { |
95 |
memmove(new_member->min.ipv6, min_address, 16); |
memmove(new_member->min.ipv6, min_address, 16); |
143 |
return AddAddressGroupEntry(data, is_ipv6, min_address, max_address, is_delete); |
return AddAddressGroupEntry(data, is_ipv6, min_address, max_address, is_delete); |
144 |
} |
} |
145 |
|
|
146 |
static ADDRESS_GROUP_ENTRY *FindOrAssignNewAddressGroup(const char *group_name) |
static struct address_group_entry *FindOrAssignNewAddressGroup(const char *group_name) |
147 |
{ |
{ |
148 |
int i; |
int i; |
149 |
ADDRESS_GROUP_ENTRY *group; |
struct address_group_entry *group; |
150 |
for (i = 0; i <= 1; i++) { |
for (i = 0; i <= 1; i++) { |
151 |
for (group = group_list; group; group = group->next) { |
for (group = group_list; group; group = group->next) { |
152 |
if (strcmp(group_name, group->group_name->name) == 0) return group; |
if (strcmp(group_name, group->group_name->name) == 0) return group; |
160 |
return NULL; |
return NULL; |
161 |
} |
} |
162 |
|
|
163 |
static int AddressMatchesToGroup(const u8 is_ipv6, const u32 *address, const ADDRESS_GROUP_ENTRY *group) |
static int AddressMatchesToGroup(const u8 is_ipv6, const u32 *address, const struct address_group_entry *group) |
164 |
{ |
{ |
165 |
ADDRESS_GROUP_MEMBER *member; |
struct address_group_member *member; |
166 |
const u32 ip = ntohl(*address); |
const u32 ip = ntohl(*address); |
167 |
for (member = group->first_member; member; member = member->next) { |
for (member = group->first_member; member; member = member->next) { |
168 |
if (member->is_deleted) continue; |
if (member->is_deleted) continue; |
175 |
return 0; |
return 0; |
176 |
} |
} |
177 |
|
|
178 |
int ReadAddressGroupPolicy(IO_BUFFER *head) |
int ReadAddressGroupPolicy(struct io_buffer *head) |
179 |
{ |
{ |
180 |
ADDRESS_GROUP_ENTRY *group = (ADDRESS_GROUP_ENTRY *) head->read_var1; |
struct address_group_entry *group = head->read_var1; |
181 |
ADDRESS_GROUP_MEMBER *member = (ADDRESS_GROUP_MEMBER *) head->read_var2; |
struct address_group_member *member = head->read_var2; |
182 |
if (!group) group = group_list; |
if (!group) group = group_list; |
183 |
while (group) { |
while (group) { |
184 |
head->read_var1 = (struct domain_info *) group; |
head->read_var1 = group; |
185 |
if (!member) member = group->first_member; |
if (!member) member = group->first_member; |
186 |
while (member) { |
while (member) { |
187 |
head->read_var2 = (void *) member; |
head->read_var2 = member; |
188 |
if (!member->is_deleted) { |
if (!member->is_deleted) { |
189 |
char buf[128]; |
char buf[128]; |
190 |
if (member->is_ipv6) { |
if (member->is_ipv6) { |
266 |
if (is_add) { |
if (is_add) { |
267 |
if ((ptr = domain->first_acl_ptr) == NULL) goto first_entry; |
if ((ptr = domain->first_acl_ptr) == NULL) goto first_entry; |
268 |
while (1) { |
while (1) { |
269 |
IP_NETWORK_ACL_RECORD *new_ptr; |
struct ip_network_acl_record *new_ptr; |
270 |
if (ptr->type == TYPE_IP_NETWORK_ACL && ptr->u.b[0] == operation && ptr->u.b[1] == record_type && ptr->cond == condition && ((IP_NETWORK_ACL_RECORD *) ptr)->min_port == min_port && max_port == ((IP_NETWORK_ACL_RECORD *) ptr)->max_port) { |
if (ptr->type == TYPE_IP_NETWORK_ACL && ptr->u.b[0] == operation && ptr->u.b[1] == record_type && ptr->cond == condition && ((struct ip_network_acl_record *) ptr)->min_port == min_port && max_port == ((struct ip_network_acl_record *) ptr)->max_port) { |
271 |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
272 |
if (((IP_NETWORK_ACL_RECORD *) ptr)->u.group == group) { |
if (((struct ip_network_acl_record *) ptr)->u.group == group) { |
273 |
ptr->is_deleted = 0; |
ptr->is_deleted = 0; |
274 |
/* Found. Nothing to do. */ |
/* Found. Nothing to do. */ |
275 |
error = 0; |
error = 0; |
276 |
break; |
break; |
277 |
} |
} |
278 |
} else if (record_type == IP_RECORD_TYPE_IPv4) { |
} else if (record_type == IP_RECORD_TYPE_IPv4) { |
279 |
if (((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.min == min_ip && max_ip == ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.max) { |
if (((struct ip_network_acl_record *) ptr)->u.ipv4.min == min_ip && max_ip == ((struct ip_network_acl_record *) ptr)->u.ipv4.max) { |
280 |
ptr->is_deleted = 0; |
ptr->is_deleted = 0; |
281 |
/* Found. Nothing to do. */ |
/* Found. Nothing to do. */ |
282 |
error = 0; |
error = 0; |
283 |
break; |
break; |
284 |
} |
} |
285 |
} else if (record_type == IP_RECORD_TYPE_IPv6) { |
} else if (record_type == IP_RECORD_TYPE_IPv6) { |
286 |
if (memcmp(((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.min, min_address, 16) == 0 && memcmp(max_address, ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.max, 16) == 0) { |
if (memcmp(((struct ip_network_acl_record *) ptr)->u.ipv6.min, min_address, 16) == 0 && memcmp(max_address, ((struct ip_network_acl_record *) ptr)->u.ipv6.max, 16) == 0) { |
287 |
ptr->is_deleted = 0; |
ptr->is_deleted = 0; |
288 |
/* Found. Nothing to do. */ |
/* Found. Nothing to do. */ |
289 |
error = 0; |
error = 0; |
298 |
first_entry: ; |
first_entry: ; |
299 |
if (is_add == 1 && TooManyDomainACL(domain)) break; |
if (is_add == 1 && TooManyDomainACL(domain)) break; |
300 |
/* Not found. Append it to the tail. */ |
/* Not found. Append it to the tail. */ |
301 |
if ((new_ptr = (IP_NETWORK_ACL_RECORD *) alloc_element(sizeof(IP_NETWORK_ACL_RECORD))) == NULL) break; |
if ((new_ptr = alloc_element(sizeof(*new_ptr))) == NULL) break; |
302 |
new_ptr->head.type = TYPE_IP_NETWORK_ACL; |
new_ptr->head.type = TYPE_IP_NETWORK_ACL; |
303 |
new_ptr->head.u.b[0] = operation; |
new_ptr->head.u.b[0] = operation; |
304 |
new_ptr->head.u.b[1] = record_type; |
new_ptr->head.u.b[1] = record_type; |
320 |
} else { |
} else { |
321 |
error = -ENOENT; |
error = -ENOENT; |
322 |
for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { |
for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { |
323 |
if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr->u.b[0] != operation || ptr->u.b[1] != record_type || ptr->cond != condition || ((IP_NETWORK_ACL_RECORD *) ptr)->min_port != min_port || ((IP_NETWORK_ACL_RECORD *) ptr)->max_port != max_port) continue; |
if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr->u.b[0] != operation || ptr->u.b[1] != record_type || ptr->cond != condition || ((struct ip_network_acl_record *) ptr)->min_port != min_port || ((struct ip_network_acl_record *) ptr)->max_port != max_port) continue; |
324 |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
325 |
if (((IP_NETWORK_ACL_RECORD *) ptr)->u.group != group) continue; |
if (((struct ip_network_acl_record *) ptr)->u.group != group) continue; |
326 |
} else if (record_type == IP_RECORD_TYPE_IPv4) { |
} else if (record_type == IP_RECORD_TYPE_IPv4) { |
327 |
if (((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.min != min_ip || max_ip != ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.max) continue; |
if (((struct ip_network_acl_record *) ptr)->u.ipv4.min != min_ip || max_ip != ((struct ip_network_acl_record *) ptr)->u.ipv4.max) continue; |
328 |
} else if (record_type == IP_RECORD_TYPE_IPv6) { |
} else if (record_type == IP_RECORD_TYPE_IPv6) { |
329 |
if (memcmp(((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.min, min_address, 16) || memcmp(max_address, ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.max, 16)) continue; |
if (memcmp(((struct ip_network_acl_record *) ptr)->u.ipv6.min, min_address, 16) || memcmp(max_address, ((struct ip_network_acl_record *) ptr)->u.ipv6.max, 16)) continue; |
330 |
} |
} |
331 |
error = DelDomainACL(ptr); |
error = DelDomainACL(ptr); |
332 |
break; |
break; |
345 |
const u32 ip = ntohl(*address); /* using host byte order to allow u32 comparison than memcmp().*/ |
const u32 ip = ntohl(*address); /* using host byte order to allow u32 comparison than memcmp().*/ |
346 |
if (!CheckCCSFlags(CCS_TOMOYO_MAC_FOR_NETWORK)) return 0; |
if (!CheckCCSFlags(CCS_TOMOYO_MAC_FOR_NETWORK)) return 0; |
347 |
for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { |
for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { |
348 |
if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr->u.b[0] != operation || port < ((IP_NETWORK_ACL_RECORD *) ptr)->min_port || ((IP_NETWORK_ACL_RECORD *) ptr)->max_port < port || CheckCondition(ptr->cond, NULL)) continue; |
if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr->u.b[0] != operation || port < ((struct ip_network_acl_record *) ptr)->min_port || ((struct ip_network_acl_record *) ptr)->max_port < port || CheckCondition(ptr->cond, NULL)) continue; |
349 |
if (ptr->u.b[1] == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (ptr->u.b[1] == IP_RECORD_TYPE_ADDRESS_GROUP) { |
350 |
if (AddressMatchesToGroup(is_ipv6, address, ((IP_NETWORK_ACL_RECORD *) ptr)->u.group)) break; |
if (AddressMatchesToGroup(is_ipv6, address, ((struct ip_network_acl_record *) ptr)->u.group)) break; |
351 |
} else if (ptr->u.b[1] == IP_RECORD_TYPE_IPv4) { |
} else if (ptr->u.b[1] == IP_RECORD_TYPE_IPv4) { |
352 |
if (!is_ipv6 && ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.min <= ip && ip <= ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.max) break; |
if (!is_ipv6 && ((struct ip_network_acl_record *) ptr)->u.ipv4.min <= ip && ip <= ((struct ip_network_acl_record *) ptr)->u.ipv4.max) break; |
353 |
} else { |
} else { |
354 |
if (is_ipv6 && memcmp(((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.min, address, 16) <= 0 && memcmp(address, ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.max, 16) <= 0) break; |
if (is_ipv6 && memcmp(((struct ip_network_acl_record *) ptr)->u.ipv6.min, address, 16) <= 0 && memcmp(address, ((struct ip_network_acl_record *) ptr)->u.ipv6.max, 16) <= 0) break; |
355 |
} |
} |
356 |
} |
} |
357 |
if (ptr) { |
if (ptr) { |