5 |
* |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.6.0-pre 2008/01/18 |
* Version: 1.6.0-pre 2008/01/21 |
9 |
* |
* |
10 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
11 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
297 |
{ |
{ |
298 |
struct acl_info *ptr; |
struct acl_info *ptr; |
299 |
struct ip_network_acl_record *acl; |
struct ip_network_acl_record *acl; |
|
struct ip_network_acl_record_with_condition *p; |
|
300 |
int error = -ENOMEM; |
int error = -ENOMEM; |
301 |
const u32 min_ip = ntohl(*min_address), max_ip = ntohl(*max_address); /* using host byte order to allow u32 comparison than memcmp().*/ |
const u32 min_ip = ntohl(*min_address), max_ip = ntohl(*max_address); /* using host byte order to allow u32 comparison than memcmp().*/ |
302 |
const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL; |
const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL; |
308 |
mutex_lock(&domain_acl_lock); |
mutex_lock(&domain_acl_lock); |
309 |
if (!is_delete) { |
if (!is_delete) { |
310 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
311 |
switch (ptr->type & ~ACL_DELETED) { |
if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION)) != TYPE_IP_NETWORK_ACL) continue; |
312 |
case TYPE_IP_NETWORK_ACL: |
if (GetConditionPart(ptr) != condition) continue; |
313 |
if (condition) continue; |
acl = container_of(ptr, struct ip_network_acl_record, head); |
|
acl = container_of(ptr, struct ip_network_acl_record, head); |
|
|
break; |
|
|
case TYPE_IP_NETWORK_ACL_WITH_CONDITION: |
|
|
p = container_of(ptr, struct ip_network_acl_record_with_condition, record.head); |
|
|
if (p->condition != condition) continue; |
|
|
acl = &p->record; |
|
|
break; |
|
|
default: |
|
|
continue; |
|
|
} |
|
314 |
if (acl->operation_type != operation || acl->record_type != record_type || acl->min_port != min_port || max_port != acl->max_port) continue; |
if (acl->operation_type != operation || acl->record_type != record_type || acl->min_port != min_port || max_port != acl->max_port) continue; |
315 |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
316 |
if (acl->u.group != group) continue; |
if (acl->u.group != group) continue; |
323 |
goto out; |
goto out; |
324 |
} |
} |
325 |
/* Not found. Append it to the tail. */ |
/* Not found. Append it to the tail. */ |
326 |
if (condition) { |
if ((acl = alloc_acl_element(TYPE_IP_NETWORK_ACL, condition)) == NULL) goto out; |
|
if ((p = alloc_element(sizeof(*p))) == NULL) goto out; |
|
|
acl = &p->record; |
|
|
p->condition = condition; |
|
|
acl->head.type = TYPE_IP_NETWORK_ACL_WITH_CONDITION; |
|
|
} else { |
|
|
if ((acl = alloc_element(sizeof(*acl))) == NULL) goto out; |
|
|
acl->head.type = TYPE_IP_NETWORK_ACL; |
|
|
} |
|
327 |
acl->operation_type = operation; |
acl->operation_type = operation; |
328 |
acl->record_type = record_type; |
acl->record_type = record_type; |
329 |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
341 |
} else { |
} else { |
342 |
error = -ENOENT; |
error = -ENOENT; |
343 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
344 |
switch (ptr->type) { |
if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL) continue; |
345 |
case TYPE_IP_NETWORK_ACL: |
if (GetConditionPart(ptr) != condition) continue; |
346 |
if (condition) continue; |
acl = container_of(ptr, struct ip_network_acl_record, head); |
|
acl = container_of(ptr, struct ip_network_acl_record, head); |
|
|
break; |
|
|
case TYPE_IP_NETWORK_ACL_WITH_CONDITION: |
|
|
p = container_of(ptr, struct ip_network_acl_record_with_condition, record.head); |
|
|
if (p->condition != condition) continue; |
|
|
acl = &p->record; |
|
|
break; |
|
|
default: |
|
|
continue; |
|
|
} |
|
347 |
if (acl->operation_type != operation || acl->record_type != record_type || acl->min_port != min_port || max_port != acl->max_port) continue; |
if (acl->operation_type != operation || acl->record_type != record_type || acl->min_port != min_port || max_port != acl->max_port) continue; |
348 |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
349 |
if (acl->u.group != group) continue; |
if (acl->u.group != group) continue; |
374 |
if (!mode) return 0; |
if (!mode) return 0; |
375 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
376 |
struct ip_network_acl_record *acl; |
struct ip_network_acl_record *acl; |
377 |
struct ip_network_acl_record_with_condition *p; |
if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL) continue; |
378 |
const struct condition_list *cond; |
acl = container_of(ptr, struct ip_network_acl_record, head); |
379 |
switch (ptr->type) { |
if (acl->operation_type != operation || port < acl->min_port || acl->max_port < port || !CheckCondition(ptr, NULL)) continue; |
|
default: |
|
|
continue; |
|
|
case TYPE_IP_NETWORK_ACL: |
|
|
acl = container_of(ptr, struct ip_network_acl_record, head); |
|
|
cond = NULL; |
|
|
break; |
|
|
case TYPE_IP_NETWORK_ACL_WITH_CONDITION: |
|
|
p = container_of(ptr, struct ip_network_acl_record_with_condition, record.head); |
|
|
acl = &p->record; |
|
|
cond = p->condition; |
|
|
break; |
|
|
} |
|
|
if (acl->operation_type != operation || port < acl->min_port || acl->max_port < port || !CheckCondition(cond, NULL)) continue; |
|
380 |
if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) { |
381 |
if (!AddressMatchesToGroup(is_ipv6, address, acl->u.group)) continue; |
if (!AddressMatchesToGroup(is_ipv6, address, acl->u.group)) continue; |
382 |
} else if (acl->record_type == IP_RECORD_TYPE_IPv4) { |
} else if (acl->record_type == IP_RECORD_TYPE_IPv4) { |