1 /* This file is part of GNU Radius.
2    Copyright (C) 2000,2001,2002,2003,2004,2006,
3    2007,2008 Free Software Foundation, Inc.
4 
5    Written by Sergey Poznyakoff
6 
7    GNU Radius is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    GNU Radius is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GNU Radius; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 
21 #if defined(HAVE_CONFIG_H)
22 # include <config.h>
23 #endif
24 
25 #ifdef USE_SNMP
26 
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 
30 #include <snmp/asn1.h>
31 #include <snmp/snmp.h>
32 #include <snmp/mib.h>
33 
34 #include <sysdep.h>
35 #include <radiusd.h>
36 #include <radius/radutmp.h>
37 #include <radsnmp.h>
38 #define SERVER
39 #include <radmibs.h>
40 
41 #define MAXOIDLEN 512
42 
43 struct snmp_pdu * snmp_agent_response(struct snmp_pdu *pdu, int access);
44 int variable_cmp(struct snmp_var *v1, struct snmp_var *v2);
45 static grad_nas_t *nas_lookup_index(int ind);
46 static void snmpserv_before_config_hook(void *unused1, void *unused2);
47 static void snmpserv_after_config_hook(void *arg, void *unused);
48 static void snmp_tree_init();
49 
50 static grad_list_t /* of ACL */ *snmp_acl;
51 static grad_list_t /* of Community */ *commlist;
52 Server_stat *server_stat;
53 struct radstat radstat;
54 
55 /* ************************************************************************ */
56 /* Configuration file */
57 
58 static grad_list_t /* of NETNAME */ *netlist;
59 
60 static int
_netname_cmp(const void * item,const void * data)61 _netname_cmp(const void *item, const void *data)
62 {
63 	const NETNAME *p = item;
64 	const char *name = data;
65 	return strcmp(p->name, name);
66 }
67 
68 static NETNAME *
netname_find(char * name)69 netname_find(char *name)
70 {
71         return grad_list_locate(netlist, name, _netname_cmp);
72 }
73 
74 static int
_netdef_destroy(void * item,void * data ARG_UNUSED)75 _netdef_destroy(void *item, void *data ARG_UNUSED)
76 {
77 	grad_free(item);
78 	return 0;
79 }
80 
81 static int
_netname_destroy(void * item,void * data ARG_UNUSED)82 _netname_destroy(void *item, void *data ARG_UNUSED)
83 {
84 	NETNAME *p = item;
85 	grad_free(p->name);
86 	grad_list_destroy(&p->netlist, _netdef_destroy, NULL);
87 	grad_free(p);
88 	return 0;
89 }
90 
91 static void
netgrad_list_destroy()92 netgrad_list_destroy()
93 {
94 	grad_list_destroy(&netlist, _netname_destroy, NULL);
95 }
96 
97 /* ************************************************************************ */
98 /* ACL fiddling */
99 
100 void
snmp_add_community(char * str,int access)101 snmp_add_community(char *str, int access)
102 {
103         Community *p = grad_emalloc(sizeof(*p));
104         p->name = grad_estrdup(str);
105         p->access = access;
106 	if (!commlist)
107 		commlist = grad_list_create();
108         grad_list_append(commlist, p);
109 }
110 
111 
112 static int
_community_cmp(const void * item,const void * data)113 _community_cmp(const void *item, const void *data)
114 {
115         const Community *p = item;
116 	return strcmp(p->name, (const char*) data);
117 }
118 
119 
120 Community *
snmp_find_community(char * str)121 snmp_find_community(char *str)
122 {
123 	return grad_list_locate(commlist, str, _community_cmp);
124 }
125 
126 static int
_community_destroy(void * item,void * data)127 _community_destroy(void *item, void *data)
128 {
129 	Community *p = item;
130 	grad_free(p->name);
131 	grad_free(p);
132 	return 0;
133 }
134 
135 void
snmp_free_communities()136 snmp_free_communities()
137 {
138 	grad_list_destroy(&commlist, _community_destroy, NULL);
139 }
140 
141 struct acl_closure {
142 	grad_uint32_t ip;
143 	char *community;
144 	int access;
145 };
146 
147 int
_netdef_cmp(const void * item,const void * data)148 _netdef_cmp(const void *item, const void *data)
149 {
150 	const grad_netdef_t *nd = item;
151 	const struct acl_closure *clos = data;
152 
153 	if (grad_ip_in_net_p(nd, clos->ip))
154 		return 0;
155 	return 1;
156 }
157 
158 int
_acl_iterator(void * item,void * data)159 _acl_iterator(void *item, void *data)
160 {
161 	ACL *acl = item;
162 	struct acl_closure *clos = data;
163 
164 	if (acl->community
165 	    && strcmp(acl->community->name, clos->community))
166 		return 0;
167 	if (grad_list_locate(acl->netlist, data, _netdef_cmp)) {
168 		clos->access = acl->community ? acl->community->access : 0;
169 		return 1;
170 	}
171 	return 0;
172 }
173 
174 int
check_acl(grad_uint32_t ip,char * community)175 check_acl(grad_uint32_t ip, char *community)
176 {
177 	struct acl_closure clos;
178 
179 	clos.ip = ntohl(ip);
180 	clos.community = community;
181 	clos.access = 0;
182 	grad_list_iterate(snmp_acl, _acl_iterator, &clos);
183         return clos.access;
184 }
185 
186 void
snmp_add_acl(Community * community,grad_list_t * netlist)187 snmp_add_acl(Community *community, grad_list_t /* of grad_netdef_t */ *netlist)
188 {
189         ACL *acl;
190 
191 	acl = grad_emalloc(sizeof(*acl));
192 	acl->community = community;
193 	acl->netlist = netlist;
194 	if (!snmp_acl)
195 		snmp_acl = grad_list_create();
196 	grad_list_append(snmp_acl, acl);
197 }
198 
199 static int
_acl_destroy(void * item,void * data)200 _acl_destroy(void *item, void *data)
201 {
202 	grad_free(item);
203 	return 0;
204 }
205 
206 void
snmp_free_acl()207 snmp_free_acl()
208 {
209 	grad_list_destroy(&snmp_acl, _acl_destroy, NULL);
210 }
211 
212 
213 /* ************************************************************************* */
214 static int _opened_snmp_sockets;
215 
216 int
snmp_stmt_begin(int finish,void * data,void * up_data)217 snmp_stmt_begin(int finish, void *data, void *up_data)
218 {
219 	if (!finish) {
220 		netgrad_list_destroy();
221 		snmp_free_communities();
222 		snmp_free_acl();
223 		_opened_snmp_sockets = 0;
224 	} else if (radius_mode == MODE_DAEMON
225 		   && !_opened_snmp_sockets
226 		   && snmp_port)
227 		udp_open(R_SNMP, INADDR_ANY, snmp_port, 1);
228 	return 0;
229 }
230 
231 static int
snmp_cfg_ident(int argc,cfg_value_t * argv,void * block_data,void * handler_data)232 snmp_cfg_ident(int argc, cfg_value_t *argv, void *block_data,
233 	       void *handler_data)
234 {
235 	if (argc > 2) {
236 		cfg_argc_error(0);
237 		return 0;
238 	}
239 
240  	if (argv[1].type != CFG_STRING) {
241 		cfg_type_error(CFG_STRING);
242 		return 0;
243 	}
244 	if (server_id)
245 		grad_free(server_id);
246 	server_id = grad_estrdup(argv[1].v.string);
247 	return 0;
248 }
249 
250 static grad_keyword_t snmp_access[] = {
251 	{ "read-only", SNMP_RO },
252 	{ "read-write", SNMP_RW },
253 	{ "ro", SNMP_RO },
254 	{ "rw", SNMP_RW },
255 	{ 0 }
256 };
257 
258 static int
snmp_cfg_community(int argc,cfg_value_t * argv,void * block_data,void * handler_data)259 snmp_cfg_community(int argc, cfg_value_t *argv,
260 		   void *block_data, void *handler_data)
261 {
262 	int access;
263 
264 	if (argc != 3) {
265 		cfg_argc_error(argc < 3);
266 		return 0;
267 	}
268 
269  	if (argv[1].type != CFG_STRING
270 	    || argv[2].type != CFG_STRING) {
271 		cfg_type_error(CFG_STRING);
272 		return 0;
273 	}
274 
275 	access = grad_xlat_keyword(snmp_access, argv[2].v.string, -1);
276 	if (access == -1)
277 		return 1;
278 
279 	if (snmp_find_community(argv[1].v.string)) {
280 		grad_log(GRAD_LOG_ERR,
281 		         _("%s:%d: community %s already declared"),
282 		         cfg_filename, cfg_line_num, argv[1].v.string);
283 		return 0;
284 	}
285 
286 	snmp_add_community(argv[1].v.string, access);
287 	return 0;
288 }
289 
290 int
snmp_cfg_listen(int argc,cfg_value_t * argv,void * block_data,void * handler_data)291 snmp_cfg_listen(int argc, cfg_value_t *argv,
292 		void *block_data, void *handler_data)
293 {
294 	int i, errcnt = 0;
295 
296 	if (argc == 2 && argv[1].type == CFG_BOOLEAN) {
297 		if (argv[1].v.bool == 0)
298 			snmp_port = 0;
299 		return 0;
300 	}
301 
302 	for (i = 1; i < argc; i++)
303 		if (argv[i].type != CFG_HOST) {
304 			cfg_type_error(CFG_HOST);
305 			errcnt++;
306 		}
307 
308 	if (errcnt == 0 && radius_mode == MODE_DAEMON)
309 		for (i = 1; i < argc; i++)
310 			udp_open(R_SNMP,
311 				 argv[i].v.host.ipaddr,
312 				 argv[i].v.host.port > 0 ?
313 				 argv[i].v.host.port : snmp_port,
314 				 1);
315 	_opened_snmp_sockets++;
316 	return 0;
317 }
318 
319 static int
snmp_cfg_network(int argc,cfg_value_t * argv,void * block_data,void * handler_data)320 snmp_cfg_network(int argc, cfg_value_t *argv,
321 		 void *block_data, void *handler_data)
322 {
323 	int i;
324 	NETNAME *np;
325 
326 	if (argc < 3) {
327 		cfg_argc_error(1);
328 		return 0;
329 	}
330 
331  	if (argv[1].type != CFG_STRING) {
332 		cfg_type_error(CFG_STRING);
333 		return 0;
334 	}
335 
336         np = grad_emalloc(sizeof(*np));
337 	if (!netlist)
338 		netlist = grad_list_create(netlist);
339 
340 	grad_list_append(netlist, np);
341         np->name = grad_estrdup(argv[1].v.string);
342 	np->netlist = grad_list_create();
343 	for (i = 2; i < argc; i++) {
344 		if (argv[i].type != CFG_NETWORK) {
345 			grad_log(GRAD_LOG_ERR,
346 			         _("%s:%d: list item %d has wrong datatype"),
347 			         cfg_filename, cfg_line_num,
348 			         i);
349 		} else {
350 			grad_netdef_t *net = grad_emalloc(sizeof(*net));
351 			net->ipaddr = argv[i].v.network.ipaddr;
352 			net->netmask = argv[i].v.network.netmask;
353 			grad_list_append(np->netlist, net);
354 		}
355 	}
356 	return 0;
357 }
358 
359 static int
snmp_cfg_allow(int argc,cfg_value_t * argv,void * block_data,void * handler_data)360 snmp_cfg_allow(int argc, cfg_value_t *argv,
361 	       void *block_data, void *handler_data)
362 {
363 	Community *comm;
364 	NETNAME *nn;
365 
366 	if (argc != 3) {
367 		cfg_argc_error(argc < 3);
368 		return 0;
369 	}
370 
371  	if (argv[1].type != CFG_STRING || argv[2].type != CFG_STRING) {
372 		cfg_type_error(CFG_STRING);
373 		return 0;
374 	}
375 
376 	if ((nn = netname_find(argv[1].v.string)) == NULL) {
377 		grad_log(GRAD_LOG_ERR, _("%s:%d: no such network: %s"),
378 		         cfg_filename, cfg_line_num, argv[1].v.string);
379 		return 0;
380 	}
381 
382 	comm = snmp_find_community(argv[2].v.string);
383 	if (!comm) {
384 		grad_log(GRAD_LOG_ERR,
385 		         _("%s:%d: undefined community %s"),
386 		         cfg_filename, cfg_line_num, argv[2].v.string);
387 		return 0;
388 	}
389 
390 	snmp_add_acl(comm, nn->netlist);
391 	return 0;
392 }
393 
394 static int
snmp_cfg_deny(int argc,cfg_value_t * argv,void * block_data,void * handler_data)395 snmp_cfg_deny(int argc, cfg_value_t *argv,
396 	      void *block_data, void *handler_data)
397 {
398 	NETNAME *nn;
399 
400 	if (argc != 2) {
401 		cfg_argc_error(argc < 2);
402 		return 0;
403 	}
404 
405  	if (argv[1].type != CFG_STRING) {
406 		cfg_type_error(CFG_STRING);
407 		return 0;
408 	}
409 
410 	if ((nn = netname_find(argv[1].v.string)) == NULL) {
411 		grad_log(GRAD_LOG_ERR, _("%s:%d: no such network: %s"),
412 		         cfg_filename, cfg_line_num, argv[1].v.string);
413 		return 0;
414 	}
415 
416 	snmp_add_acl(NULL, nn->netlist);
417 	return 0;
418 }
419 
420 static struct cfg_stmt acl_stmt[] = {
421 	{ "allow", CS_STMT, NULL, snmp_cfg_allow, NULL, NULL, NULL },
422 	{ "deny", CS_STMT, NULL, snmp_cfg_deny, NULL, NULL, NULL },
423 	{ NULL },
424 };
425 
426 struct cfg_stmt snmp_stmt[] = {
427 	{ "port", CS_STMT, NULL, cfg_get_port, &snmp_port, NULL, NULL },
428 	{ "listen", CS_STMT, NULL, snmp_cfg_listen, NULL, NULL, NULL },
429 	{ "max-requests", CS_STMT, NULL,
430 	  cfg_get_integer, &request_class[R_SNMP].max_requests,
431 	  NULL, NULL },
432 	{ "time-to-live", CS_STMT, NULL,
433 	  cfg_get_integer, &request_class[R_SNMP].ttl,
434 	  NULL, NULL },
435 	{ "request-cleanup-delay", CS_STMT, NULL,
436 	  cfg_get_integer, &request_class[R_SNMP].cleanup_delay,
437 	  NULL, NULL },
438 	{ "ident", CS_STMT, NULL, snmp_cfg_ident, NULL,
439 	  NULL, NULL },
440 	{ "community", CS_STMT, NULL, snmp_cfg_community, NULL,
441 	  NULL, NULL },
442 	{ "storage", CS_BLOCK, NULL, NULL, NULL,
443 	  storage_stmt, NULL },
444 	{ "network", CS_STMT, NULL, snmp_cfg_network, NULL,
445 	  NULL, NULL },
446 	{ "acl", CS_BLOCK, NULL, NULL, NULL, acl_stmt, NULL },
447 	/* Obsolete statements */
448 	{ "spawn", CS_STMT, NULL, cfg_obsolete, NULL, NULL, NULL },
449 	{ NULL, }
450 };
451 
452 static void
snmpserv_before_config_hook(void * a ARG_UNUSED,void * b ARG_UNUSED)453 snmpserv_before_config_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
454 {
455 	if (server_stat) {
456 		server_stat->auth.status = serv_init;
457 		server_stat->acct.status = serv_init;
458 	}
459 }
460 
461 static void
snmpserv_after_config_hook(void * arg,void * data ARG_UNUSED)462 snmpserv_after_config_hook(void *arg, void *data ARG_UNUSED)
463 {
464 	stat_done();
465 	stat_init();
466 	if (server_stat) {
467 		grad_nas_t *nas;
468 		grad_iterator_t *itr;
469 
470 		server_stat->auth.status =
471 			suspend_flag ? serv_suspended : serv_running;
472 		snmp_auth_server_reset();
473 
474 		server_stat->acct.status = server_stat->auth.status;
475 		snmp_acct_server_reset();
476 
477 		*(serv_stat*)arg = server_stat->auth.status;
478 		snmp_init_nas_stat();
479 		itr = grad_nas_iterator();
480 		for (nas = grad_iterator_first(itr); nas; nas = grad_iterator_next(itr))
481 			snmp_attach_nas_stat(nas);
482 		grad_iterator_destroy(&itr);
483 		snmp_sort_nas_stat();
484 	}
485 }
486 
487 void
snmpserv_init(void * arg)488 snmpserv_init(void *arg)
489 {
490 	stat_init();
491 	radiusd_set_preconfig_hook(snmpserv_before_config_hook, NULL, 0);
492 	radiusd_set_postconfig_hook(snmpserv_after_config_hook, arg, 0);
493 	snmp_tree_init();
494 	snmpserv_after_config_hook(arg, NULL);
495 }
496 
497 /* ************************************************************************ */
498 /* Application-specific */
499 
500 struct mib_node_t *mib_tree;
501 int snmp_auth_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
502                       struct snmp_var **varp, int *errp);
503 int snmp_auth_v_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
504                         struct snmp_var **varp, int *errp);
505 int snmp_acct_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
506                       struct snmp_var **varp, int *errp);
507 int snmp_acct_v_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
508                         struct snmp_var **varp, int *errp);
509 int snmp_serv_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
510                       struct snmp_var **varp, int *errp);
511 int snmp_stat_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
512                       struct snmp_var **varp, int *errp);
513 
514 int snmp_stat_nas1(enum mib_node_cmd cmd, void *closure, subid_t subid,
515                    struct snmp_var **varp, int *errp);
516 int snmp_stat_nas2(enum mib_node_cmd cmd, void *closure, subid_t subid,
517                    struct snmp_var **varp, int *errp);
518 int snmp_stat_nas3(enum mib_node_cmd cmd, void *closure, subid_t subid,
519                    struct snmp_var **varp, int *errp);
520 int snmp_stat_nas4(enum mib_node_cmd cmd, void *closure, subid_t subid,
521                    struct snmp_var **varp, int *errp);
522 int snmp_nas_table(enum mib_node_cmd cmd, void *closure, subid_t subid,
523                    struct snmp_var **varp, int *errp);
524 int snmp_port_index1(enum mib_node_cmd cmd, void *closure, subid_t subid,
525                      struct snmp_var **varp, int *errp);
526 int snmp_port_index2(enum mib_node_cmd cmd, void *closure, subid_t subid,
527                      struct snmp_var **varp, int *errp);
528 int snmp_port_table(enum mib_node_cmd cmd, void *closure, subid_t subid,
529                     struct snmp_var **varp, int *errp);
530 
531 struct auth_mib_data {
532         int nas_index;
533 };
534 
535 struct nas_data {
536         subid_t quad[4];
537 };
538 
539 struct nas_table_data {
540         int row;
541 };
542 
543 struct port_data {
544         int nas_index;
545         int port_no;
546 };
547 
548 struct port_table_data {
549         int port_index;
550 };
551 
552 union snmpserv_data {
553         struct auth_mib_data auth_mib;
554         struct nas_data nas;
555         struct nas_table_data nas_data;
556         struct port_data port;
557         struct port_table_data port_table;
558 };
559 
560 static union snmpserv_data *__snmpserv_data;
561 
562 static void *
snmpserv_get_data()563 snmpserv_get_data()
564 {
565         if (!__snmpserv_data) {
566                 __snmpserv_data = grad_emalloc(sizeof(*__snmpserv_data));
567                 __snmpserv_data->auth_mib.nas_index = 1;
568         }
569         return __snmpserv_data;
570 }
571 
572 static struct mib_data {
573         oid_t oid;
574         mib_fp handler;
575         void *closure;
576 } mib_data[] = {
577         /* Authentication */
578         /* Fixed oids */
579         { oid_AuthServIdent,                   snmp_auth_handler, NULL },
580         { oid_AuthServUpTime,                  snmp_auth_handler, NULL },
581         { oid_AuthServResetTime,               snmp_auth_handler, NULL },
582         { oid_AuthServConfigReset,             snmp_auth_handler, NULL },
583         { oid_AuthServTotalAccessRequests,     snmp_auth_handler, NULL },
584         { oid_AuthServTotalInvalidRequests,    snmp_auth_handler, NULL },
585         { oid_AuthServTotalDupAccessRequests,  snmp_auth_handler, NULL },
586         { oid_AuthServTotalAccessAccepts,      snmp_auth_handler, NULL },
587         { oid_AuthServTotalAccessRejects,      snmp_auth_handler, NULL },
588         { oid_AuthServTotalAccessChallenges,   snmp_auth_handler, NULL },
589         { oid_AuthServTotalMalformedAccessRequests,
590                                              snmp_auth_handler, NULL },
591         { oid_AuthServTotalBadAuthenticators,  snmp_auth_handler, NULL },
592         { oid_AuthServTotalPacketsDropped,     snmp_auth_handler, NULL },
593         { oid_AuthServTotalUnknownTypes,       snmp_auth_handler, NULL },
594 
595         /* Variable oids */
596         { oid_AuthClientIndex,                 snmp_auth_v_handler,NULL },
597         { oid_AuthClientAddress,               snmp_auth_v_handler,NULL },
598         { oid_AuthClientID,                    snmp_auth_v_handler,NULL },
599         { oid_AuthServAccessRequests,          snmp_auth_v_handler,NULL },
600         { oid_AuthServDupAccessRequests,       snmp_auth_v_handler,NULL },
601         { oid_AuthServAccessAccepts,           snmp_auth_v_handler,NULL },
602         { oid_AuthServAccessRejects,           snmp_auth_v_handler,NULL },
603         { oid_AuthServAccessChallenges,        snmp_auth_v_handler,NULL },
604         { oid_AuthServMalformedAccessRequests, snmp_auth_v_handler,NULL },
605         { oid_AuthServBadAuthenticators,       snmp_auth_v_handler,NULL },
606         { oid_AuthServPacketsDropped,          snmp_auth_v_handler,NULL },
607         { oid_AuthServUnknownTypes,            snmp_auth_v_handler,NULL },
608 
609         /* Accounting */
610         /* Fixed oids */
611         { oid_AccServIdent,                    snmp_acct_handler, NULL },
612         { oid_AccServUpTime,                   snmp_acct_handler, NULL },
613         { oid_AccServResetTime,                snmp_acct_handler, NULL },
614         { oid_AccServConfigReset,              snmp_acct_handler, NULL },
615         { oid_AccServTotalRequests,            snmp_acct_handler, NULL },
616         { oid_AccServTotalInvalidRequests,     snmp_acct_handler, NULL },
617         { oid_AccServTotalDupRequests,         snmp_acct_handler, NULL },
618         { oid_AccServTotalResponses,           snmp_acct_handler, NULL },
619         { oid_AccServTotalMalformedRequests,   snmp_acct_handler, NULL },
620         { oid_AccServTotalBadAuthenticators,   snmp_acct_handler, NULL },
621         { oid_AccServTotalPacketsDropped,      snmp_acct_handler, NULL },
622         { oid_AccServTotalNoRecords,           snmp_acct_handler, NULL },
623         { oid_AccServTotalUnknownTypes,        snmp_acct_handler, NULL },
624 
625         /* Variable oids */
626         { oid_AccClientIndex,                  snmp_acct_v_handler,NULL },
627         { oid_AccClientAddress,                snmp_acct_v_handler,NULL },
628         { oid_AccClientID,                     snmp_acct_v_handler,NULL },
629         { oid_AccServPacketsDropped,           snmp_acct_v_handler,NULL },
630         { oid_AccServRequests,                 snmp_acct_v_handler,NULL },
631         { oid_AccServDupRequests,              snmp_acct_v_handler,NULL },
632         { oid_AccServResponses,                snmp_acct_v_handler,NULL },
633         { oid_AccServBadAuthenticators,        snmp_acct_v_handler,NULL },
634         { oid_AccServMalformedRequests,        snmp_acct_v_handler,NULL },
635         { oid_AccServNoRecords,                snmp_acct_v_handler,NULL },
636         { oid_AccServUnknownTypes,             snmp_acct_v_handler,NULL },
637 
638 #ifdef SNMP_COMPAT_0_96
639 
640         /* Server */
641         { oid_grad_radiusServerUpTime,         snmp_serv_handler, NULL },
642         { oid_grad_radiusServerResetTime,      snmp_serv_handler, NULL },
643         { oid_grad_radiusServerState,          snmp_serv_handler, NULL },
644 
645 
646         /* Statistics */
647         { oid_grad_StatIdent,             snmp_stat_handler, NULL },
648         { oid_grad_StatUpTime,            snmp_stat_handler, NULL },
649         { oid_grad_StatConfigReset,       snmp_stat_handler, NULL },
650         { oid_grad_StatTotalLines,        snmp_stat_handler, NULL },
651         { oid_grad_StatTotalLinesInUse,   snmp_stat_handler, NULL },
652         { oid_grad_StatTotalLinesIdle,    snmp_stat_handler, NULL },
653 
654         /* Variable oids */
655         { oid_grad_NASIndex1,             snmp_stat_nas1, NULL },
656         { oid_grad_NASIndex2,             snmp_stat_nas2, NULL },
657         { oid_grad_NASIndex3,             snmp_stat_nas3, NULL },
658         { oid_grad_NASIndex4,             snmp_stat_nas4, NULL },
659 
660         { oid_grad_NASAddress,            snmp_nas_table, NULL },
661         { oid_grad_NASID,                 snmp_nas_table, NULL },
662         { oid_grad_NASLines,              snmp_nas_table, NULL },
663         { oid_grad_NASLinesInUse,         snmp_nas_table, NULL },
664         { oid_grad_NASLinesIdle,          snmp_nas_table, NULL },
665 
666         { oid_grad_StatPortIndex1,        snmp_port_index1, NULL },
667         { oid_grad_StatPortIndex2,        snmp_port_index2, NULL },
668 
669         /* port table */
670         { oid_grad_StatPortNASIndex,      snmp_port_table, NULL },
671         { oid_grad_StatPortID,            snmp_port_table, NULL },
672         { oid_grad_StatPortFramedAddress, snmp_port_table, NULL },
673         { oid_grad_StatPortTotalLogins,   snmp_port_table, NULL },
674         { oid_grad_StatPortStatus,        snmp_port_table, NULL },
675         { oid_grad_StatPortStatusChangeTimestamp,   snmp_port_table, NULL },
676         { oid_grad_StatPortUpTime,        snmp_port_table, NULL },
677         { oid_grad_StatPortLastLoginName, snmp_port_table, NULL },
678         { oid_grad_StatPortLastLoginTimestamp,  snmp_port_table, NULL },
679         { oid_grad_StatPortLastLogoutTimestamp, snmp_port_table, NULL },
680         { oid_grad_StatPortIdleTotalTime, snmp_port_table, NULL },
681         { oid_grad_StatPortIdleMaxTime,   snmp_port_table, NULL },
682         { oid_grad_StatPortIdleMaxTimestamp, snmp_port_table, NULL },
683         { oid_grad_StatPortInUseTotalTime, snmp_port_table, NULL },
684         { oid_grad_StatPortInUseMaxTime,   snmp_port_table, NULL },
685         { oid_grad_StatPortInUseMaxTimestamp, snmp_port_table, NULL },
686 #endif
687         /* enterprise.gnu.radius subtree */
688         /* Server */
689         { oid_radiusServerUpTime,         snmp_serv_handler, NULL },
690         { oid_radiusServerResetTime,      snmp_serv_handler, NULL },
691         { oid_radiusServerState,          snmp_serv_handler, NULL },
692 
693 
694         /* Statistics */
695         { oid_StatIdent,                       snmp_stat_handler, NULL },
696         { oid_StatUpTime,                      snmp_stat_handler, NULL },
697         { oid_StatConfigReset,                 snmp_stat_handler, NULL },
698         { oid_StatTotalLines,                  snmp_stat_handler, NULL },
699         { oid_StatTotalLinesInUse,             snmp_stat_handler, NULL },
700         { oid_StatTotalLinesIdle,              snmp_stat_handler, NULL },
701 
702         /* Variable oids */
703         { oid_NASIndex1,                       snmp_stat_nas1, NULL },
704         { oid_NASIndex2,                       snmp_stat_nas2, NULL },
705         { oid_NASIndex3,                       snmp_stat_nas3, NULL },
706         { oid_NASIndex4,                       snmp_stat_nas4, NULL },
707 
708         { oid_NASAddress,                      snmp_nas_table, NULL },
709         { oid_NASID,                           snmp_nas_table, NULL },
710         { oid_NASLines,                        snmp_nas_table, NULL },
711         { oid_NASLinesInUse,                   snmp_nas_table, NULL },
712         { oid_NASLinesIdle,                    snmp_nas_table, NULL },
713 
714         { oid_StatPortIndex1,                  snmp_port_index1, NULL },
715         { oid_StatPortIndex2,                  snmp_port_index2, NULL },
716 
717         /* port table */
718         { oid_StatPortNASIndex,                snmp_port_table, NULL },
719         { oid_StatPortID,                      snmp_port_table, NULL },
720         { oid_StatPortFramedAddress,           snmp_port_table, NULL },
721         { oid_StatPortTotalLogins,             snmp_port_table, NULL },
722         { oid_StatPortStatus,                  snmp_port_table, NULL },
723         { oid_StatPortStatusChangeTimestamp,   snmp_port_table, NULL },
724         { oid_StatPortUpTime,                  snmp_port_table, NULL },
725         { oid_StatPortLastLoginName,           snmp_port_table, NULL },
726         { oid_StatPortLastLoginTimestamp,      snmp_port_table, NULL },
727         { oid_StatPortLastLogoutTimestamp,     snmp_port_table, NULL },
728         { oid_StatPortIdleTotalTime,           snmp_port_table, NULL },
729         { oid_StatPortIdleMaxTime,             snmp_port_table, NULL },
730         { oid_StatPortIdleMaxTimestamp,        snmp_port_table, NULL },
731         { oid_StatPortInUseTotalTime,          snmp_port_table, NULL },
732         { oid_StatPortInUseMaxTime,            snmp_port_table, NULL },
733         { oid_StatPortInUseMaxTimestamp,       snmp_port_table, NULL },
734 
735 };
736 
737 void
snmp_tree_init()738 snmp_tree_init()
739 {
740         struct mib_data *p;
741         struct mib_node_t *node;
742 
743         snmp_init(0, 0, (snmp_alloc_t)grad_emalloc, (snmp_free_t)grad_free);
744 
745         for (p = mib_data; p < mib_data + GRAD_NITEMS(mib_data); p++) {
746                 mib_insert(&mib_tree, p->oid, &node);
747                 if (p->handler) {
748                         node->handler = p->handler;
749                         node->closure = p->closure;
750                 }
751         }
752 }
753 
754 /* Mark reset of the auth server. Do not do any real work, though.
755  */
756 void
snmp_auth_server_reset()757 snmp_auth_server_reset()
758 {
759         struct timeval tv;
760         struct timezone tz;
761 
762         gettimeofday(&tv, &tz);
763         server_stat->auth.reset_time = tv;
764 }
765 
766 /* Mark reset of the acct server. Again, no real work, please.
767  */
768 void
snmp_acct_server_reset()769 snmp_acct_server_reset()
770 {
771         struct timeval tv;
772         struct timezone tz;
773 
774         gettimeofday(&tv, &tz);
775         server_stat->acct.reset_time = tv;
776 }
777 
778 
779 /* ************************************************************************* */
780 /* FIXME: these belong to snmp_mib.c */
781 
782 int mib_get(struct mib_node_t *node, struct snmp_var **varp,
783             int *errp);
784 int mib_get_next(struct mib_node_t *node, struct snmp_var **varp,
785                  int *errp);
786 int mib_set_try(struct mib_node_t *node, struct snmp_var **varp,
787                 int *errp);
788 int mib_set(struct mib_node_t *node, struct snmp_var **varp);
789 oid_t mib_node_oid(struct mib_node_t *node);
790 
791 int mib_down(struct mib_node_t *node, oid_t oid);
792 void mib_reset(struct mib_node_t *node);
793 
794 /* For a given node generate its oid. Note: When not needed anymore, the
795    oid should be freed by snmp_free */
796 oid_t
mib_node_oid(struct mib_node_t * node)797 mib_node_oid(struct mib_node_t *node)
798 {
799         oid_t oid;
800         int i;
801 
802         oid = oid_create(node->index+1);
803         if (!oid)
804                 return oid;
805         for (i = node->index; node && i >= 0; i--, node = node->up) {
806                 SUBID(oid,i) = (node->subid != SUBID_X) ?
807                                  node->subid :
808                                  (subid_t)(*node->handler)(MIB_NODE_GET_SUBID,
809                                                            node->closure,
810                                                            0,
811                                                            NULL, NULL);
812         }
813         return oid;
814 }
815 
816 void
mib_reset(struct mib_node_t * node)817 mib_reset(struct mib_node_t *node)
818 {
819         if (node->subid == SUBID_X) {
820                 (*node->handler)(MIB_NODE_RESET, node->closure,
821                                  0,
822                                  NULL, NULL);
823         }
824 }
825 
826 int
mib_down(struct mib_node_t * node,oid_t oid)827 mib_down(struct mib_node_t *node, oid_t oid)
828 {
829         if (node->subid == SUBID_X) {
830                 if (OIDLEN(oid) <= node->index) {
831                     (*node->handler)(MIB_NODE_RESET, node->closure,
832                                      0,
833                                      NULL, NULL);
834                     return 0;
835                 } else if ((*node->handler)(MIB_NODE_NEXT, node->closure,
836                                             SUBID(oid,node->index),
837                                             NULL, NULL) == 0)
838                         return 0;
839         }
840         return 1;
841 }
842 
843 /* Get next node.
844    Input:  node -- root node to start search from
845            varp[0][0] -- Variable to start from
846    Output: varp[0][0] -- Next variable (with its value)
847            errp[0]    -- Error status
848    Return: 0 -- OK */
849 int
mib_get_next(struct mib_node_t * node,struct snmp_var ** varp,int * errp)850 mib_get_next(struct mib_node_t *node, struct snmp_var **varp, int *errp)
851 {
852         int rc;
853         oid_t oid = (*varp)->name;
854         char buf[MAXOIDLEN];
855         struct snmp_var *temp_var;
856         struct mib_node_t *found_node;
857 
858         GRAD_DEBUG1(2, "OID %s",
859                     sprint_oid(buf, sizeof(buf), (*varp)->name));
860 
861         /* first, find the node itself */
862         rc = mib_lookup(node, oid, OIDLEN(oid), &found_node);
863 
864         *errp = SNMP_ERR_NOERROR;
865 
866         do {
867                 int depth = 0;
868                 node = found_node;
869                 mib_reset(node);
870 
871                 while (node) {
872                         if (depth++ && node->next == NULL)
873                                 break;
874 
875                         if (node->next) {
876                                 node = node->next;
877                                 mib_reset(node);
878                         } else if (node->subid == SUBID_X) {
879                                 if (mib_down(node, oid))
880                                         node = NULL;
881                         } else
882                                 node = node->down;
883                 }
884 
885                 if (!node) {
886                         /* The subtree is exhausted. Roll back until we find
887                            first non-traversed down link */
888                         GRAD_DEBUG2(2, "rolling back from %d:%d",
889                                     found_node->index,
890                                     found_node->subid);
891                         while (node = found_node->up) {
892                                 mib_reset(node);
893                                 if (node->down && node->down != found_node)
894                                         break;
895                                 if (node->subid == SUBID_X &&
896                                     mib_down(node, oid) == 0)
897                                         break;
898                                 found_node = node;
899                         }
900 
901                         if (node)
902                                 GRAD_DEBUG2(2, "rollback stopped at %d:%d",
903                                             node->index,
904                                             node->subid);
905 
906                         if (node && node->subid != SUBID_X)
907                                 node = node->down;
908 
909                 }
910 
911                 found_node = node;
912 
913         } while (found_node && found_node->handler == NULL);
914 
915         if (!found_node || !found_node->handler) {
916                 *errp = SNMP_ERR_NOSUCHNAME;
917                 return -1;
918         }
919 
920         oid = mib_node_oid(found_node);
921         temp_var = snmp_var_create(oid);
922         snmp_free(oid);
923 
924         GRAD_DEBUG1(2, "NXT %s", sprint_oid(buf, sizeof(buf), temp_var->name));
925 
926         *varp = temp_var;
927         (*found_node->handler)(MIB_NODE_GET,
928                                found_node->closure,
929                                SUBID(temp_var->name,OIDLEN(temp_var->name)-1),
930                                varp, errp);
931         snmp_var_free(temp_var);
932         return 0;
933 }
934 
935 /* Get the value of a given variable
936    Input:  node -- root node to start search from
937            varp[0][0] -- Variable to look for
938    Output: varp[0][0] -- Variable with value (not the same as on input!)
939            errp[0]    -- Error status
940    Return: 0 -- OK */
941 int
mib_get(struct mib_node_t * node,struct snmp_var ** varp,int * errp)942 mib_get(struct mib_node_t *node, struct snmp_var **varp, int *errp)
943 {
944         oid_t oid = (*varp)->name;
945 
946         if (mib_lookup(node, oid, OIDLEN(oid), &node) != MIB_MATCH_EXACT ||
947             !node->handler) {
948                 *errp = SNMP_ERR_NOSUCHNAME;
949                 return -1;
950         }
951 
952         return (*node->handler)(MIB_NODE_GET, node->closure,
953                                 SUBID(oid,OIDLEN(oid)-1),
954                                 varp, errp);
955 }
956 
957 /* Check if a variable can be set
958    Input: node -- tree node to start from
959           varp[0][0] -- variable to look for
960    Output:errp -- error status
961    Return: 0 -- OK */
962 int
mib_set_try(struct mib_node_t * node,struct snmp_var ** varp,int * errp)963 mib_set_try(struct mib_node_t *node, struct snmp_var **varp, int *errp)
964 {
965         oid_t oid = (*varp)->name;
966 
967         if (mib_lookup(node, oid, OIDLEN(oid), &node) != MIB_MATCH_EXACT ||
968             !node->handler) {
969                 *errp = SNMP_ERR_NOSUCHNAME;
970                 return -1;
971         }
972 
973         if ((*node->handler)(MIB_NODE_SET_TRY, node->closure,
974                              SUBID(oid,OIDLEN(oid)-1),
975                              varp, errp) != 0)
976                 return -1;
977         return 0;
978 }
979 
980 /* Set a variable to the new value. The fuction must be called only
981    when previous call to mib_set_try returned OK, so only rudimentary
982    error checking is done.
983    Input: node -- tree node to start from
984           varp[0][0] -- variable to be set
985    Return: 0 -- OK */
986 int
mib_set(struct mib_node_t * node,struct snmp_var ** varp)987 mib_set(struct mib_node_t *node, struct snmp_var **varp)
988 {
989         oid_t oid = (*varp)->name;
990 
991         if (mib_lookup(node, oid, OIDLEN(oid), &node) != MIB_MATCH_EXACT ||
992             !node->handler) {
993                 return -1;
994         }
995 
996         return (*node->handler)(MIB_NODE_SET, node->closure,
997                                 SUBID(oid,OIDLEN(oid)-1),
998                                 varp, NULL);
999 }
1000 
1001 /* ************************************************************************* */
1002 
1003 /* Generate response PDU for a given request.
1004    Input: pdu -- Request pdu
1005           access -- Access rights
1006    Return:Response PDU, NULL on error */
1007 struct snmp_pdu *
snmp_agent_response(struct snmp_pdu * pdu,int access)1008 snmp_agent_response(struct snmp_pdu *pdu, int access)
1009 {
1010         struct snmp_pdu *answer = NULL;
1011         struct snmp_var *vp, *vnew = NULL, **vpp;
1012         struct snmp_var **vresp;
1013         int index = 0;
1014 
1015         if ((answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
1016                 answer->req_id = pdu->req_id;
1017                 answer->err_ind = 0;
1018                 switch (pdu->type) {
1019 
1020                 case SNMP_PDU_SET:
1021                         /* First, check for the consistency of
1022                          * the request (rfc1157, 4.1.5):
1023                          */
1024                         GRAD_DEBUG(1, "SetRequest-PDU");
1025                         if (access == SNMP_RO) {
1026                                 answer->err_stat = SNMP_ERR_GENERR;
1027                                 answer->err_ind = 1;
1028                                 GRAD_DEBUG(1,"bad access mode");
1029                                 return answer;
1030                         }
1031                         for (vp = pdu->var; vp; vp = vp->next) {
1032                                 index++;
1033 
1034                                 if (mib_set_try(mib_tree, &vp,
1035                                                 &answer->err_stat))
1036                                         break;
1037                         }
1038 
1039                         if (answer->err_stat != SNMP_ERR_NOERROR) {
1040                                 answer->var = snmp_var_dup_list(pdu->var);
1041                                 answer->err_ind = index;
1042                                 GRAD_DEBUG(1, "returning error");
1043                                 return answer;
1044                         }
1045 
1046                         /* Do real work */
1047                         vresp = &answer->var;
1048                         /* Loop through all variables */
1049                         for (vpp = &pdu->var;
1050                              *vpp;
1051                              vpp = &(*vpp)->next) {
1052                                 vp = *vpp;
1053 
1054                                 vnew = vp;
1055                                 mib_set(mib_tree, &vnew);
1056 
1057                                 *vresp = vnew;
1058                                 vresp = &vnew->next;
1059                         }
1060 
1061                         GRAD_DEBUG(1, "success");
1062                         return answer;
1063 
1064                 case SNMP_PDU_GET:
1065                         GRAD_DEBUG(1, "GetRequest-PDU");
1066 
1067                         vresp = &answer->var;
1068                         /* Loop through all variables */
1069                         for (vpp = &pdu->var; *vpp; vpp = &(*vpp)->next) {
1070                                 vp = *vpp;
1071 
1072                                 index++;
1073 
1074                                 vnew = vp;
1075                                 mib_get(mib_tree, &vnew,
1076                                         &answer->err_stat);
1077 
1078                                 /* Was there an error? */
1079                                 if (answer->err_stat != SNMP_ERR_NOERROR
1080                                     || vnew == NULL) {
1081                                         answer->err_ind = index;
1082                                         GRAD_DEBUG(1,"returning");
1083                                         /* preserve the rest of vars */
1084                                         *vresp = snmp_var_dup_list(vp);
1085                                         return answer;
1086                                 }
1087                                 /* No error.
1088                                  * Insert this var at the end, and move on
1089                                  * to the next.
1090                                  */
1091                                 *vresp = vnew;
1092                                 vresp = &vnew->next;
1093                         }
1094                         return answer;
1095 
1096                 case SNMP_PDU_GETNEXT:
1097                         GRAD_DEBUG(1, "GetNextRequest-PDU");
1098 
1099                         vresp = &answer->var;
1100                         /* Loop through all variables */
1101                         for (vpp = &pdu->var; *vpp; vpp = &(*vpp)->next) {
1102                                 vp = *vpp;
1103 
1104                                 index++;
1105                                 vnew = vp;
1106                                 mib_get_next(mib_tree, &vnew,
1107                                              &answer->err_stat);
1108                                 /* Was there an error? */
1109                                 if (answer->err_stat != SNMP_ERR_NOERROR
1110                                     || vnew == NULL) {
1111                                         answer->err_ind = index;
1112                                         GRAD_DEBUG1(1,
1113                                                     "returning: err_stat=%d",
1114 						     answer->err_stat);
1115                                         /* preserve the rest of vars */
1116                                         *vresp = snmp_var_dup_list(vp);
1117                                         return answer;
1118                                 }
1119                                 /* No error.
1120                                  * Insert this var at the end, and move on
1121                                  * to the next.
1122                                  */
1123                                 *vresp = vnew;
1124                                 vresp = &vnew->next;
1125                         }
1126                         break;
1127 
1128                 default:
1129                         snmp_pdu_free(answer);
1130                         answer = NULL;
1131                 }
1132         }
1133         return answer;
1134 }
1135 
1136 /* ************************************************************************* */
1137 
1138 grad_counter_t
timeval_diff(struct timeval * tva,struct timeval * tvb)1139 timeval_diff(struct timeval *tva, struct timeval *tvb)
1140 {
1141         return  (tva->tv_sec - tvb->tv_sec)*100 +
1142                 (tva->tv_usec - tvb->tv_usec)/10000;
1143 }
1144 
1145 serv_stat
abridge_server_state()1146 abridge_server_state()
1147 {
1148         switch (server_stat->auth.status) {
1149         case serv_init:
1150         case serv_running:
1151                 return server_stat->auth.status;
1152         case serv_other:
1153         default:
1154                 return serv_other;
1155         }
1156 }
1157 
1158 /* ************************************************************************* */
1159 /* Auth sub-tree */
1160 
1161 struct snmp_var *snmp_auth_var_get(subid_t subid, oid_t oid, int *errp);
1162 int snmp_auth_var_set(subid_t subid, struct snmp_var **vp, int *errp);
1163 
1164 /* Handler function for fixed oids from the authentication subtree */
1165 int
snmp_auth_handler(enum mib_node_cmd cmd,void * closure,subid_t subid,struct snmp_var ** varp,int * errp)1166 snmp_auth_handler(enum mib_node_cmd cmd, void *closure,
1167 		  subid_t subid, struct snmp_var **varp, int *errp)
1168 {
1169         oid_t oid = (*varp)->name;
1170 
1171         switch (cmd) {
1172         case MIB_NODE_GET:
1173                 if ((*varp = snmp_auth_var_get(subid, oid, errp)) == NULL)
1174                         return -1;
1175                 break;
1176 
1177         case MIB_NODE_SET:
1178                 return snmp_auth_var_set(subid, varp, errp);
1179 
1180         case MIB_NODE_SET_TRY:
1181                 return snmp_auth_var_set(subid, varp, errp);
1182 
1183         case MIB_NODE_RESET:
1184                 break;
1185 
1186         default: /* unused: should never get there */
1187                 abort();
1188 
1189         }
1190 
1191         return 0;
1192 }
1193 
1194 struct snmp_var *
snmp_auth_var_get(subid_t subid,oid_t oid,int * errp)1195 snmp_auth_var_get(subid_t subid, oid_t oid, int *errp)
1196 {
1197         struct snmp_var *ret;
1198         struct timeval tv;
1199         struct timezone tz;
1200         char *p;
1201 
1202         ret = snmp_var_create(oid);
1203         *errp = SNMP_ERR_NOERROR;
1204 
1205         switch (subid) {
1206 
1207         case MIB_KEY_AuthServIdent:
1208                 p = make_server_ident();
1209                 ret->type = ASN_OCTET_STR;
1210                 ret->val_length = strlen(p);
1211                 ret->var_str = snmp_strdup(p);
1212                 grad_free(p);
1213                 break;
1214 
1215         case MIB_KEY_AuthServUpTime:
1216                 gettimeofday(&tv, &tz);
1217                 ret->type = SMI_TIMETICKS;
1218                 ret->val_length = sizeof(grad_counter_t);
1219                 ret->var_int = timeval_diff(&tv, &server_stat->start_time);
1220                 break;
1221 
1222         case MIB_KEY_AuthServResetTime:
1223                 gettimeofday(&tv, &tz);
1224                 ret->type = SMI_TIMETICKS;
1225                 ret->val_length = sizeof(grad_counter_t);
1226                 ret->var_int = timeval_diff(&tv,
1227                                             &server_stat->auth.reset_time);
1228                 break;
1229 
1230         case MIB_KEY_AuthServConfigReset:
1231                 ret->type = ASN_INTEGER;
1232                 ret->val_length = sizeof(grad_counter_t);
1233                 ret->var_int = abridge_server_state();
1234                 break;
1235 
1236         case MIB_KEY_AuthServTotalAccessRequests:
1237                 ret->type = SMI_COUNTER32;
1238                 ret->val_length = sizeof(grad_counter_t);
1239                 ret->var_int = server_stat->auth.num_access_req;
1240                 break;
1241 
1242         case MIB_KEY_AuthServTotalInvalidRequests:
1243                 ret->type = SMI_COUNTER32;
1244                 ret->val_length = sizeof(grad_counter_t);
1245                 ret->var_int = server_stat->auth.num_invalid_req;
1246                 break;
1247 
1248         case MIB_KEY_AuthServTotalDupAccessRequests:
1249                 ret->type = SMI_COUNTER32;
1250                 ret->val_length = sizeof(grad_counter_t);
1251                 ret->var_int = server_stat->auth.num_dup_req;
1252                 break;
1253 
1254         case MIB_KEY_AuthServTotalAccessAccepts:
1255                 ret->type = SMI_COUNTER32;
1256                 ret->val_length = sizeof(grad_counter_t);
1257                 ret->var_int = server_stat->auth.num_accepts;
1258                 break;
1259 
1260         case MIB_KEY_AuthServTotalAccessRejects:
1261                 ret->type = SMI_COUNTER32;
1262                 ret->val_length = sizeof(grad_counter_t);
1263                 ret->var_int = server_stat->auth.num_rejects;
1264                 break;
1265 
1266         case MIB_KEY_AuthServTotalAccessChallenges:
1267                 ret->type = SMI_COUNTER32;
1268                 ret->val_length = sizeof(grad_counter_t);
1269                 ret->var_int = server_stat->auth.num_challenges;
1270                 break;
1271 
1272         case MIB_KEY_AuthServTotalMalformedAccessRequests:
1273                 ret->type = SMI_COUNTER32;
1274                 ret->val_length = sizeof(grad_counter_t);
1275                 ret->var_int = server_stat->auth.num_bad_req;
1276                 break;
1277 
1278         case MIB_KEY_AuthServTotalBadAuthenticators:
1279                 ret->type = SMI_COUNTER32;
1280                 ret->val_length = sizeof(grad_counter_t);
1281                 ret->var_int = server_stat->auth.num_bad_auth;
1282                 break;
1283 
1284         case MIB_KEY_AuthServTotalPacketsDropped:
1285                 ret->type = SMI_COUNTER32;
1286                 ret->val_length = sizeof(grad_counter_t);
1287                 ret->var_int = server_stat->auth.num_dropped;
1288                 break;
1289 
1290         case MIB_KEY_AuthServTotalUnknownTypes:
1291                 ret->type = SMI_COUNTER32;
1292                 ret->val_length = sizeof(grad_counter_t);
1293                 ret->var_int = server_stat->auth.num_unknowntypes;
1294                 break;
1295 
1296         default:
1297                 *errp = SNMP_ERR_NOSUCHNAME;
1298                 snmp_var_free(ret);
1299                 return NULL;
1300         }
1301         return ret;
1302 }
1303 
1304 int
snmp_auth_var_set(subid_t subid,struct snmp_var ** vp,int * errp)1305 snmp_auth_var_set(subid_t subid, struct snmp_var **vp, int *errp)
1306 {
1307         if (errp) { /* just test */
1308                 *errp = SNMP_ERR_NOERROR;
1309                 switch (subid) {
1310 
1311                 case MIB_KEY_AccServConfigReset:
1312                         if ((*vp)->type != ASN_INTEGER ||
1313                             (*vp)->var_int != serv_reset) {
1314                                 *errp = SNMP_ERR_BADVALUE;
1315                                 *vp = NULL;
1316                         }
1317                         break;
1318                 default:
1319                         *errp = SNMP_ERR_BADVALUE;
1320                         (*vp) = NULL;
1321                 }
1322         } else {
1323                 /* do set it */
1324                 *vp = snmp_var_dup(*vp);
1325 
1326                 switch (subid) {
1327 
1328                 case MIB_KEY_AccServConfigReset:
1329                         server_stat->auth.status = serv_init;
1330                         grad_log(GRAD_LOG_INFO,
1331                                  _("acct server re-initializing on SNMP request"));
1332                         break;
1333 
1334                 }
1335         }
1336         return (*vp == NULL);
1337 }
1338 
1339 /* Variable oids */
1340 
1341 void get_auth_nasstat(grad_nas_t *nas, struct snmp_var *var, int ind);
1342 int snmp_auth_v_handler(enum mib_node_cmd cmd, void *closure,
1343                         subid_t subid, struct snmp_var **varp,
1344                         int *errp);
1345 struct snmp_var *snmp_auth_var_v_get(subid_t subid, struct snmp_var *var,
1346                                      int *errp);
1347 int snmp_auth_var_next(subid_t subid, struct auth_mib_data *closure);
1348 
1349 /* Handler function for variable oid of the authentication subtree */
1350 int
snmp_auth_v_handler(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)1351 snmp_auth_v_handler(enum mib_node_cmd cmd, void *unused, subid_t subid,
1352 		    struct snmp_var **varp, int *errp)
1353 {
1354         struct auth_mib_data *data = (struct auth_mib_data *)
1355                                             snmpserv_get_data();
1356         switch (cmd) {
1357         case MIB_NODE_GET:
1358                 if ((*varp = snmp_auth_var_v_get(subid, *varp, errp)) == NULL)
1359                         return -1;
1360                 break;
1361 
1362         case MIB_NODE_SET:
1363         case MIB_NODE_SET_TRY:
1364                 /* None of these can be set */
1365                 if (errp)
1366                         *errp = SNMP_ERR_NOSUCHNAME;
1367                 return -1;
1368 
1369         case MIB_NODE_COMPARE:
1370                 return 0;
1371 
1372         case MIB_NODE_NEXT:
1373                 return snmp_auth_var_next(subid+1, data);
1374 
1375         case MIB_NODE_GET_SUBID:
1376                 return data->nas_index;
1377 
1378         case MIB_NODE_RESET:
1379                 data->nas_index = 1;
1380                 break;
1381 
1382         }
1383 
1384         return 0;
1385 }
1386 
1387 int
snmp_auth_var_next(subid_t subid,struct auth_mib_data * closure)1388 snmp_auth_var_next(subid_t subid, struct auth_mib_data *closure)
1389 {
1390         if (!nas_lookup_index(subid))
1391                 return -1;
1392 
1393         closure->nas_index = subid;
1394         return 0;
1395 }
1396 
1397 struct snmp_var *
snmp_auth_var_v_get(subid_t subid,struct snmp_var * var,int * errp)1398 snmp_auth_var_v_get(subid_t subid, struct snmp_var *var, int *errp)
1399 {
1400         struct snmp_var *ret;
1401         subid_t key;
1402         grad_nas_t *nas;
1403 
1404         ret = snmp_var_create(var->name);
1405         *errp = SNMP_ERR_NOERROR;
1406 
1407         switch (key = SUBID(var->name, OIDLEN(var->name)-2)) {
1408         case MIB_KEY_AuthClientIndex:
1409         case MIB_KEY_AuthClientAddress:
1410         case MIB_KEY_AuthClientID:
1411         case MIB_KEY_AuthServAccessRequests:
1412         case MIB_KEY_AuthServDupAccessRequests:
1413         case MIB_KEY_AuthServAccessAccepts:
1414         case MIB_KEY_AuthServAccessRejects:
1415         case MIB_KEY_AuthServAccessChallenges:
1416         case MIB_KEY_AuthServMalformedAccessRequests:
1417         case MIB_KEY_AuthServBadAuthenticators:
1418         case MIB_KEY_AuthServPacketsDropped:
1419         case MIB_KEY_AuthServUnknownTypes:
1420                 if ((nas = nas_lookup_index(subid)) != NULL &&
1421                     nas->app_data) {
1422                         get_auth_nasstat(nas, ret, key);
1423                         break;
1424                 }
1425                 /*FALLTHRU*/
1426         default:
1427                 *errp = SNMP_ERR_NOSUCHNAME;
1428                 snmp_var_free(ret);
1429                 return NULL;
1430         }
1431         return ret;
1432 }
1433 
1434 void
get_auth_nasstat(grad_nas_t * nas,struct snmp_var * var,int key)1435 get_auth_nasstat(grad_nas_t *nas, struct snmp_var *var, int key)
1436 {
1437         struct nas_stat *statp = nas->app_data;
1438 
1439         switch (key) {
1440         case MIB_KEY_AuthClientIndex:
1441                 var->type = ASN_INTEGER;
1442                 var->val_length = sizeof(int);
1443                 var->var_int = statp->index;
1444                 break;
1445 
1446         case MIB_KEY_AuthClientAddress:
1447                 var->type = SMI_IPADDRESS;
1448                 var->val_length = sizeof(grad_uint32_t);
1449                 var->var_str = snmp_alloc(sizeof(grad_uint32_t));
1450                 *(grad_uint32_t*)var->var_str = ntohl(statp->ipaddr);
1451                 break;
1452 
1453         case MIB_KEY_AuthClientID:
1454                 var->type = ASN_OCTET_STR;
1455                 var->val_length = strlen(nas->longname);
1456                 var->var_str = snmp_strdup(nas->longname);
1457                 break;
1458 
1459         case MIB_KEY_AuthServAccessRequests:
1460                 var->type = SMI_COUNTER32;
1461                 var->val_length = sizeof(grad_counter_t);
1462                 var->var_int = statp->auth.num_access_req;
1463                 break;
1464 
1465         case MIB_KEY_AuthServDupAccessRequests:
1466                 var->type = SMI_COUNTER32;
1467                 var->val_length = sizeof(grad_counter_t);
1468                 var->var_int = statp->auth.num_dup_req;
1469                 break;
1470 
1471         case MIB_KEY_AuthServAccessAccepts:
1472                 var->type = SMI_COUNTER32;
1473                 var->val_length = sizeof(grad_counter_t);
1474                 var->var_int = statp->auth.num_accepts;
1475                 break;
1476 
1477         case MIB_KEY_AuthServAccessRejects:
1478                 var->type = SMI_COUNTER32;
1479                 var->val_length = sizeof(grad_counter_t);
1480                 var->var_int = statp->auth.num_rejects;
1481                 break;
1482 
1483         case MIB_KEY_AuthServAccessChallenges:
1484                 var->type = SMI_COUNTER32;
1485                 var->val_length = sizeof(grad_counter_t);
1486                 var->var_int = statp->auth.num_challenges;
1487                 break;
1488 
1489         case MIB_KEY_AuthServMalformedAccessRequests:
1490                 var->type = SMI_COUNTER32;
1491                 var->val_length = sizeof(grad_counter_t);
1492                 var->var_int = statp->auth.num_bad_req;
1493                 break;
1494 
1495         case MIB_KEY_AuthServBadAuthenticators:
1496                 var->type = SMI_COUNTER32;
1497                 var->val_length = sizeof(grad_counter_t);
1498                 var->var_int = statp->auth.num_bad_auth;
1499                 break;
1500 
1501         case MIB_KEY_AuthServPacketsDropped:
1502                 var->type = SMI_COUNTER32;
1503                 var->val_length = sizeof(grad_counter_t);
1504                 var->var_int = statp->auth.num_dropped;
1505                 break;
1506 
1507         case MIB_KEY_AuthServUnknownTypes:
1508                 var->type = SMI_COUNTER32;
1509                 var->val_length = sizeof(grad_counter_t);
1510                 var->var_int = statp->auth.num_unknowntypes;
1511                 break;
1512 
1513         }
1514 }
1515 
1516 
1517 /* ************************************************************************* */
1518 /* Accounting sub-tree */
1519 struct snmp_var *snmp_acct_var_get(subid_t subid, oid_t oid, int *errp);
1520 int snmp_acct_var_set(subid_t subid, struct snmp_var **vp, int *errp);
1521 
1522 /* Handler function for fixed oids from the authentication subtree */
1523 
1524 int
snmp_acct_handler(enum mib_node_cmd cmd,void * closure,subid_t subid,struct snmp_var ** varp,int * errp)1525 snmp_acct_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
1526 		  struct snmp_var **varp, int *errp)
1527 {
1528         oid_t oid = (*varp)->name;
1529 
1530         switch (cmd) {
1531         case MIB_NODE_GET:
1532                 if ((*varp = snmp_acct_var_get(subid, oid, errp)) == NULL)
1533                         return -1;
1534                 break;
1535 
1536         case MIB_NODE_SET:
1537                 return snmp_acct_var_set(subid, varp, errp);
1538 
1539         case MIB_NODE_SET_TRY:
1540                 return snmp_acct_var_set(subid, varp, errp);
1541 
1542         case MIB_NODE_RESET:
1543                 break;
1544 
1545         default: /* unused: should never get there */
1546                 abort();
1547 
1548         }
1549 
1550         return 0;
1551 }
1552 
1553 struct snmp_var *
snmp_acct_var_get(subid_t subid,oid_t oid,int * errp)1554 snmp_acct_var_get(subid_t subid, oid_t oid, int *errp)
1555 {
1556         struct snmp_var *ret;
1557         struct timeval tv;
1558         struct timezone tz;
1559         char *p;
1560 
1561         ret = snmp_var_create(oid);
1562         *errp = SNMP_ERR_NOERROR;
1563 
1564         switch (subid) {
1565 
1566         case MIB_KEY_AccServIdent:
1567                 p = make_server_ident();
1568                 ret->type = ASN_OCTET_STR;
1569                 ret->val_length = strlen(p);
1570                 ret->var_str = snmp_strdup(p);
1571                 grad_free(p);
1572                 break;
1573 
1574         case MIB_KEY_AccServUpTime:
1575                 gettimeofday(&tv, &tz);
1576                 ret->type = SMI_TIMETICKS;
1577                 ret->val_length = sizeof(grad_counter_t);
1578                 ret->var_int = timeval_diff(&tv, &server_stat->start_time);
1579                 break;
1580 
1581         case MIB_KEY_AccServResetTime:
1582                 gettimeofday(&tv, &tz);
1583                 ret->type = SMI_TIMETICKS;
1584                 ret->val_length = sizeof(grad_counter_t);
1585                 ret->var_int = timeval_diff(&tv, &server_stat->acct.reset_time);
1586                 break;
1587 
1588         case MIB_KEY_AccServConfigReset:
1589                 ret->type = ASN_INTEGER;
1590                 ret->val_length = sizeof(grad_counter_t);
1591                 ret->var_int = abridge_server_state();
1592                 break;
1593 
1594         case MIB_KEY_AccServTotalRequests:
1595                 ret->type = SMI_COUNTER32;
1596                 ret->val_length = sizeof(grad_counter_t);
1597                 ret->var_int = server_stat->acct.num_req;
1598                 break;
1599 
1600         case MIB_KEY_AccServTotalInvalidRequests:
1601                 ret->type = SMI_COUNTER32;
1602                 ret->val_length = sizeof(grad_counter_t);
1603                 ret->var_int = server_stat->acct.num_invalid_req;
1604                 break;
1605 
1606         case MIB_KEY_AccServTotalDupRequests:
1607                 ret->type = SMI_COUNTER32;
1608                 ret->val_length = sizeof(grad_counter_t);
1609                 ret->var_int = server_stat->acct.num_dup_req;
1610                 break;
1611 
1612         case MIB_KEY_AccServTotalResponses:
1613                 ret->type = SMI_COUNTER32;
1614                 ret->val_length = sizeof(grad_counter_t);
1615                 ret->var_int = server_stat->acct.num_resp;
1616                 break;
1617 
1618         case MIB_KEY_AccServTotalMalformedRequests:
1619                 ret->type = SMI_COUNTER32;
1620                 ret->val_length = sizeof(grad_counter_t);
1621                 ret->var_int = server_stat->acct.num_bad_req;
1622                 break;
1623 
1624         case MIB_KEY_AccServTotalBadAuthenticators:
1625                 ret->type = SMI_COUNTER32;
1626                 ret->val_length = sizeof(grad_counter_t);
1627                 ret->var_int = server_stat->acct.num_bad_sign;
1628                 break;
1629 
1630         case MIB_KEY_AccServTotalPacketsDropped:
1631                 ret->type = SMI_COUNTER32;
1632                 ret->val_length = sizeof(grad_counter_t);
1633                 ret->var_int = server_stat->acct.num_dropped;
1634                 break;
1635 
1636         case MIB_KEY_AccServTotalNoRecords:
1637                 ret->type = SMI_COUNTER32;
1638                 ret->val_length = sizeof(grad_counter_t);
1639                 ret->var_int = server_stat->acct.num_norecords;
1640                 break;
1641 
1642         case MIB_KEY_AccServTotalUnknownTypes:
1643                 ret->type = SMI_COUNTER32;
1644                 ret->val_length = sizeof(grad_counter_t);
1645                 ret->var_int = server_stat->acct.num_unknowntypes;
1646                 break;
1647 
1648         default:
1649                 *errp = SNMP_ERR_NOSUCHNAME;
1650                 snmp_var_free(ret);
1651                 return NULL;
1652         }
1653         return ret;
1654 }
1655 
1656 int
snmp_acct_var_set(subid_t subid,struct snmp_var ** vp,int * errp)1657 snmp_acct_var_set(subid_t subid, struct snmp_var **vp, int *errp)
1658 {
1659         if (errp) { /* just test */
1660                 *errp = SNMP_ERR_NOERROR;
1661                 switch (subid) {
1662 
1663                 case MIB_KEY_AuthServConfigReset:
1664                         if ((*vp)->type != ASN_INTEGER ||
1665                             (*vp)->var_int != serv_reset) {
1666                                 *errp = SNMP_ERR_BADVALUE;
1667                                 *vp = NULL;
1668                         }
1669                         break;
1670                 default:
1671                         *errp = SNMP_ERR_BADVALUE;
1672                         (*vp) = NULL;
1673                 }
1674         } else {
1675                 /* do set it */
1676                 *vp = snmp_var_dup(*vp);
1677 
1678                 switch (subid) {
1679 
1680                 case MIB_KEY_AuthServConfigReset:
1681                         server_stat->auth.status = serv_init;
1682                         grad_log(GRAD_LOG_INFO,
1683                                  _("auth server re-initializing on SNMP request"));
1684                         break;
1685 
1686                 }
1687         }
1688         return (*vp == NULL);
1689 }
1690 
1691 void get_acct_nasstat(grad_nas_t *nas, struct snmp_var *var, int key);
1692 int snmp_acct_v_handler(enum mib_node_cmd cmd, void *closure,
1693                         subid_t subid, struct snmp_var **varp,
1694                         int *errp);
1695 struct snmp_var *snmp_acct_var_v_get(subid_t subid, struct snmp_var *var,
1696                                      int *errp);
1697 
1698 /* Handler function for variable oid of the authentication subtree */
1699 int
snmp_acct_v_handler(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)1700 snmp_acct_v_handler(enum mib_node_cmd cmd, void *unused, subid_t subid,
1701 		    struct snmp_var **varp, int *errp)
1702 {
1703         struct auth_mib_data *data = (struct auth_mib_data *)
1704                                         snmpserv_get_data();
1705         switch (cmd) {
1706         case MIB_NODE_GET:
1707                 if ((*varp = snmp_acct_var_v_get(subid, *varp, errp)) == NULL)
1708                         return -1;
1709                 break;
1710 
1711         case MIB_NODE_SET:
1712         case MIB_NODE_SET_TRY:
1713                 /* None of these can be set */
1714                 if (errp)
1715                         *errp = SNMP_ERR_NOSUCHNAME;
1716                 return -1;
1717 
1718         case MIB_NODE_COMPARE:
1719                 return 0;
1720 
1721         case MIB_NODE_NEXT:
1722                 return snmp_auth_var_next(subid+1, data);
1723 
1724         case MIB_NODE_GET_SUBID:
1725                 return data->nas_index;
1726 
1727         case MIB_NODE_RESET:
1728                 data->nas_index = 1;
1729                 break;
1730 
1731         }
1732 
1733         return 0;
1734 }
1735 
1736 struct snmp_var *
snmp_acct_var_v_get(subid_t subid,struct snmp_var * var,int * errp)1737 snmp_acct_var_v_get(subid_t subid, struct snmp_var *var, int *errp)
1738 {
1739         struct snmp_var *ret;
1740         subid_t key;
1741         grad_nas_t *nas;
1742 
1743         ret = snmp_var_create(var->name);
1744         *errp = SNMP_ERR_NOERROR;
1745 
1746         switch (key = SUBID(var->name, OIDLEN(var->name)-2)) {
1747         case MIB_KEY_AccClientIndex:
1748         case MIB_KEY_AccClientAddress:
1749         case MIB_KEY_AccClientID:
1750         case MIB_KEY_AccServPacketsDropped:
1751         case MIB_KEY_AccServRequests:
1752         case MIB_KEY_AccServDupRequests:
1753         case MIB_KEY_AccServResponses:
1754         case MIB_KEY_AccServBadAuthenticators:
1755         case MIB_KEY_AccServMalformedRequests:
1756         case MIB_KEY_AccServNoRecords:
1757         case MIB_KEY_AccServUnknownTypes:
1758                 if ((nas = nas_lookup_index(subid)) != NULL &&
1759                      nas->app_data) {
1760                         get_acct_nasstat(nas, ret, key);
1761                         break;
1762                 }
1763                 /*FALLTHRU*/
1764         default:
1765                 *errp = SNMP_ERR_NOSUCHNAME;
1766                 snmp_var_free(ret);
1767                 return NULL;
1768         }
1769         return ret;
1770 }
1771 
1772 void
get_acct_nasstat(grad_nas_t * nas,struct snmp_var * var,int key)1773 get_acct_nasstat(grad_nas_t *nas, struct snmp_var *var, int key)
1774 {
1775         struct nas_stat *statp = nas->app_data;
1776 
1777         switch (key) {
1778         case MIB_KEY_AccClientIndex:
1779                 var->type = ASN_INTEGER;
1780                 var->val_length = sizeof(int);
1781                 var->var_int = statp->index;
1782                 break;
1783 
1784         case MIB_KEY_AccClientAddress:
1785                 var->type = SMI_IPADDRESS;
1786                 var->val_length = sizeof(grad_uint32_t);
1787                 var->var_str = snmp_alloc(sizeof(grad_uint32_t));
1788                 *(grad_uint32_t*)var->var_str = ntohl(statp->ipaddr);
1789                 break;
1790 
1791         case MIB_KEY_AccClientID:
1792                 var->type = ASN_OCTET_STR;
1793                 var->val_length = strlen(nas->longname);
1794                 var->var_str = snmp_strdup(nas->longname);
1795                 break;
1796 
1797         case MIB_KEY_AccServPacketsDropped:
1798                 var->type = SMI_COUNTER32;
1799                 var->val_length = sizeof(grad_counter_t);
1800                 var->var_int = statp->acct.num_dropped;
1801                 break;
1802 
1803         case MIB_KEY_AccServRequests:
1804                 var->type = SMI_COUNTER32;
1805                 var->val_length = sizeof(grad_counter_t);
1806                 var->var_int = statp->acct.num_req;
1807                 break;
1808 
1809         case MIB_KEY_AccServDupRequests:
1810                 var->type = SMI_COUNTER32;
1811                 var->val_length = sizeof(grad_counter_t);
1812                 var->var_int = statp->acct.num_dup_req;
1813                 break;
1814 
1815         case MIB_KEY_AccServResponses:
1816                 var->type = SMI_COUNTER32;
1817                 var->val_length = sizeof(grad_counter_t);
1818                 var->var_int = statp->acct.num_resp;
1819                 break;
1820 
1821         case MIB_KEY_AccServBadAuthenticators:
1822                 var->type = SMI_COUNTER32;
1823                 var->val_length = sizeof(grad_counter_t);
1824                 var->var_int = statp->acct.num_bad_sign;
1825                 break;
1826 
1827         case MIB_KEY_AccServMalformedRequests:
1828                 var->type = SMI_COUNTER32;
1829                 var->val_length = sizeof(grad_counter_t);
1830                 var->var_int = statp->acct.num_bad_req;
1831                 break;
1832 
1833         case MIB_KEY_AccServNoRecords:
1834                 var->type = SMI_COUNTER32;
1835                 var->val_length = sizeof(grad_counter_t);
1836                 var->var_int = statp->acct.num_norecords;
1837                 break;
1838 
1839         case MIB_KEY_AccServUnknownTypes:
1840                 var->type = SMI_COUNTER32;
1841                 var->val_length = sizeof(grad_counter_t);
1842                 var->var_int = statp->acct.num_unknowntypes;
1843                 break;
1844         }
1845 }
1846 
1847 /* ************************************************************************* */
1848 /* Server */
1849 struct snmp_var *snmp_serv_var_get(subid_t subid, oid_t oid, int *errp);
1850 int snmp_serv_var_set(subid_t subid, struct snmp_var **vp, int *errp);
1851 
1852 /* Handler function for fixed oids from the server subtree */
1853 
1854 int
snmp_serv_handler(enum mib_node_cmd cmd,void * closure,subid_t subid,struct snmp_var ** varp,int * errp)1855 snmp_serv_handler(enum mib_node_cmd cmd, void *closure,
1856 		  subid_t subid, struct snmp_var **varp, int *errp)
1857 {
1858         oid_t oid = (*varp)->name;
1859 
1860         switch (cmd) {
1861         case MIB_NODE_GET:
1862                 if ((*varp = snmp_serv_var_get(subid, oid, errp)) == NULL)
1863                         return -1;
1864                 break;
1865 
1866         case MIB_NODE_SET:
1867                 return snmp_serv_var_set(subid, varp, errp);
1868 
1869         case MIB_NODE_SET_TRY:
1870                 return snmp_serv_var_set(subid, varp, errp);
1871 
1872         case MIB_NODE_RESET:
1873                 break;
1874 
1875         default: /* unused: should never get there */
1876                 abort();
1877 
1878         }
1879 
1880         return 0;
1881 }
1882 
1883 struct snmp_var *
snmp_serv_var_get(subid_t subid,oid_t oid,int * errp)1884 snmp_serv_var_get(subid_t subid, oid_t oid, int *errp)
1885 {
1886         struct snmp_var *ret;
1887         struct timeval tv;
1888         struct timezone tz;
1889 
1890         ret = snmp_var_create(oid);
1891         *errp = SNMP_ERR_NOERROR;
1892 
1893         switch (subid) {
1894 
1895         case MIB_KEY_radiusServerUpTime:
1896                 gettimeofday(&tv, &tz);
1897                 ret->type = SMI_TIMETICKS;
1898                 ret->val_length = sizeof(grad_counter_t);
1899                 ret->var_int = timeval_diff(&tv, &server_stat->start_time);
1900                 break;
1901 
1902         case MIB_KEY_radiusServerResetTime:
1903                 gettimeofday(&tv, &tz);
1904                 ret->type = SMI_TIMETICKS;
1905                 ret->val_length = sizeof(grad_counter_t);
1906                 ret->var_int = timeval_diff(&tv,
1907                                             &server_stat->auth.reset_time);
1908                 break;
1909 
1910         case MIB_KEY_radiusServerState:
1911                 ret->type = ASN_INTEGER;
1912                 ret->val_length = sizeof(grad_counter_t);
1913                 ret->var_int = server_stat->auth.status;/*FIXME*/
1914                 break;
1915         default:
1916                 *errp = SNMP_ERR_NOSUCHNAME;
1917                 snmp_var_free(ret);
1918                 return NULL;
1919         }
1920         return ret;
1921 }
1922 
1923 int
snmp_serv_var_set(subid_t subid,struct snmp_var ** vp,int * errp)1924 snmp_serv_var_set(subid_t subid, struct snmp_var **vp, int *errp)
1925 {
1926         if (errp) { /* just test */
1927                 *errp = SNMP_ERR_NOERROR;
1928                 switch (subid) {
1929 
1930                 case MIB_KEY_radiusServerState:
1931                         if ((*vp)->type != ASN_INTEGER) {
1932                                 *errp = SNMP_ERR_BADVALUE;
1933                                 *vp = NULL;
1934                         } else {
1935                                 switch ((*vp)->var_int) {
1936                                 case serv_reset:
1937                                 case serv_init:
1938                                 case serv_running:
1939                                 case serv_suspended:
1940                                 case serv_shutdown:
1941                                         break;
1942                                 default:
1943                                         *errp = SNMP_ERR_BADVALUE;
1944                                         *vp = NULL;
1945                                 }
1946                         }
1947                         break;
1948                 default:
1949                         *errp = SNMP_ERR_BADVALUE;
1950                         (*vp) = NULL;
1951                 }
1952         } else {
1953                 /* do set it */
1954                 *vp = snmp_var_dup(*vp);
1955 
1956                 switch (subid) {
1957 
1958                 case MIB_KEY_radiusServerState:
1959                         server_stat->auth.status = (*vp)->var_int;
1960                         switch ((*vp)->var_int) {
1961                         case serv_reset:
1962                                 grad_log(GRAD_LOG_NOTICE,
1963                                          _("server re-initializing on SNMP request"));
1964                                 break;
1965                         case serv_init:
1966                                 grad_log(GRAD_LOG_NOTICE,
1967                                          _("server restart on SNMP request"));
1968                                 break;
1969                         case serv_running:
1970                                 grad_log(GRAD_LOG_NOTICE,
1971                                          _("server continuing on SNMP request"));
1972                                 break;
1973                         case serv_suspended:
1974                                 grad_log(GRAD_LOG_NOTICE,
1975                                          _("server suspending on SNMP request"));
1976                                 break;
1977                         case serv_shutdown:
1978                                 grad_log(GRAD_LOG_NOTICE,
1979                                          _("server shutting down on SNMP request"));
1980                                 break;
1981                         }
1982                         break;
1983 
1984                 }
1985         }
1986         return (*vp == NULL);
1987 }
1988 
1989 
1990 /* ************************************************************************* */
1991 /* Statistics */
1992 struct snmp_var *snmp_stat_var_get(subid_t subid, oid_t oid, int *errp);
1993 int snmp_stat_var_set(subid_t subid, struct snmp_var **vp, int *errp);
1994 
1995 /* Handler function for fixed oids from the authentication subtree */
1996 
1997 int
snmp_stat_handler(enum mib_node_cmd cmd,void * closure,subid_t subid,struct snmp_var ** varp,int * errp)1998 snmp_stat_handler(enum mib_node_cmd cmd, void *closure, subid_t subid,
1999 		  struct snmp_var **varp, int *errp)
2000 {
2001         oid_t oid = (*varp)->name;
2002 
2003         switch (cmd) {
2004         case MIB_NODE_GET:
2005                 if ((*varp = snmp_stat_var_get(subid, oid, errp)) == NULL)
2006                         return -1;
2007                 break;
2008 
2009         case MIB_NODE_SET:
2010         case MIB_NODE_SET_TRY:
2011                 /*FIXME: return snmp_stat_var_set(subid, varp, errp); */
2012                 *errp = SNMP_ERR_BADVALUE;
2013                 return -1;
2014 
2015         case MIB_NODE_RESET:
2016                 break;
2017 
2018         default: /* unused: should never get there */
2019                 abort();
2020 
2021         }
2022 
2023         return 0;
2024 }
2025 
2026 struct snmp_var *
snmp_stat_var_get(subid_t subid,oid_t oid,int * errp)2027 snmp_stat_var_get(subid_t subid, oid_t oid, int *errp)
2028 {
2029         struct snmp_var *ret;
2030         struct timeval tv;
2031         struct timezone tz;
2032         char *p;
2033 
2034         ret = snmp_var_create(oid);
2035         *errp = SNMP_ERR_NOERROR;
2036 
2037         switch (subid) {
2038 
2039         case MIB_KEY_StatIdent:
2040                 p = make_server_ident();
2041                 ret->type = ASN_OCTET_STR;
2042                 ret->val_length = strlen(p);
2043                 ret->var_str = snmp_strdup(p);
2044                 grad_free(p);
2045                 break;
2046 
2047         case MIB_KEY_StatUpTime:
2048                 gettimeofday(&tv, &tz);
2049                 ret->type = SMI_TIMETICKS;
2050                 ret->val_length = sizeof(grad_counter_t);
2051                 ret->var_int = timeval_diff(&tv, &radstat.start_time);
2052                 break;
2053 
2054         case MIB_KEY_StatConfigReset:
2055                 ret->type = ASN_INTEGER;
2056                 ret->val_length = sizeof(grad_counter_t);
2057                 ret->var_int = serv_running;;
2058                 break;
2059 
2060         case MIB_KEY_StatTotalLines:
2061                 ret->type = SMI_COUNTER32;
2062                 ret->val_length = sizeof(grad_counter_t);
2063                 stat_count_ports();
2064                 ret->var_int = radstat.port_active_count
2065                             + radstat.port_idle_count;
2066                 break;
2067 
2068         case MIB_KEY_StatTotalLinesInUse:
2069                 ret->type = SMI_COUNTER32;
2070                 ret->val_length = sizeof(grad_counter_t);
2071                 stat_count_ports();
2072                 ret->var_int = radstat.port_active_count;
2073                 break;
2074 
2075         case MIB_KEY_StatTotalLinesIdle:
2076                 ret->type = SMI_COUNTER32;
2077                 ret->val_length = sizeof(grad_counter_t);
2078                 stat_count_ports();
2079                 ret->var_int = radstat.port_idle_count;
2080                 break;
2081 
2082         default:
2083                 *errp = SNMP_ERR_NOSUCHNAME;
2084                 snmp_var_free(ret);
2085                 return NULL;
2086         }
2087         return ret;
2088 }
2089 
2090 int
snmp_stat_nas(int num,enum mib_node_cmd cmd,struct nas_data * closure,subid_t subid,struct snmp_var ** varp,int * errp)2091 snmp_stat_nas(int num, enum mib_node_cmd cmd, struct nas_data *closure,
2092 	      subid_t subid, struct snmp_var **varp, int *errp)
2093 {
2094         grad_nas_t *nas;
2095         struct nas_stat *nsp;
2096         grad_uint32_t ip;
2097         struct snmp_var *var;
2098         int len;
2099 
2100         switch (cmd) {
2101         case MIB_NODE_GET:
2102                 if (SUBID((*varp)->name, 6) == 9163)
2103                         len = LEN_grad_NASIndex4;
2104                 else
2105                         len = LEN_NASIndex4;
2106 
2107                 if (num != 3 || OIDLEN((*varp)->name) != len) {
2108                         *errp = SNMP_ERR_NOSUCHNAME;
2109                         return -1;
2110                 }
2111                 ip = (closure->quad[0]<<24)+
2112                         (closure->quad[1]<<16)+
2113                         (closure->quad[2]<<8) +
2114                         closure->quad[3];
2115 
2116                 if ((nsp = find_nas_stat(ip)) == NULL) {
2117                         *errp = SNMP_ERR_NOSUCHNAME;
2118                         return -1;
2119                 }
2120 
2121                 *errp = SNMP_ERR_NOERROR;
2122                 var = snmp_var_create((*varp)->name);
2123                 var->type = ASN_INTEGER;
2124                 var->val_length = sizeof(int);
2125                 var->var_int = nsp->index;
2126 
2127                 *varp = var;
2128                 break;
2129 
2130         case MIB_NODE_SET:
2131         case MIB_NODE_SET_TRY:
2132                 /* None of these can be set */
2133                 if (errp)
2134                         *errp = SNMP_ERR_NOSUCHNAME;
2135                 return -1;
2136 
2137         case MIB_NODE_COMPARE:
2138                 closure->quad[num] = subid;
2139                 return 0;
2140 
2141         case MIB_NODE_NEXT:
2142                 if (num != 3)
2143                         return  -1;
2144 
2145                 ip = (closure->quad[0]<<24)+
2146                         (closure->quad[1]<<16)+
2147                         (closure->quad[2]<<8) +
2148                         closure->quad[3];
2149 
2150                 if ((nas = grad_nas_lookup_ip(ip)) == NULL) {
2151                         return -1;
2152                 }
2153 
2154                 nsp = nas->app_data;
2155                 if ((nas = nas_lookup_index(nsp->index+1)) == NULL) {
2156                         return -1;
2157                 }
2158 
2159 		/* FIXME: MIBS do not reflect netmask */
2160                 for (num = 0; num < 4; num++)
2161                         closure->quad[num] = (nas->netdef.ipaddr >>
2162                                               (8*(3-num))) & 0xff;
2163 
2164                 break;
2165 
2166         case MIB_NODE_GET_SUBID:
2167                 return closure->quad[num];
2168 
2169         case MIB_NODE_RESET:
2170                 if (num == 0) {
2171                         if (nas = nas_lookup_index(1))
2172                                 for (num = 0; num < 4; num++)
2173                                         closure->quad[num] =
2174 						(nas->netdef.ipaddr >>
2175                                                           (8*(3-num))) & 0xff;
2176                 }
2177                 break;
2178 
2179         }
2180 
2181         return 0;
2182 }
2183 
2184 int
snmp_stat_nas1(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2185 snmp_stat_nas1(enum mib_node_cmd cmd, void *unused,
2186 	       subid_t subid, struct snmp_var **varp, int *errp)
2187 {
2188         return snmp_stat_nas(0, cmd,
2189                              (struct nas_data*)snmpserv_get_data(), subid,
2190                              varp, errp);
2191 }
2192 
2193 int
snmp_stat_nas2(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2194 snmp_stat_nas2(enum mib_node_cmd cmd, void *unused,
2195 	       subid_t subid, struct snmp_var **varp, int *errp)
2196 {
2197         return snmp_stat_nas(1, cmd,
2198                              (struct nas_data*)snmpserv_get_data(), subid,
2199                              varp, errp);
2200 }
2201 
2202 int
snmp_stat_nas3(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2203 snmp_stat_nas3(enum mib_node_cmd cmd, void *unused,
2204 	       subid_t subid, struct snmp_var **varp, int *errp)
2205 {
2206         return snmp_stat_nas(2, cmd,
2207                              (struct nas_data*)snmpserv_get_data(), subid,
2208                              varp, errp);
2209 }
2210 
2211 int
snmp_stat_nas4(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2212 snmp_stat_nas4(enum mib_node_cmd cmd, void *unused,
2213 	       subid_t subid, struct snmp_var **varp, int *errp)
2214 {
2215         return snmp_stat_nas(3, cmd,
2216                              (struct nas_data*)snmpserv_get_data(), subid,
2217                              varp, errp);
2218 }
2219 
2220 
2221 void get_stat_nasstat(grad_nas_t *nas, struct snmp_var *var, int ind);
2222 struct snmp_var *snmp_nas_table_get(subid_t subid, oid_t oid, int *errp);
2223 
2224 int
snmp_nas_table(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2225 snmp_nas_table(enum mib_node_cmd cmd, void *unused,
2226 	       subid_t subid, struct snmp_var **varp, int *errp)
2227 {
2228         struct nas_table_data *data = (struct nas_table_data*)
2229                                          snmpserv_get_data();
2230         switch (cmd) {
2231         case MIB_NODE_GET:
2232                 if ((*varp = snmp_nas_table_get(subid, (*varp)->name, errp))
2233                     == NULL)
2234                         return -1;
2235                 break;
2236 
2237         case MIB_NODE_SET:
2238         case MIB_NODE_SET_TRY:
2239                 /* None of these can be set */
2240                 if (errp)
2241                         *errp = SNMP_ERR_NOSUCHNAME;
2242                 return -1;
2243 
2244         case MIB_NODE_NEXT:
2245                 if (!nas_lookup_index(subid+1))
2246                         return -1;
2247                 data->row = subid+1;
2248                 break;
2249 
2250         case MIB_NODE_RESET:
2251                 data->row = 1;
2252                 break;
2253 
2254         case MIB_NODE_GET_SUBID:
2255                 return data->row;
2256 
2257         case MIB_NODE_COMPARE:
2258                 return 0;
2259 
2260         default: /* unused: should never get there */
2261                 abort();
2262 
2263         }
2264 
2265         return 0;
2266 
2267 }
2268 
2269 struct snmp_var *
snmp_nas_table_get(subid_t subid,oid_t oid,int * errp)2270 snmp_nas_table_get(subid_t subid, oid_t oid, int *errp)
2271 {
2272         struct snmp_var *ret;
2273         subid_t key;
2274         grad_nas_t *nas;
2275 
2276         ret = snmp_var_create(oid);
2277         *errp = SNMP_ERR_NOERROR;
2278 
2279         switch (key = SUBID(oid, OIDLEN(oid)-2)) {
2280         case MIB_KEY_NASAddress:
2281         case MIB_KEY_NASID:
2282         case MIB_KEY_NASLines:
2283         case MIB_KEY_NASLinesInUse:
2284         case MIB_KEY_NASLinesIdle:
2285                 if ((nas = nas_lookup_index(subid)) != NULL && nas->app_data) {
2286                         get_stat_nasstat(nas, ret, key);
2287                         break;
2288                 }
2289                 /*FALLTHRU*/
2290         default:
2291                 *errp = SNMP_ERR_NOSUCHNAME;
2292                 snmp_var_free(ret);
2293                 return NULL;
2294         }
2295         return ret;
2296 }
2297 
2298 void
get_stat_nasstat(grad_nas_t * nas,struct snmp_var * var,int ind)2299 get_stat_nasstat(grad_nas_t *nas, struct snmp_var *var, int ind)
2300 {
2301         struct nas_stat *statp = nas->app_data;
2302 
2303         switch (ind) {
2304         case MIB_KEY_NASAddress:
2305                 var->type = SMI_IPADDRESS;
2306                 var->val_length = sizeof(grad_uint32_t);
2307                 var->var_str = snmp_alloc(sizeof(grad_uint32_t));
2308                 *(grad_uint32_t*)var->var_str = ntohl(statp->ipaddr);
2309                 break;
2310 
2311         case MIB_KEY_NASID:
2312                 var->type = ASN_OCTET_STR;
2313                 var->val_length = strlen(nas->longname);
2314                 var->var_str = snmp_strdup(nas->longname);
2315                 break;
2316 
2317         case MIB_KEY_NASLines:
2318                 stat_count_ports();
2319                 var->type = SMI_COUNTER32;
2320                 var->val_length = sizeof(grad_counter_t);
2321                 var->var_int = statp->ports_active +
2322                                statp->ports_idle;
2323                 break;
2324 
2325         case MIB_KEY_NASLinesInUse:
2326                 stat_count_ports();
2327                 var->type = SMI_COUNTER32;
2328                 var->val_length = sizeof(grad_counter_t);
2329                 var->var_int = statp->ports_active;
2330                 break;
2331 
2332         case MIB_KEY_NASLinesIdle:
2333                 stat_count_ports();
2334                 var->type = SMI_COUNTER32;
2335                 var->val_length = sizeof(grad_counter_t);
2336                 var->var_int = statp->ports_idle;
2337                 break;
2338 
2339         }
2340 }
2341 
2342 /*ARGSUSED*/
2343 int
snmp_port_index1(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2344 snmp_port_index1(enum mib_node_cmd cmd, void *unused,
2345 		 subid_t subid, struct snmp_var **varp, int *errp)
2346 {
2347         grad_nas_t *nas;
2348         struct port_data *pind = (struct port_data*)snmpserv_get_data();
2349 
2350         switch (cmd) {
2351         case MIB_NODE_GET:
2352                 *errp = SNMP_ERR_NOSUCHNAME;
2353                 return -1;
2354 
2355         case MIB_NODE_SET:
2356         case MIB_NODE_SET_TRY:
2357                 /* None of these can be set */
2358                 if (errp)
2359                         *errp = SNMP_ERR_NOSUCHNAME;
2360                 return -1;
2361 
2362         case MIB_NODE_COMPARE:
2363                 pind->nas_index = subid;
2364                 return 0;
2365 
2366         case MIB_NODE_NEXT:
2367                 return  -1;
2368 
2369         case MIB_NODE_GET_SUBID:
2370                 return pind->nas_index;
2371 
2372         case MIB_NODE_RESET:
2373                 pind->nas_index = 1;
2374                 while ((nas = nas_lookup_index(pind->nas_index)) &&
2375                        (pind->port_no = stat_get_next_port_no(nas, 0)) == 0)
2376                         pind->nas_index++;
2377                 break;
2378         }
2379 
2380         return 0;
2381 }
2382 
2383 int
snmp_port_index2(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2384 snmp_port_index2(enum mib_node_cmd cmd, void *unused,
2385 		 subid_t subid, struct snmp_var **varp, int *errp)
2386 {
2387         grad_nas_t *nas;
2388         int index;
2389         struct snmp_var *var;
2390         struct port_data *pind = (struct port_data*)snmpserv_get_data();
2391 
2392         switch (cmd) {
2393         case MIB_NODE_GET:
2394                 if ((nas = nas_lookup_index(pind->nas_index)) == NULL ||
2395                     (index = stat_get_port_index(nas, pind->port_no)) == 0) {
2396                         *errp = SNMP_ERR_NOSUCHNAME;
2397                         return -1;
2398                 }
2399                 *errp = SNMP_ERR_NOERROR;
2400                 var = snmp_var_create((*varp)->name);
2401                 var->type = ASN_INTEGER;
2402                 var->val_length = sizeof(int);
2403                 var->var_int = index;
2404                 *varp = var;
2405                 break;
2406 
2407         case MIB_NODE_SET:
2408         case MIB_NODE_SET_TRY:
2409                 /* None of these can be set */
2410                 if (errp)
2411                         *errp = SNMP_ERR_NOSUCHNAME;
2412                 return -1;
2413 
2414         case MIB_NODE_COMPARE:
2415                 pind->port_no = subid;
2416                 return 0;
2417 
2418         case MIB_NODE_NEXT:
2419                 if ((nas = nas_lookup_index(pind->nas_index)) == NULL)
2420                         return -1;
2421                 index = stat_get_next_port_no(nas, pind->port_no);
2422                 if (index > 0) {
2423                         pind->port_no = index;
2424                         break;
2425                 }
2426                 /* move to next nas */
2427                 while ((nas = nas_lookup_index(++pind->nas_index)) &&
2428                        (pind->port_no = stat_get_next_port_no(nas, 0)) == 0)
2429                         ;
2430 
2431                 if (nas && pind->port_no > 0)
2432                         break;
2433 
2434                 return -1;
2435 
2436         case MIB_NODE_GET_SUBID:
2437                 return pind->port_no;
2438 
2439         case MIB_NODE_RESET:
2440                 break;
2441         }
2442 
2443         return 0;
2444 }
2445 
2446 struct snmp_var *snmp_port_get(subid_t subid, struct snmp_var *var, int *errp);
2447 void get_port_stat(PORT_STAT *port, struct snmp_var *var, subid_t key);
2448 
2449 int
snmp_port_table(enum mib_node_cmd cmd,void * unused,subid_t subid,struct snmp_var ** varp,int * errp)2450 snmp_port_table(enum mib_node_cmd cmd, void *unused,
2451 		subid_t subid, struct snmp_var **varp, int *errp)
2452 {
2453         struct port_table_data *p = (struct port_table_data*)
2454                                          snmpserv_get_data();
2455 
2456         switch (cmd) {
2457         case MIB_NODE_GET:
2458                 if ((*varp = snmp_port_get(subid, *varp, errp)) == NULL)
2459                         return -1;
2460                 break;
2461 
2462         case MIB_NODE_SET:
2463         case MIB_NODE_SET_TRY:
2464                 /* None of these can be set */
2465                 if (errp)
2466                         *errp = SNMP_ERR_NOSUCHNAME;
2467                 return -1;
2468 
2469         case MIB_NODE_COMPARE:
2470                 return 0;
2471 
2472         case MIB_NODE_NEXT:
2473                 if (findportbyindex(subid+1)) {
2474                         p->port_index = subid+1;
2475                         return 0;
2476                 }
2477                 return -1;
2478 
2479         case MIB_NODE_GET_SUBID:
2480                 return p->port_index;
2481 
2482         case MIB_NODE_RESET:
2483                 p->port_index = 1;
2484                 break;
2485 
2486         }
2487 
2488         return 0;
2489 }
2490 
2491 struct snmp_var *
snmp_port_get(subid_t subid,struct snmp_var * var,int * errp)2492 snmp_port_get(subid_t subid, struct snmp_var *var, int *errp)
2493 {
2494         struct snmp_var *ret;
2495         subid_t key;
2496         oid_t oid = var->name;
2497         PORT_STAT *port;
2498 
2499         ret = snmp_var_create(oid);
2500         *errp = SNMP_ERR_NOERROR;
2501 
2502         switch (key = SUBID(oid, OIDLEN(oid)-2)) {
2503 
2504         case MIB_KEY_StatPortNASIndex:
2505         case MIB_KEY_StatPortID:
2506         case MIB_KEY_StatPortFramedAddress:
2507         case MIB_KEY_StatPortTotalLogins:
2508         case MIB_KEY_StatPortStatus:
2509         case MIB_KEY_StatPortStatusChangeTimestamp:
2510         case MIB_KEY_StatPortUpTime:
2511         case MIB_KEY_StatPortLastLoginName:
2512         case MIB_KEY_StatPortLastLoginTimestamp:
2513         case MIB_KEY_StatPortLastLogoutTimestamp:
2514         case MIB_KEY_StatPortIdleTotalTime:
2515         case MIB_KEY_StatPortIdleMaxTime:
2516         case MIB_KEY_StatPortIdleMaxTimestamp:
2517         case MIB_KEY_StatPortInUseTotalTime:
2518         case MIB_KEY_StatPortInUseMaxTime:
2519         case MIB_KEY_StatPortInUseMaxTimestamp:
2520                 if (port = findportbyindex(subid)) {
2521                         get_port_stat(port, ret, key);
2522                         break;
2523                 }
2524                 /*FALLTHRU*/
2525 
2526         default:
2527                 *errp = SNMP_ERR_NOSUCHNAME;
2528                 snmp_var_free(ret);
2529                 return NULL;
2530         }
2531         return ret;
2532 }
2533 
2534 #define TDIFF(tv, time) (tv.tv_sec - time)*100 + tv.tv_usec/10000;
2535 
2536 void
get_port_stat(PORT_STAT * port,struct snmp_var * var,subid_t key)2537 get_port_stat(PORT_STAT *port, struct snmp_var *var, subid_t key)
2538 {
2539         struct timeval tv;
2540         struct timezone tz;
2541         grad_nas_t *nas;
2542 
2543         switch (key) {
2544 
2545         case MIB_KEY_StatPortNASIndex:
2546                 nas = grad_nas_lookup_ip(port->ip);
2547                 var->type = ASN_INTEGER;
2548                 var->val_length = sizeof(grad_counter_t);
2549                 if (nas && nas->app_data) {
2550                         struct nas_stat *nsp = nas->app_data;
2551                         var->var_int = nsp->index;
2552                 } else
2553                         var->var_int = 0;
2554                 break;
2555 
2556         case MIB_KEY_StatPortID:
2557                 var->type = ASN_INTEGER;
2558                 var->val_length = sizeof(grad_counter_t);
2559                 var->var_int = port->port_no;
2560                 break;
2561 
2562         case MIB_KEY_StatPortFramedAddress:
2563                 var->type = SMI_IPADDRESS;
2564                 var->val_length = sizeof(grad_uint32_t);
2565                 var->var_str = snmp_alloc(sizeof(grad_uint32_t));
2566                 *(grad_uint32_t*)var->var_str = port->framed_address;
2567                 break;
2568 
2569         case MIB_KEY_StatPortTotalLogins:
2570                 var->type = SMI_COUNTER32;
2571                 var->val_length = sizeof(grad_counter_t);
2572                 var->var_int = port->count;
2573                 break;
2574 
2575         case MIB_KEY_StatPortStatus:
2576                 var->type = ASN_INTEGER;
2577                 var->val_length = sizeof(grad_counter_t);
2578                 var->var_int = port->active ? port_active : port_idle;
2579                 break;
2580 
2581         case MIB_KEY_StatPortStatusChangeTimestamp:
2582                 var->type = ASN_INTEGER;
2583                 var->val_length = sizeof(int);
2584                 var->var_int = port->start;
2585                 break;
2586 
2587         case MIB_KEY_StatPortUpTime:
2588                 gettimeofday(&tv, &tz);
2589                 var->type = SMI_TIMETICKS;
2590                 var->val_length = sizeof(grad_counter_t);
2591                 var->var_int = TDIFF(tv, port->start);
2592                 break;
2593 
2594         case MIB_KEY_StatPortLastLoginName:
2595                 var->type = ASN_OCTET_STR;
2596                 var->val_length = strlen(port->login);
2597                 var->var_str = snmp_strdup(port->login);
2598                 break;
2599 
2600         case MIB_KEY_StatPortLastLoginTimestamp:
2601                 var->type = ASN_INTEGER;
2602                 var->val_length = sizeof(int);
2603                 var->var_int = port->lastin;
2604                 break;
2605 
2606         case MIB_KEY_StatPortLastLogoutTimestamp:
2607                 var->type = ASN_INTEGER;
2608                 var->val_length = sizeof(int);
2609                 var->var_int = port->lastout;
2610                 break;
2611 
2612         case MIB_KEY_StatPortIdleTotalTime:
2613                 var->type = SMI_TIMETICKS;
2614                 var->val_length = sizeof(grad_counter_t);
2615                 var->var_int = port->idle * 100;
2616                 break;
2617 
2618         case MIB_KEY_StatPortIdleMaxTime:
2619                 var->type = SMI_TIMETICKS;
2620                 var->val_length = sizeof(grad_counter_t);
2621                 var->var_int = port->maxidle.time * 100;
2622                 break;
2623 
2624         case MIB_KEY_StatPortIdleMaxTimestamp:
2625                 var->type = ASN_INTEGER;
2626                 var->val_length = sizeof(int);
2627                 var->var_int = port->maxidle.start;
2628                 break;
2629 
2630         case MIB_KEY_StatPortInUseTotalTime:
2631                 var->type = SMI_TIMETICKS;
2632                 var->val_length = sizeof(grad_counter_t);
2633                 var->var_int = port->inuse * 100;
2634                 break;
2635 
2636         case MIB_KEY_StatPortInUseMaxTime:
2637                 var->type = SMI_TIMETICKS;
2638                 var->val_length = sizeof(grad_counter_t);
2639                 var->var_int = port->maxinuse.time * 100;
2640                 break;
2641 
2642         case MIB_KEY_StatPortInUseMaxTimestamp:
2643                 var->type = ASN_INTEGER;
2644                 var->val_length = sizeof(int);
2645                 var->var_int = port->maxinuse.start;
2646                 break;
2647         }
2648 }
2649 
2650 grad_nas_t *
nas_lookup_index(int ind)2651 nas_lookup_index(int ind)
2652 {
2653         grad_nas_t *nas;
2654 	grad_iterator_t *itr = grad_nas_iterator();
2655         struct nas_stat *ns;
2656 
2657         for (nas = grad_iterator_first(itr); nas; nas = grad_iterator_next(itr)) {
2658                 ns = nas->app_data;
2659                 if (ns && ns->index == ind)
2660                         break;
2661         }
2662 	grad_iterator_destroy(&itr);
2663         return nas;
2664 }
2665 
2666 
2667 /* *********************** SNMP Protocol Interface ************************* */
2668 
2669 /* Decode the SNMP request */
2670 static int
snmp_decode(SNMP_REQ * req,u_char * buf,size_t len)2671 snmp_decode(SNMP_REQ *req, u_char *buf, size_t len)
2672 {
2673         struct snmp_pdu *pdu;
2674         struct snmp_session sess;
2675         int access;
2676         char comm[128];
2677         int comm_len;
2678         char ipbuf[GRAD_IPV4_STRING_LENGTH];
2679 
2680         log_open(GRAD_LOG_SNMP);
2681 
2682         if ((pdu = snmp_pdu_create(0)) == NULL) {
2683                 grad_log(GRAD_LOG_ERR,
2684                          _("can't create SNMP PDU: %s"),
2685                          snmp_strerror(snmp_errno));
2686                 return -1;
2687         }
2688         comm_len = sizeof(comm);
2689         if (snmp_decode_request(&sess, pdu, buf, len, comm, &comm_len)) {
2690                 grad_log(GRAD_LOG_ERR,
2691                          _("can't decode SNMP packet from %s: %s"),
2692 		         grad_ip_iptostr(ntohl(req->addr.sin_addr.s_addr),
2693 				         ipbuf),
2694 		         snmp_strerror(snmp_errno));
2695                 return -1;
2696         }
2697 
2698         access = check_acl(req->addr.sin_addr.s_addr, comm);
2699         if (!access) {
2700                 grad_log(GRAD_LOG_NOTICE,
2701                          _("DENIED attempt to access community %s from %s"),
2702                          comm,
2703                          grad_ip_iptostr(ntohl(req->addr.sin_addr.s_addr),
2704                                          ipbuf));
2705                 return 1;
2706         }
2707         req->pdu = pdu;
2708         req->community = grad_estrdup(comm);
2709         req->access = access;
2710         return 0;
2711 }
2712 
2713 int
snmp_req_decode(const struct sockaddr_in * srv_sa,const struct sockaddr_in * clt_sa,void * input,size_t inputsize,void ** output)2714 snmp_req_decode(const struct sockaddr_in *srv_sa,
2715 		const struct sockaddr_in *clt_sa,
2716 		void *input, size_t inputsize, void **output)
2717 {
2718         SNMP_REQ *req;
2719 
2720 	req = grad_emalloc(sizeof *req);
2721 	req->addr = *clt_sa;
2722         if (snmp_decode(req, input, inputsize)) {
2723                 grad_free(req);
2724                 return 1;
2725         }
2726 	*output = req;
2727 	return 0;
2728 }
2729 
2730 int
snmp_req_cmp(void * ap,void * bp)2731 snmp_req_cmp(void *ap, void *bp)
2732 {
2733         SNMP_REQ *a = ap, *b = bp;
2734         return (a->addr.sin_addr.s_addr == b->addr.sin_addr.s_addr &&
2735 		a->pdu->req_id == b->pdu->req_id) ? RCMP_EQ : RCMP_NE;
2736 }
2737 
2738 /* Free the SNMP request */
2739 void
snmp_req_free(void * ptr)2740 snmp_req_free(void *ptr)
2741 {
2742         SNMP_REQ *req = ptr;
2743         snmp_pdu_free(req->pdu);
2744         grad_free(req->community);
2745         grad_free(req);
2746 }
2747 
2748 void
snmp_req_drop(int type,void * data,void * orig_data,int fd,const char * status_str)2749 snmp_req_drop(int type, void *data, void *orig_data,
2750 	      int fd, const char *status_str)
2751 {
2752         SNMP_REQ *req = data ? data : orig_data;
2753         char ipbuf[GRAD_IPV4_STRING_LENGTH];
2754 
2755         grad_log(GRAD_LOG_NOTICE,
2756                  _("Dropping SNMP request from client %s: %s"),
2757                  grad_ip_iptostr(ntohl(req->addr.sin_addr.s_addr), ipbuf),
2758                  status_str);
2759 }
2760 
2761 static u_char send_buffer[RAD_BUFFER_SIZE];
2762 
2763 int
snmp_req_respond(REQUEST * request)2764 snmp_req_respond(REQUEST *request)
2765 {
2766 	SNMP_REQ *req = request->data;
2767 	struct snmp_session session;
2768         struct snmp_pdu *pdu;
2769         int len;
2770 
2771         pdu = snmp_agent_response(req->pdu, req->access);
2772         if (pdu) {
2773                 session.version = SNMP_VERSION_1;
2774                 session.community.str = req->community;
2775                 session.community.len = strlen(req->community);
2776                 len = sizeof(send_buffer);
2777                 if (snmp_encode_request(&session, pdu, send_buffer, &len)==0) {
2778                         sendto(request->fd,
2779                                send_buffer, len,
2780                                0, (struct sockaddr *) &request->addr,
2781                                sizeof(request->addr));
2782                 }
2783                 snmp_pdu_free(pdu);
2784         }
2785         return 0;
2786 }
2787 
2788 #endif
2789 
2790 
2791 
2792 
2793 
2794