root/src/modules/ip_acl.c

Revision 17458db8a05223809f885a032344956d81ade411, 6.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 2 years ago)

bad symbol name here, how did this ever work?

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2011, Circonus, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name Circonus, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34 #include "noit_module.h"
35 #include "noit_check.h"
36 #include "noit_check_tools.h"
37 #include "utils/noit_log.h"
38 #include "utils/noit_hash.h"
39 #include "utils/noit_btrie.h"
40 #include "ip_acl.xmlh"
41 #include <assert.h>
42
43 #define DENY_PTR (void *)-1
44 #define ALLOW_PTR (void *)1
45
46 static int ip_acl_module_id = -1;
47
48 static noit_hash_table acls = NOIT_HASH_EMPTY;
49
50 static void
51 free_btrie(void *vb) {
52   btrie *acl = vb;
53   if(acl) {
54     noit_drop_tree(acl, NULL);
55     free(acl);
56   }
57 }
58 static int
59 ip_acl_onload(noit_image_t *self) {
60   int i, cnt;
61   noit_conf_section_t *acl_c;
62   ip_acl_module_id = noit_check_register_module("ip_acl");
63   if(ip_acl_module_id < 0) return -1;
64
65   acl_c = noit_conf_get_sections(NULL, "/noit/acls//acl", &cnt);
66   if(acl_c) {
67     for(i=0; i<cnt; i++) {
68       char *name;
69       int j, rcnt, arcnt = 0;
70       noit_conf_section_t *rule_c;
71       if(noit_conf_get_string(acl_c[i], "@name", &name)) {
72         rule_c = noit_conf_get_sections(acl_c[i], "rule", &rcnt);
73         if(rule_c) {
74           btrie *acl = calloc(1, sizeof(*acl));
75           for(j=0; j<rcnt; j++) {
76             int mask = -1, rv;
77             char dirstr[16] = "unspecified";
78             char *cp, target[256] = "";
79             union {
80               struct in_addr addr4;
81               struct in6_addr addr6;
82             } a;
83
84             noit_conf_get_stringbuf(rule_c[j], "self::node()", target, sizeof(target));
85             if(NULL != (cp = strchr(target, '/'))) {
86               *cp++ = '\0';
87               mask = atoi(cp);
88             }
89             if(!noit_conf_get_stringbuf(rule_c[j], "@type", dirstr, sizeof(dirstr)) ||
90                (strcmp(dirstr, "deny") && strcmp(dirstr, "allow"))) {
91               noitL(noit_error, "Unknown acl rule type \"%s\" in acl \"%s\"\n",
92                     dirstr, name);
93             }
94             else if(inet_pton(AF_INET, target, &a) == 1) {
95               if(mask == -1) mask = 32;
96               noit_add_route_ipv4(acl, &a.addr4, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR);
97               arcnt++;
98             }
99             else if(inet_pton(AF_INET6, target, &a) == 1) {
100               if(mask == -1) mask = 128;
101               noit_add_route_ipv6(acl, &a.addr6, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR);
102               arcnt++;
103             }
104           }
105           noitL(noit_error, "ACL %s/%p -> %d/%d rules\n", name, acl, arcnt, rcnt);
106           noit_hash_replace(&acls, name, strlen(name), acl, free, free_btrie);
107           free(rule_c);
108         }
109       }
110     }
111     free(acl_c);
112   }
113   return 0;
114 }
115
116 static int
117 ip_acl_config(noit_module_generic_t *self, noit_hash_table *o) {
118   return 0;
119 }
120
121 static noit_hook_return_t
122 ip_acl_hook_impl(void *closure, noit_module_t *self,
123                  noit_check_t *check, noit_check_t *cause) {
124   char deny_msg[128];
125   stats_t current;
126   noit_hash_table *config;
127   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
128   const char *k = NULL;
129   int klen;
130   void *data;
131   config = noit_check_get_module_config(check, ip_acl_module_id);
132   if(!config || config->size == 0) return NOIT_HOOK_CONTINUE;
133   while(noit_hash_next(config, &iter, &k, &klen, &data)) {
134     if(k) {
135       void *dir = NULL;
136       unsigned char mask;
137       if(noit_hash_retrieve(&acls, k, strlen(k), &data)) {
138         btrie *acl = data;
139         if(check->target_family == AF_INET) {
140           dir = noit_find_bpm_route_ipv4(acl, &check->target_addr.addr, &mask);
141           if(dir == DENY_PTR) goto prevent;
142           else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE;
143         }
144         else if(check->target_family == AF_INET6) {
145           dir = noit_find_bpm_route_ipv6(acl, &check->target_addr.addr6, &mask);
146           if(dir == DENY_PTR) goto prevent;
147           else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE;
148         }
149       }
150     }
151   }
152   return NOIT_HOOK_CONTINUE;
153
154  prevent:
155   memset(&current, 0, sizeof(current));
156   current.available = NP_UNAVAILABLE;
157   current.state = NP_BAD;
158   gettimeofday(&current.whence, NULL);
159   snprintf(deny_msg, sizeof(deny_msg), "prevented by ACL '%s'", k ? k : "unknown");
160   current.status = deny_msg;
161   noit_check_set_stats(self, check, &current);
162   return NOIT_HOOK_DONE;
163 }
164 static int
165 ip_acl_init(noit_module_generic_t *self) {
166   check_preflight_hook_register("ip_acl", ip_acl_hook_impl, NULL);
167   return 0;
168 }
169
170 noit_module_generic_t ip_acl = {
171   {
172     NOIT_GENERIC_MAGIC,
173     NOIT_GENERIC_ABI_VERSION,
174     "ip_acl",
175     "IP Access Controls for Checks",
176     ip_acl_xml_description,
177     ip_acl_onload
178   },
179   ip_acl_config,
180   ip_acl_init
181 };
182
Note: See TracBrowser for help on using the browser.