44 |
static void snmpserv_after_config_hook(void *arg, void *unused); |
static void snmpserv_after_config_hook(void *arg, void *unused); |
45 |
static void snmp_tree_init(); |
static void snmp_tree_init(); |
46 |
|
|
47 |
ACL *snmp_acl, *snmp_acl_tail; |
static LIST /* of ACL */ *snmp_acl; |
48 |
Community *commlist, *commlist_tail; |
static LIST /* of Community */ *commlist; |
49 |
Server_stat *server_stat; |
Server_stat *server_stat; |
50 |
struct radstat radstat; |
struct radstat radstat; |
51 |
|
|
52 |
/* ************************************************************************ */ |
/* ************************************************************************ */ |
53 |
/* Configuration file */ |
/* Configuration file */ |
54 |
|
|
55 |
typedef struct netlist Netlist; |
static LIST /* of NETNAME */ *netlist; |
56 |
struct netlist { |
|
57 |
Netlist *next; |
static int |
58 |
char *name; |
_netname_cmp(const void *item, const void *data) |
59 |
ACL *acl; |
{ |
60 |
|
const NETNAME *p = item; |
61 |
|
const char *name = data; |
62 |
|
return strcmp(p->name, name); |
63 |
|
} |
64 |
|
|
65 |
|
static NETNAME * |
66 |
|
netname_find(char *name) |
67 |
|
{ |
68 |
|
return list_locate(netlist, name, _netname_cmp); |
69 |
|
} |
70 |
|
|
71 |
|
static int |
72 |
|
_netdef_destroy(void *item, void *data ARG_UNUSED) |
73 |
|
{ |
74 |
|
efree(item); |
75 |
|
return 0; |
76 |
|
} |
77 |
|
|
78 |
|
static int |
79 |
|
_netname_destroy(void *item, void *data ARG_UNUSED) |
80 |
|
{ |
81 |
|
NETNAME *p = item; |
82 |
|
efree(p->name); |
83 |
|
list_destroy(&p->netlist, _netdef_destroy, NULL); |
84 |
|
efree(p); |
85 |
|
return 0; |
86 |
|
} |
87 |
|
|
88 |
|
static void |
89 |
|
netlist_destroy() |
90 |
|
{ |
91 |
|
list_destroy(&netlist, _netname_destroy, NULL); |
92 |
|
} |
93 |
|
|
94 |
|
/* ************************************************************************ */ |
95 |
|
/* ACL fiddling */ |
96 |
|
|
97 |
|
void |
98 |
|
snmp_add_community(char *str, int access) |
99 |
|
{ |
100 |
|
Community *p = emalloc(sizeof(*p)); |
101 |
|
p->name = estrdup(str); |
102 |
|
p->access = access; |
103 |
|
if (!commlist) |
104 |
|
commlist = list_create(); |
105 |
|
list_append(commlist, p); |
106 |
|
} |
107 |
|
|
108 |
|
|
109 |
|
static int |
110 |
|
_community_cmp(const void *item, const void *data) |
111 |
|
{ |
112 |
|
const Community *p = item; |
113 |
|
return strcmp(p->name, (const char*) data); |
114 |
|
} |
115 |
|
|
116 |
|
|
117 |
|
Community * |
118 |
|
snmp_find_community(char *str) |
119 |
|
{ |
120 |
|
return list_locate(commlist, str, _community_cmp); |
121 |
|
} |
122 |
|
|
123 |
|
static int |
124 |
|
_community_destroy(void *item, void *data) |
125 |
|
{ |
126 |
|
Community *p = item; |
127 |
|
efree(p->name); |
128 |
|
efree(p); |
129 |
|
return 0; |
130 |
|
} |
131 |
|
|
132 |
|
void |
133 |
|
snmp_free_communities() |
134 |
|
{ |
135 |
|
list_destroy(&commlist, _community_destroy, NULL); |
136 |
|
} |
137 |
|
|
138 |
|
struct acl_closure { |
139 |
|
UINT4 ip; |
140 |
|
char *community; |
141 |
|
int access; |
142 |
}; |
}; |
|
static Netlist *netlist; |
|
143 |
|
|
144 |
static ACL * |
int |
145 |
find_netlist(char *name) |
_netdef_cmp(void *item, void *data) |
146 |
{ |
{ |
147 |
Netlist *p; |
NETDEF *nd = item; |
148 |
|
struct acl_closure *clos = data; |
149 |
|
|
150 |
for (p = netlist; p; p = p->next) |
if (nd->ipaddr == (clos->ip & nd->netmask)) |
151 |
if (strcmp(p->name, name) == 0) |
return 0; |
152 |
return p->acl; |
return 1; |
153 |
|
} |
154 |
|
|
155 |
return NULL; |
int |
156 |
|
_acl_iterator(void *item, void *data) |
157 |
|
{ |
158 |
|
ACL *acl = item; |
159 |
|
struct acl_closure *clos = data; |
160 |
|
|
161 |
|
if (acl->community |
162 |
|
&& strcmp(acl->community->name, clos->community)) |
163 |
|
return 0; |
164 |
|
if (list_locate(acl->netlist, data, _netdef_cmp)) { |
165 |
|
clos->access = acl->community->access; |
166 |
|
return 1; |
167 |
|
} |
168 |
|
return 0; |
169 |
} |
} |
170 |
|
|
171 |
|
int |
172 |
|
check_acl(UINT4 ip, char *community) |
173 |
|
{ |
174 |
|
struct acl_closure clos; |
175 |
|
|
176 |
|
clos.ip = ntohl(ip); |
177 |
|
clos.community = community; |
178 |
|
clos.access = 0; |
179 |
|
list_iterate(snmp_acl, _acl_iterator, &clos); |
180 |
|
return clos.access; |
181 |
|
} |
182 |
|
|
183 |
|
void |
184 |
|
snmp_add_acl(Community *community, LIST /* of NETDEF */ *netlist) |
185 |
|
{ |
186 |
|
ACL *acl; |
187 |
|
|
188 |
|
acl = emalloc(sizeof(*acl)); |
189 |
|
acl->community = community; |
190 |
|
acl->netlist = netlist; |
191 |
|
if (!snmp_acl) |
192 |
|
snmp_acl = list_create(); |
193 |
|
list_append(snmp_acl, acl); |
194 |
|
} |
195 |
|
|
196 |
|
static int |
197 |
|
_acl_destroy(void *item, void *data) |
198 |
|
{ |
199 |
|
efree(item); |
200 |
|
return 0; |
201 |
|
} |
202 |
|
|
203 |
|
void |
204 |
|
snmp_free_acl() |
205 |
|
{ |
206 |
|
list_destroy(&snmp_acl, _acl_destroy, NULL); |
207 |
|
} |
208 |
|
|
209 |
|
|
210 |
|
/* ************************************************************************* */ |
211 |
static int _opened_snmp_sockets; |
static int _opened_snmp_sockets; |
212 |
|
|
213 |
int |
int |
214 |
snmp_stmt_begin(int finish, void *data, void *up_data) |
snmp_stmt_begin(int finish, void *data, void *up_data) |
215 |
{ |
{ |
216 |
if (!finish) { |
if (!finish) { |
217 |
|
netlist_destroy(); |
218 |
snmp_free_communities(); |
snmp_free_communities(); |
219 |
snmp_free_acl(); |
snmp_free_acl(); |
220 |
_opened_snmp_sockets = 0; |
_opened_snmp_sockets = 0; |
282 |
return 0; |
return 0; |
283 |
} |
} |
284 |
|
|
|
static void |
|
|
destroy_netlist(void *np) |
|
|
{ |
|
|
Netlist *netlist = np; |
|
|
free_acl(netlist->acl); |
|
|
efree(netlist->name); |
|
|
} |
|
|
|
|
285 |
int |
int |
286 |
snmp_cfg_listen(int argc, cfg_value_t *argv, |
snmp_cfg_listen(int argc, cfg_value_t *argv, |
287 |
void *block_data, void *handler_data) |
void *block_data, void *handler_data) |
310 |
void *block_data, void *handler_data) |
void *block_data, void *handler_data) |
311 |
{ |
{ |
312 |
int i; |
int i; |
313 |
Netlist *p; |
NETNAME *np; |
|
ACL *head = NULL, *tail = NULL; |
|
314 |
|
|
315 |
if (argc < 3) { |
if (argc < 3) { |
316 |
cfg_argc_error(1); |
cfg_argc_error(1); |
322 |
return 0; |
return 0; |
323 |
} |
} |
324 |
|
|
325 |
p = cfg_malloc(sizeof(*p), destroy_netlist); |
np = emalloc(sizeof(*np)); |
326 |
p->next = netlist; |
if (!netlist) |
327 |
p->name = estrdup(argv[1].v.string); |
netlist = list_create(netlist); |
328 |
|
|
329 |
|
list_append(netlist, np); |
330 |
|
np->name = estrdup(argv[1].v.string); |
331 |
|
np->netlist = list_create(); |
332 |
for (i = 2; i < argc; i++) { |
for (i = 2; i < argc; i++) { |
333 |
if (argv[i].type != CFG_NETWORK) { |
if (argv[i].type != CFG_NETWORK) { |
334 |
radlog(L_ERR, |
radlog(L_ERR, |
336 |
cfg_filename, cfg_line_num, |
cfg_filename, cfg_line_num, |
337 |
i); |
i); |
338 |
} else { |
} else { |
339 |
ACL *acl = mem_alloc(sizeof(*acl)); |
NETDEF *net = emalloc(sizeof(*net)); |
340 |
acl->ipaddr = argv[i].v.network.ipaddr; |
net->ipaddr = argv[i].v.network.ipaddr; |
341 |
acl->netmask = argv[i].v.network.netmask; |
net->netmask = argv[i].v.network.netmask; |
342 |
if (tail) |
list_append(np->netlist, net); |
|
tail->next = acl; |
|
|
else |
|
|
head = acl; |
|
|
tail = acl; |
|
343 |
} |
} |
344 |
} |
} |
|
p->acl = head; |
|
|
netlist = p; |
|
345 |
return 0; |
return 0; |
346 |
} |
} |
347 |
|
|
350 |
void *block_data, void *handler_data) |
void *block_data, void *handler_data) |
351 |
{ |
{ |
352 |
Community *comm; |
Community *comm; |
353 |
ACL *acl; |
NETNAME *nn; |
354 |
|
|
355 |
if (argc != 3) { |
if (argc != 3) { |
356 |
cfg_argc_error(argc < 3); |
cfg_argc_error(argc < 3); |
362 |
return 0; |
return 0; |
363 |
} |
} |
364 |
|
|
365 |
if ((acl = find_netlist(argv[1].v.string)) == NULL) { |
if ((nn = netname_find(argv[1].v.string)) == NULL) { |
366 |
radlog(L_ERR, _("%s:%d: no such acl: %s"), |
radlog(L_ERR, _("%s:%d: no such network: %s"), |
367 |
cfg_filename, cfg_line_num, argv[1].v.string); |
cfg_filename, cfg_line_num, argv[1].v.string); |
368 |
return 0; |
return 0; |
369 |
} |
} |
376 |
return 0; |
return 0; |
377 |
} |
} |
378 |
|
|
379 |
snmp_add_acl(acl, comm); |
snmp_add_acl(comm, nn->netlist); |
380 |
return 0; |
return 0; |
381 |
} |
} |
382 |
|
|
384 |
snmp_cfg_deny(int argc, cfg_value_t *argv, |
snmp_cfg_deny(int argc, cfg_value_t *argv, |
385 |
void *block_data, void *handler_data) |
void *block_data, void *handler_data) |
386 |
{ |
{ |
387 |
ACL *acl; |
NETNAME *nn; |
388 |
|
|
389 |
if (argc != 2) { |
if (argc != 2) { |
390 |
cfg_argc_error(argc < 2); |
cfg_argc_error(argc < 2); |
396 |
return 0; |
return 0; |
397 |
} |
} |
398 |
|
|
399 |
if ((acl = find_netlist(argv[1].v.string)) == NULL) { |
if ((nn = netname_find(argv[1].v.string)) == NULL) { |
400 |
radlog(L_ERR, _("%s:%d: no such acl: %s"), |
radlog(L_ERR, _("%s:%d: no such network: %s"), |
401 |
cfg_filename, cfg_line_num, argv[1].v.string); |
cfg_filename, cfg_line_num, argv[1].v.string); |
402 |
return 0; |
return 0; |
403 |
} |
} |
404 |
|
|
405 |
snmp_add_acl(acl, NULL); |
snmp_add_acl(NULL, nn->netlist); |
406 |
return 0; |
return 0; |
407 |
} |
} |
408 |
|
|
475 |
} |
} |
476 |
|
|
477 |
/* ************************************************************************ */ |
/* ************************************************************************ */ |
|
/* ACL fiddling */ |
|
|
|
|
|
void |
|
|
snmp_add_community(char *str, int access) |
|
|
{ |
|
|
Community *p = mem_alloc(sizeof(*p)); |
|
|
p->name = estrdup(str); |
|
|
p->access = access; |
|
|
if (commlist_tail) |
|
|
commlist_tail->next = p; |
|
|
else |
|
|
commlist = p; |
|
|
commlist_tail = p; |
|
|
} |
|
|
|
|
|
Community * |
|
|
snmp_find_community(char *str) |
|
|
{ |
|
|
Community *p; |
|
|
|
|
|
for (p = commlist; p; p = p->next) |
|
|
if (strcmp(p->name, str) == 0) |
|
|
return p; |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
void |
|
|
snmp_free_communities() |
|
|
{ |
|
|
Community *p = commlist, *next; |
|
|
while (p) { |
|
|
next = p->next; |
|
|
efree(p->name); |
|
|
mem_free(p); |
|
|
p = next; |
|
|
} |
|
|
commlist = commlist_tail = NULL; |
|
|
} |
|
|
|
|
|
int |
|
|
check_acl(UINT4 ip, char *community) |
|
|
{ |
|
|
ACL *acl; |
|
|
|
|
|
for (acl = snmp_acl; acl; acl = acl->next) { |
|
|
if (acl->ipaddr == (ip & acl->netmask)) { |
|
|
if (!acl->community) |
|
|
return 0; |
|
|
else if (strcmp(acl->community->name, community) == 0) |
|
|
return acl->community->access; |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
|
void |
|
|
snmp_add_acl(ACL *acl, Community *community) |
|
|
{ |
|
|
ACL *new_acl; |
|
|
|
|
|
for (; acl; acl = acl->next) { |
|
|
new_acl = mem_alloc(sizeof(*new_acl)); |
|
|
memcpy(new_acl, acl, sizeof(ACL)); |
|
|
new_acl->community = community; |
|
|
new_acl->ipaddr = ntohl(new_acl->ipaddr); |
|
|
new_acl->netmask = ntohl(new_acl->netmask); |
|
|
if (snmp_acl_tail) |
|
|
snmp_acl_tail->next = new_acl; |
|
|
else |
|
|
snmp_acl = new_acl; |
|
|
snmp_acl_tail = new_acl; |
|
|
} |
|
|
} |
|
|
|
|
|
void |
|
|
snmp_free_acl() |
|
|
{ |
|
|
free_acl(snmp_acl); |
|
|
snmp_acl = snmp_acl_tail = NULL; |
|
|
} |
|
|
|
|
|
void |
|
|
free_acl(ACL *acl) |
|
|
{ |
|
|
ACL *next; |
|
|
|
|
|
while (acl) { |
|
|
next = acl->next; |
|
|
mem_free(acl); |
|
|
acl = next; |
|
|
} |
|
|
} |
|
|
|
|
|
/* ************************************************************************ */ |
|
478 |
/* Application-specific */ |
/* Application-specific */ |
479 |
|
|
480 |
struct mib_node_t *mib_tree; |
struct mib_node_t *mib_tree; |