38 static const char* acl_str =
"acl";
47 acl_parse_range_type(
char* ip,
char** mask)
50 if((p=strchr(ip,
'&'))!=0) {
55 if((p=strchr(ip,
'/'))!=0) {
60 if((p=strchr(ip,
'-'))!=0) {
75 acl_parse_range_subnet(
char* p,
void* addr,
int maxbits)
77 int subnet_bits = atoi(p);
78 uint8_t* addr_bytes = (uint8_t*)addr;
79 if (subnet_bits == 0 && strcmp(p,
"0")!=0) {
80 return ODS_STATUS_ACL_SUBNET_BAD_RANGE;
82 if (subnet_bits < 0 || subnet_bits > maxbits) {
83 return ODS_STATUS_ACL_SUBNET_OUT_RANGE;
86 while(subnet_bits >= 8) {
92 {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
93 *addr_bytes = shifts[subnet_bits];
129 ods_status status = ODS_STATUS_OK;
139 ods_log_error(
"[%s] unable to create acl: tsig %s not found",
147 acl->
port = atoi((
const char*) port);
153 acl->
range_type = acl_parse_range_type(address, &p);
154 acl->
address = strdup(address);
156 ods_log_error(
"[%s] unable to create acl: allocator_strdup() "
161 if (acl->
family == AF_INET6) {
163 ods_log_error(
"[%s] unable to create acl: bad ipv6 address "
164 "(%s)", acl_str, acl->
address);
171 ods_log_error(
"[%s] unable to create acl: bad ipv6 address"
172 " mask (%s)", acl_str, p);
178 if (status != ODS_STATUS_OK) {
179 ods_log_error(
"[%s] unable to create acl: %s (%s)",
180 acl_str, ods_status2str(status), p);
185 }
else if (acl->
family == AF_INET) {
187 ods_log_error(
"[%s] unable to create acl: bad ipv4 address "
188 "(%s)", acl_str, acl->
address);
195 ods_log_error(
"[%s] unable to create acl: bad ipv4 address"
196 " mask (%s)", acl_str, p);
202 if (status != ODS_STATUS_OK) {
203 ods_log_error(
"[%s] unable to create acl: %s (%s)",
204 acl_str, ods_status2str(status), p);
221 acl_addr_matches_mask(uint32_t* a, uint32_t* b, uint32_t* mask,
size_t sz)
224 ods_log_assert(sz % 4 == 0);
226 for (i=0; i<sz; ++i) {
227 if (((*a++)&*mask) != ((*b++)&*mask)) {
240 acl_addr_matches_range(uint32_t* minval, uint32_t* x, uint32_t* maxval,
244 uint8_t checkmin = 1;
245 uint8_t checkmax = 1;
246 ods_log_assert(sz % 4 == 0);
249 for (i=0; i<sz; ++i) {
251 if (checkmin && minval[i] > x[i]) {
254 if (checkmax && maxval[i] < x[i]) {
258 if (checkmin && minval[i] != x[i]) {
261 if (checkmax && maxval[i]!=x[i]) {
264 if (!checkmin && !checkmax) {
277 acl_addr_matches(
acl_type* acl,
struct sockaddr_storage* addr)
286 if (acl->
family == AF_INET6) {
287 struct sockaddr_in6* addr6 = (
struct sockaddr_in6*) addr;
288 if (addr->ss_family != AF_INET6) {
291 if (acl->
port != 0 && acl->
port != ntohs(addr6->sin6_port)) {
297 if (!acl_addr_matches_mask((uint32_t*)&acl->
addr.
addr6,
298 (uint32_t*)&addr6->sin6_addr,
300 sizeof(
struct in6_addr))) {
305 if (!acl_addr_matches_range((uint32_t*)&acl->
addr.
addr6,
306 (uint32_t*)&addr6->sin6_addr,
308 sizeof(
struct in6_addr))) {
314 if (memcmp(&addr6->sin6_addr, &acl->
addr.
addr6,
315 sizeof(
struct in6_addr)) != 0) {
322 struct sockaddr_in* addr4 = (
struct sockaddr_in*)addr;
323 if (addr4->sin_family != AF_INET) {
326 if (acl->
port != 0 && acl->
port != ntohs(addr4->sin_port)) {
332 if (!acl_addr_matches_mask((uint32_t*)&acl->
addr.
addr,
333 (uint32_t*)&addr4->sin_addr,
335 sizeof(
struct in_addr))) {
340 if (!acl_addr_matches_range((uint32_t*)&acl->
addr.
addr,
341 (uint32_t*)&addr4->sin_addr,
343 sizeof(
struct in_addr))) {
349 if (memcmp(&addr4->sin_addr, &acl->
addr.
addr,
350 sizeof(
struct in_addr)) != 0) {
370 ods_log_debug(
"[%s] no match: no acl or tsig", acl_str);
377 ods_log_debug(
"[%s] no match: tsig present but no config", acl_str);
381 ods_log_debug(
"[%s] no match: tsig %s", acl_str,
386 ods_log_debug(
"[%s] no match: tsig error %d", acl_str,
391 ods_log_debug(
"[%s] no match: missing key/algo", acl_str);
395 ods_log_debug(
"[%s] no match: no config", acl_str);
399 ods_log_debug(
"[%s] no match: key names not the same", acl_str);
403 ods_log_debug(
"[%s] no match: algorithms not the same", acl_str);
416 addr2ip(
struct sockaddr_storage addr,
char* ip,
size_t len)
418 if (addr.ss_family == AF_INET6) {
419 if (!inet_ntop(AF_INET6, &((
struct sockaddr_in6 *)&addr)->sin6_addr,
424 if (!inet_ntop(AF_INET, &((
struct sockaddr_in *)&addr)->sin_addr,
441 if (acl_addr_matches(find, addr) && acl_tsig_matches(find, trr)) {
442 ods_log_debug(
"[%s] match %s", acl_str, find->
address);