1 /*
2 * Smux module authored by Rohit Dube.
3 * Rewritten by Nick Amato <naamato@merit.net>.
4 */
5
6 #include <net-snmp/net-snmp-config.h>
7 #include <net-snmp/net-snmp-features.h>
8 #include <sys/types.h>
9 #include <ctype.h>
10
11 #if HAVE_IO_H /* win32 */
12 #include <io.h>
13 #endif
14 #include <stdio.h>
15 #if HAVE_STDLIB_H
16 #include <stdlib.h>
17 #endif
18 #if HAVE_STRING_H
19 #include <string.h>
20 #else
21 #include <strings.h>
22 #endif
23 #if HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #if HAVE_ERR_H
27 #include <err.h>
28 #endif
29 #if TIME_WITH_SYS_TIME
30 # include <sys/time.h>
31 # include <time.h>
32 #else
33 # if HAVE_SYS_TIME_H
34 # include <sys/time.h>
35 # else
36 # include <time.h>
37 # endif
38 #endif
39 #include <errno.h>
40 #if HAVE_NETDB_H
41 #include <netdb.h>
42 #endif
43
44 #include <sys/stat.h>
45 #if HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
47 #endif
48 #if HAVE_SYS_FILIO_H
49 #include <sys/filio.h>
50 #endif
51
52 #if HAVE_NETINET_IN_H
53 #include <netinet/in.h>
54 #endif
55
56 #if HAVE_ARPA_INET_H
57 #include <arpa/inet.h>
58 #endif
59
60 #if HAVE_SYS_IOCTL_H
61 #include <sys/ioctl.h>
62 #endif
63
64 #include <net-snmp/net-snmp-includes.h>
65 #include <net-snmp/agent/net-snmp-agent-includes.h>
66 #include <net-snmp/library/tools.h>
67
68 #include "smux.h"
69 #include "snmpd.h"
70
71 netsnmp_feature_require(snprint_objid);
72
73 long smux_long;
74 u_long smux_ulong;
75 struct sockaddr_in smux_sa;
76 struct counter64 smux_counter64;
77 oid smux_objid[MAX_OID_LEN];
78 u_char smux_str[SMUXMAXSTRLEN];
79 int smux_listen_sd = -1;
80
81 static struct timeval smux_rcv_timeout;
82 static long smux_reqid;
83
84 void init_smux(void);
85 static u_char *smux_open_process(int, u_char *, size_t *, int *);
86 static u_char *smux_rreq_process(int, u_char *, size_t *);
87 static u_char *smux_close_process(int, u_char *, size_t *);
88 static u_char *smux_trap_process(u_char *, size_t *);
89 static u_char *smux_parse(u_char *, oid *, size_t *, size_t *, u_char *);
90 static u_char *smux_parse_var(u_char *, size_t *, oid *, size_t *,
91 size_t *, u_char *);
92 static void smux_send_close(int, int);
93 static void smux_list_detach(smux_reg **, smux_reg *);
94 static void smux_replace_active(smux_reg *, smux_reg *);
95 static void smux_peer_cleanup(int);
96 static int smux_auth_peer(oid *, size_t, char *, int);
97 static int smux_build(u_char, long, oid *,
98 size_t *, u_char, u_char *, size_t, u_char *,
99 size_t *);
100 static int smux_list_add(smux_reg **, smux_reg *);
101 static int smux_pdu_process(int, u_char *, size_t);
102 static int smux_send_rrsp(int, int);
103 static smux_reg *smux_find_match(smux_reg *, int, oid *, size_t, long);
104 static smux_reg *smux_find_replacement(oid *, size_t);
105 u_char *var_smux_get(oid *, size_t, oid *, size_t *, int, size_t *,
106 u_char *);
107 int var_smux_write(int, u_char *, u_char, size_t, oid *, size_t);
108
109 static smux_reg *ActiveRegs; /* Active registrations */
110 static smux_reg *PassiveRegs; /* Currently unused registrations */
111
112 static smux_peer_auth *Auths[SMUX_MAX_PEERS]; /* Configured peers */
113 static int nauths, npeers = 0;
114
115
116
117 void
smux_parse_smux_socket(const char * token,char * cptr)118 smux_parse_smux_socket(const char *token, char *cptr)
119 {
120 DEBUGMSGTL(("smux", "port spec: %s\n", cptr));
121 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_SMUX_SOCKET, cptr);
122 }
123
124 void
smux_parse_peer_auth(const char * token,char * cptr)125 smux_parse_peer_auth(const char *token, char *cptr)
126 {
127 smux_peer_auth *aptr;
128 char *password_cptr;
129 int rv;
130
131 if ((aptr =
132 (smux_peer_auth *) calloc(1, sizeof(smux_peer_auth))) == NULL) {
133 snmp_log_perror("smux_parse_peer_auth: malloc");
134 return;
135 }
136 if (nauths == SMUX_MAX_PEERS) {
137 config_perror("Too many smuxpeers");
138 free(aptr);
139 return;
140 }
141
142 password_cptr = strchr(cptr, ' ');
143 if (password_cptr)
144 *(password_cptr++) = '\0';
145
146 /*
147 * oid
148 */
149 aptr->sa_active_fd = -1;
150 aptr->sa_oid_len = MAX_OID_LEN;
151 rv = read_objid( cptr, aptr->sa_oid, &aptr->sa_oid_len );
152 DEBUGMSGTL(("smux_conf", "parsing registration for: %s\n", cptr));
153 if (!rv)
154 config_perror("Error parsing smux oid");
155
156 if (password_cptr != NULL) { /* Do we have a password or not? */
157 DEBUGMSGTL(("smux_conf", "password is: %s\n",
158 SNMP_STRORNULL(password_cptr)));
159
160 /*
161 * password
162 */
163 if (*password_cptr)
164 strlcpy(aptr->sa_passwd, password_cptr, sizeof(aptr->sa_passwd));
165 } else {
166 /*
167 * null passwords OK
168 */
169 DEBUGMSGTL(("smux_conf", "null password\n"));
170 }
171
172 Auths[nauths++] = aptr;
173 return;
174 }
175
176 void
smux_free_peer_auth(void)177 smux_free_peer_auth(void)
178 {
179 int i;
180
181 for (i = 0; i < nauths; i++) {
182 free(Auths[i]);
183 Auths[i] = NULL;
184 }
185 nauths = 0;
186 }
187
188 void
init_smux(void)189 init_smux(void)
190 {
191 snmpd_register_config_handler("smuxpeer", smux_parse_peer_auth,
192 smux_free_peer_auth,
193 "OID-IDENTITY PASSWORD");
194 snmpd_register_config_handler("smuxsocket",
195 smux_parse_smux_socket, NULL,
196 "SMUX bind address");
197 }
198
199 void
real_init_smux(void)200 real_init_smux(void)
201 {
202 struct sockaddr_in lo_socket;
203 char *smux_socket;
204 int one = 1;
205
206 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
207 smux_listen_sd = -1;
208 return;
209 }
210
211 /*
212 * Reqid
213 */
214 smux_reqid = 0;
215 smux_listen_sd = -1;
216
217 /*
218 * Receive timeout
219 */
220 smux_rcv_timeout.tv_sec = 0;
221 smux_rcv_timeout.tv_usec = 500000;
222
223 /*
224 * Get ready to listen on the SMUX port
225 */
226 memset(&lo_socket, (0), sizeof(lo_socket));
227 lo_socket.sin_family = AF_INET;
228
229 smux_socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
230 NETSNMP_DS_SMUX_SOCKET);
231 #ifdef NETSNMP_ENABLE_LOCAL_SMUX
232 if (!smux_socket)
233 smux_socket = "127.0.0.1"; /* By default, listen on localhost only */
234 #endif
235 netsnmp_sockaddr_in( &lo_socket, smux_socket, SMUXPORT );
236
237 if ((smux_listen_sd = (int) socket(AF_INET, SOCK_STREAM, 0)) < 0) {
238 snmp_log_perror("[init_smux] socket failed");
239 return;
240 }
241 #ifdef SO_REUSEADDR
242 /*
243 * At least on Linux, when the master agent terminates, any
244 * TCP connections for SMUX peers are put in the TIME_WAIT
245 * state for about 60 seconds. If the master agent is started
246 * during this time, the bind for the listening socket will
247 * fail because the SMUX port is in use.
248 */
249 if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
250 sizeof(one)) < 0) {
251 snmp_log_perror("[init_smux] setsockopt(SO_REUSEADDR) failed");
252 }
253 #endif /* SO_REUSEADDR */
254
255 if (bind(smux_listen_sd, (struct sockaddr *) &lo_socket,
256 sizeof(lo_socket)) < 0) {
257 snmp_log_perror("[init_smux] bind failed");
258 close(smux_listen_sd);
259 smux_listen_sd = -1;
260 return;
261 }
262 #ifdef SO_KEEPALIVE
263 if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
264 sizeof(one)) < 0) {
265 snmp_log_perror("[init_smux] setsockopt(SO_KEEPALIVE) failed");
266 close(smux_listen_sd);
267 smux_listen_sd = -1;
268 return;
269 }
270 #endif /* SO_KEEPALIVE */
271
272 if (listen(smux_listen_sd, SOMAXCONN) == -1) {
273 snmp_log_perror("[init_smux] listen failed");
274 close(smux_listen_sd);
275 smux_listen_sd = -1;
276 return;
277 }
278
279 DEBUGMSGTL(("smux_init",
280 "[smux_init] done; smux listen sd is %d, smux port is %d\n",
281 smux_listen_sd, ntohs(lo_socket.sin_port)));
282 }
283
284 static int
smux_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)285 smux_handler(netsnmp_mib_handler *handler,
286 netsnmp_handler_registration *reginfo,
287 netsnmp_agent_request_info *reqinfo,
288 netsnmp_request_info *requests)
289 {
290 u_char *access = NULL;
291 size_t var_len;
292 int exact = 1;
293 int status = 0;
294 u_char var_type;
295 static long old_reqid = -1;
296 static long old_sessid = -1;
297 long new_reqid, new_sessid;
298
299 /* Increment the reqid of outgoing SMUX messages only when processing
300 * new incoming SNMP message, i.e. when reqid or session id chamges */
301 new_reqid = reqinfo->asp->pdu->reqid;
302 new_sessid = reqinfo->asp->session->sessid;
303 DEBUGMSGTL(("smux", "smux_handler: incoming reqid=%ld, sessid=%ld\n",
304 new_reqid, new_sessid));
305 if (old_reqid != new_reqid || old_sessid != new_sessid) {
306 smux_reqid++;
307 old_reqid = new_reqid;
308 old_sessid = new_sessid;
309 }
310
311 switch (reqinfo->mode) {
312 case MODE_GETNEXT:
313 case MODE_GETBULK:
314 exact = 0;
315 }
316
317 for (; requests; requests = requests->next) {
318 switch(reqinfo->mode) {
319 case MODE_GET:
320 case MODE_GETNEXT:
321 case MODE_SET_RESERVE1:
322 access = var_smux_get(reginfo->rootoid,
323 reginfo->rootoid_len,
324 requests->requestvb->name,
325 &requests->requestvb->name_length,
326 exact,
327 &var_len,
328 &var_type);
329 if (access)
330 if (reqinfo->mode != MODE_SET_RESERVE1)
331 snmp_set_var_typed_value(requests->requestvb,
332 var_type, access, var_len);
333 if (reqinfo->mode != MODE_SET_RESERVE1)
334 break;
335 /* fall through if MODE_SET_RESERVE1 */
336 /* FALL THROUGH */
337
338 default:
339 /* SET processing */
340 status = var_smux_write(reqinfo->mode,
341 requests->requestvb->val.string,
342 requests->requestvb->type,
343 requests->requestvb->val_len,
344 requests->requestvb->name,
345 requests->requestvb->name_length);
346 if (status != SNMP_ERR_NOERROR) {
347 netsnmp_set_request_error(reqinfo, requests, status);
348 }
349 }
350 }
351 return SNMP_ERR_NOERROR;
352 }
353
354 u_char *
var_smux_get(oid * root,size_t root_len,oid * name,size_t * length,int exact,size_t * var_len,u_char * var_type)355 var_smux_get(oid *root, size_t root_len,
356 oid * name, size_t * length,
357 int exact, size_t * var_len, u_char *var_type)
358 {
359 u_char *valptr;
360 smux_reg *rptr;
361
362 /*
363 * search the active registration list
364 */
365 for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
366 if (0 >= snmp_oidtree_compare(root, root_len, rptr->sr_name,
367 rptr->sr_name_len))
368 break;
369 }
370 if (rptr == NULL)
371 return NULL;
372 else if (exact && (*length < rptr->sr_name_len))
373 return NULL;
374
375 valptr = smux_snmp_process(exact, name, length,
376 var_len, var_type, rptr->sr_fd);
377
378 if (valptr == NULL)
379 return NULL;
380
381 if ((snmp_oidtree_compare(name, *length, rptr->sr_name,
382 rptr->sr_name_len)) != 0) {
383 /*
384 * the peer has returned a value outside
385 * * of the registered tree
386 */
387 return NULL;
388 } else {
389 return valptr;
390 }
391 }
392
393 int
var_smux_write(int action,u_char * var_val,u_char var_val_type,size_t var_val_len,oid * name,size_t name_len)394 var_smux_write(int action,
395 u_char * var_val,
396 u_char var_val_type,
397 size_t var_val_len,
398 oid * name, size_t name_len)
399 {
400 smux_reg *rptr;
401 u_char buf[SMUXMAXPKTSIZE], *ptr, sout[3], type;
402 int reterr;
403 size_t var_len, datalen, name_length, packet_len;
404 size_t len;
405 ssize_t tmp_len;
406 long reqid, errsts, erridx;
407 u_char *dataptr;
408
409 DEBUGMSGTL(("smux", "[var_smux_write] entering var_smux_write\n"));
410
411 len = SMUXMAXPKTSIZE;
412 reterr = SNMP_ERR_NOERROR;
413 var_len = var_val_len;
414 name_length = name_len;
415
416 /*
417 * XXX find the descriptor again
418 */
419 for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
420 if (!snmp_oidtree_compare(name, name_len, rptr->sr_name,
421 rptr->sr_name_len))
422 break;
423 }
424
425 if (!rptr) {
426 DEBUGMSGTL(("smux", "[var_smux_write] unknown registration\n"));
427 return SNMP_ERR_GENERR;
428 }
429
430 switch (action) {
431 case RESERVE1:
432 DEBUGMSGTL(("smux", "[var_smux_write] entering RESERVE1\n"));
433
434 /*
435 * length might be long
436 */
437 var_len += (*(var_val + 1) & ASN_LONG_LEN) ?
438 var_len + ((*(var_val + 1) & 0x7F) + 2) : 2;
439
440 switch (var_val_type) {
441 case ASN_INTEGER:
442 case ASN_OCTET_STR:
443 case ASN_COUNTER:
444 case ASN_GAUGE:
445 case ASN_TIMETICKS:
446 case ASN_UINTEGER:
447 case ASN_COUNTER64:
448 case ASN_IPADDRESS:
449 case ASN_OPAQUE:
450 case ASN_NSAP:
451 case ASN_OBJECT_ID:
452 case ASN_BIT_STR:
453 datalen = var_val_len;
454 dataptr = var_val;
455 break;
456 case SNMP_NOSUCHOBJECT:
457 case SNMP_NOSUCHINSTANCE:
458 case SNMP_ENDOFMIBVIEW:
459 case ASN_NULL:
460 default:
461 DEBUGMSGTL(("smux",
462 "[var_smux_write] variable not supported\n"));
463 return SNMP_ERR_GENERR;
464 break;
465 }
466
467 if ((smux_build((u_char) SMUX_SET, smux_reqid,
468 name, &name_length, var_val_type, dataptr,
469 datalen, buf, &len)) < 0) {
470 DEBUGMSGTL(("smux", "[var_smux_write] smux build failed\n"));
471 return SNMP_ERR_GENERR;
472 }
473
474 if (sendto(rptr->sr_fd, (void *) buf, len, 0, NULL, 0) < 0) {
475 DEBUGMSGTL(("smux", "[var_smux_write] send failed\n"));
476 return SNMP_ERR_GENERR;
477 }
478
479 while (1) {
480 /*
481 * peek at what's received
482 */
483 if ((len = recvfrom(rptr->sr_fd, (void *) buf,
484 SMUXMAXPKTSIZE, MSG_PEEK, NULL, NULL)) <= 0) {
485 if ((len == -1) && ((errno == EINTR) || (errno == EAGAIN)))
486 {
487 continue;
488 }
489 DEBUGMSGTL(("smux",
490 "[var_smux_write] peek failed or timed out\n"));
491 /*
492 * do we need to do a peer cleanup in this case??
493 */
494 smux_peer_cleanup(rptr->sr_fd);
495 smux_snmp_select_list_del(rptr->sr_fd);
496 return SNMP_ERR_GENERR;
497 }
498
499 DEBUGMSGTL(("smux", "[var_smux_write] Peeked at %" NETSNMP_PRIz
500 "d bytes\n", len));
501 DEBUGDUMPSETUP("var_smux_write", buf, len);
502
503 /*
504 * determine if we received more than one packet
505 */
506 packet_len = len;
507 ptr = asn_parse_header(buf, &packet_len, &type);
508 if (ptr == NULL)
509 return SNMP_ERR_GENERR;
510 packet_len += (ptr - buf);
511 if (len > (ssize_t)packet_len) {
512 /*
513 * set length to receive only the first packet
514 */
515 len = packet_len;
516 }
517
518 /*
519 * receive the first packet
520 */
521 tmp_len = len;
522 do
523 {
524 len = tmp_len;
525 len = recvfrom(rptr->sr_fd, (void *) buf, len, 0, NULL, NULL);
526 }
527 while((len == -1) && ((errno == EINTR) || (errno == EAGAIN)));
528
529 if (len <= 0) {
530 DEBUGMSGTL(("smux",
531 "[var_smux_write] recv failed or timed out\n"));
532 smux_peer_cleanup(rptr->sr_fd);
533 smux_snmp_select_list_del(rptr->sr_fd);
534 return SNMP_ERR_GENERR;
535 }
536
537 DEBUGMSGTL(("smux", "[var_smux_write] Received %" NETSNMP_PRIz
538 "d bytes\n", len));
539
540 if (buf[0] == SMUX_TRAP) {
541 DEBUGMSGTL(("smux", "[var_smux_write] Received trap\n"));
542 DEBUGMSGTL(("smux", "Got trap from peer on fd %d\n",
543 rptr->sr_fd));
544 ptr = asn_parse_header(buf, &len, &type);
545 if (ptr == NULL)
546 return SNMP_ERR_GENERR;
547 smux_trap_process(ptr, &len);
548
549
550 /*
551 * go and peek at received data again
552 */
553 /*
554 * we could receive the reply or another trap
555 */
556 } else {
557 ptr = buf;
558 ptr = asn_parse_header(ptr, &len, &type);
559 if ((ptr == NULL) || type != SNMP_MSG_RESPONSE)
560 return SNMP_ERR_GENERR;
561
562 ptr =
563 asn_parse_int(ptr, &len, &type, &reqid, sizeof(reqid));
564 if ((ptr == NULL) || type != ASN_INTEGER)
565 return SNMP_ERR_GENERR;
566
567 ptr =
568 asn_parse_int(ptr, &len, &type, &errsts,
569 sizeof(errsts));
570 if ((ptr == NULL) || type != ASN_INTEGER)
571 return SNMP_ERR_GENERR;
572
573 if (errsts) {
574 DEBUGMSGTL(("smux",
575 "[var_smux_write] errsts returned\n"));
576 return (errsts);
577 }
578
579 ptr =
580 asn_parse_int(ptr, &len, &type, &erridx,
581 sizeof(erridx));
582 if ((ptr == NULL) || type != ASN_INTEGER)
583 return SNMP_ERR_GENERR;
584
585 reterr = SNMP_ERR_NOERROR;
586 break;
587 }
588 } /* while (1) */
589 break; /* case Action == RESERVE1 */
590
591 case RESERVE2:
592 DEBUGMSGTL(("smux", "[var_smux_write] entering RESERVE2\n"));
593 reterr = SNMP_ERR_NOERROR;
594 break; /* case Action == RESERVE2 */
595
596 case FREE:
597 case COMMIT:
598 ptr = sout;
599 *(ptr++) = (u_char) SMUX_SOUT;
600 *(ptr++) = (u_char) 1;
601 if (action == FREE) {
602 *ptr = (u_char) 1; /* rollback */
603 DEBUGMSGTL(("smux",
604 "[var_smux_write] entering FREE - sending RollBack \n"));
605 } else {
606 *ptr = (u_char) 0; /* commit */
607 DEBUGMSGTL(("smux",
608 "[var_smux_write] entering FREE - sending Commit \n"));
609 }
610
611 if ((sendto(rptr->sr_fd, (void *) sout, 3, 0, NULL, 0)) < 0) {
612 DEBUGMSGTL(("smux",
613 "[var_smux_write] send rollback/commit failed\n"));
614 return SNMP_ERR_GENERR;
615 }
616
617 reterr = SNMP_ERR_NOERROR;
618 break; /* case Action == COMMIT */
619
620 default:
621 break;
622 }
623 return reterr;
624 }
625
626
627 int
smux_accept(int sd)628 smux_accept(int sd)
629 {
630 u_char data[SMUXMAXPKTSIZE], *ptr, type;
631 struct sockaddr_in in_socket;
632 struct timeval tv;
633 int fail, fd;
634 socklen_t alen;
635 int length;
636 size_t len;
637
638 alen = sizeof(struct sockaddr_in);
639 /*
640 * this may be too high
641 */
642 tv.tv_sec = 5;
643 tv.tv_usec = 0;
644
645 /*
646 * connection request
647 */
648 DEBUGMSGTL(("smux", "[smux_accept] Calling accept()\n"));
649 errno = 0;
650 if ((fd = (int) accept(sd, (struct sockaddr *) &in_socket, &alen)) < 0) {
651 snmp_log_perror("[smux_accept] accept failed");
652 return -1;
653 } else {
654 DEBUGMSGTL(("smux", "[smux_accept] accepted fd %d from %s:%d\n",
655 fd, inet_ntoa(in_socket.sin_addr),
656 ntohs(in_socket.sin_port)));
657 if (npeers + 1 == SMUXMAXPEERS) {
658 snmp_log(LOG_ERR,
659 "[smux_accept] denied peer on fd %d, limit %d reached",
660 fd, SMUXMAXPEERS);
661 close(fd);
662 return -1;
663 }
664
665 /*
666 * now block for an OpenPDU
667 */
668 do
669 {
670 length = recvfrom(fd, (char *) data, SMUXMAXPKTSIZE, 0, NULL, NULL);
671 }
672 while((length == -1) && ((errno == EINTR) || (errno == EAGAIN)));
673
674 if (length <= 0) {
675 DEBUGMSGTL(("smux",
676 "[smux_accept] peer on fd %d died or timed out\n",
677 fd));
678 close(fd);
679 return -1;
680 }
681 /*
682 * try to authorize him
683 */
684 ptr = data;
685 len = length;
686 if ((ptr = asn_parse_header(ptr, &len, &type)) == NULL) {
687 smux_send_close(fd, SMUXC_PACKETFORMAT);
688 close(fd);
689 DEBUGMSGTL(("smux", "[smux_accept] peer on %d sent bad open", fd));
690 return -1;
691 } else if (type != (u_char) SMUX_OPEN) {
692 smux_send_close(fd, SMUXC_PROTOCOLERROR);
693 close(fd);
694 DEBUGMSGTL(("smux",
695 "[smux_accept] peer on %d did not send open: (%d)\n",
696 fd, type));
697 return -1;
698 }
699 ptr = smux_open_process(fd, ptr, &len, &fail);
700 if (fail) {
701 smux_send_close(fd, SMUXC_AUTHENTICATIONFAILURE);
702 close(fd);
703 DEBUGMSGTL(("smux",
704 "[smux_accept] peer on %d failed authentication\n",
705 fd));
706 return -1;
707 }
708
709 /*
710 * he's OK
711 */
712 #ifdef SO_RCVTIMEO
713 if (setsockopt
714 (fd, SOL_SOCKET, SO_RCVTIMEO, (void *) &tv, sizeof(tv)) < 0) {
715 DEBUGMSGTL(("smux",
716 "[smux_accept] setsockopt(SO_RCVTIMEO) failed fd %d\n",
717 fd));
718 snmp_log_perror("smux_accept: setsockopt SO_RCVTIMEO");
719 }
720 #endif
721 npeers++;
722 DEBUGMSGTL(("smux", "[smux_accept] fd %d\n", fd));
723
724 /*
725 * Process other PDUs already read, e.g. a registerRequest.
726 */
727 len = length - (ptr - data);
728 if (smux_pdu_process(fd, ptr, len) < 0) {
729 /*
730 * Easy come, easy go. Clean-up is already done.
731 */
732 return -1;
733 }
734 }
735 return fd;
736 }
737
738 int
smux_process(int fd)739 smux_process(int fd)
740 {
741 int length, tmp_length;
742 u_char data[SMUXMAXPKTSIZE];
743 u_char type, *ptr;
744 size_t packet_len;
745
746 do
747 {
748 length = recvfrom(fd, (char *) data, SMUXMAXPKTSIZE, MSG_PEEK, NULL,
749 NULL);
750 }
751 while((length == -1) && ((errno == EINTR) || (errno == EAGAIN)));
752
753 if (length <= 0)
754 {
755 if (length < 0)
756 snmp_log_perror("[smux_process] peek failed");
757 smux_peer_cleanup(fd);
758 return -1;
759 }
760
761 /*
762 * determine if we received more than one packet
763 */
764 packet_len = length;
765 ptr = asn_parse_header(data, &packet_len, &type);
766 if (ptr == NULL)
767 return -1;
768 packet_len += (ptr - data);
769 if (length > packet_len) {
770 /*
771 * set length to receive only the first packet
772 */
773 length = packet_len;
774 }
775
776 tmp_length = length;
777 do
778 {
779 length = tmp_length;
780 length = recvfrom(fd, (char *) data, length, 0, NULL, NULL);
781 }
782 while((length == -1) && ((errno == EINTR) || (errno == EAGAIN)));
783
784 if (length <= 0) {
785 /*
786 * the peer went away, close this descriptor
787 * * and delete it from the list
788 */
789 DEBUGMSGTL(("smux",
790 "[smux_process] peer on fd %d died or timed out\n",
791 fd));
792 smux_peer_cleanup(fd);
793 return -1;
794 }
795
796 return smux_pdu_process(fd, data, length);
797 }
798
799 static int
smux_pdu_process(int fd,u_char * data,size_t length)800 smux_pdu_process(int fd, u_char * data, size_t length)
801 {
802 int error;
803 size_t len;
804 u_char *ptr, type;
805
806 DEBUGMSGTL(("smux", "[smux_pdu_process] Processing %" NETSNMP_PRIz
807 "d bytes\n", length));
808
809 error = 0;
810 ptr = data;
811 while (error == 0 && ptr != NULL && ptr < data + length) {
812 len = length - (ptr - data);
813 ptr = asn_parse_header(ptr, &len, &type);
814 if (ptr == NULL) {
815 DEBUGMSGTL(("smux", "[smux_pdu_process] cannot parse header\n"));
816 break;
817 }
818 DEBUGMSGTL(("smux", "[smux_pdu_process] type is %d\n",
819 (int) type));
820 switch (type) {
821 case SMUX_OPEN:
822 smux_send_close(fd, SMUXC_PROTOCOLERROR);
823 DEBUGMSGTL(("smux",
824 "[smux_pdu_process] peer on fd %d sent duplicate open?\n",
825 fd));
826 smux_peer_cleanup(fd);
827 error = -1;
828 break;
829 case SMUX_CLOSE:
830 ptr = smux_close_process(fd, ptr, &len);
831 smux_peer_cleanup(fd);
832 error = -1;
833 break;
834 case SMUX_RREQ:
835 ptr = smux_rreq_process(fd, ptr, &len);
836 break;
837 case SMUX_RRSP:
838 error = -1;
839 smux_send_close(fd, SMUXC_PROTOCOLERROR);
840 smux_peer_cleanup(fd);
841 DEBUGMSGTL(("smux",
842 "[smux_pdu_process] peer on fd %d sent RRSP!\n",
843 fd));
844 break;
845 case SMUX_SOUT:
846 error = -1;
847 smux_send_close(fd, SMUXC_PROTOCOLERROR);
848 smux_peer_cleanup(fd);
849 DEBUGMSGTL(("smux", "This shouldn't have happened!\n"));
850 break;
851 case SMUX_TRAP:
852 DEBUGMSGTL(("smux", "Got trap from peer on fd %d\n", fd));
853 if (ptr)
854 {
855 DEBUGMSGTL(("smux", "[smux_pdu_process] call smux_trap_process.\n"));
856 ptr = smux_trap_process(ptr, &len);
857 }
858 else
859 {
860 DEBUGMSGTL(("smux", "[smux_pdu_process] smux_trap_process not called: ptr=NULL.\n"));
861 DEBUGMSGTL(("smux", "[smux_pdu_process] Error: \n%s\n", snmp_api_errstring(0)));
862 }
863 /*
864 * watch out for close on top of this...should return correct end
865 */
866 break;
867 default:
868 smux_send_close(fd, SMUXC_PACKETFORMAT);
869 smux_peer_cleanup(fd);
870 DEBUGMSGTL(("smux", "[smux_pdu_process] Wrong type %d\n",
871 (int) type));
872 error = -1;
873 break;
874 }
875 }
876 return error;
877 }
878
879 static u_char *
smux_open_process(int fd,u_char * ptr,size_t * len,int * fail)880 smux_open_process(int fd, u_char * ptr, size_t * len, int *fail)
881 {
882 u_char type;
883 long version;
884 oid oid_name[MAX_OID_LEN];
885 char passwd[SMUXMAXSTRLEN];
886 char descr[SMUXMAXSTRLEN];
887 char oid_print[SMUXMAXSTRLEN];
888 int i;
889 size_t oid_name_len, string_len;
890
891 if (!(ptr = asn_parse_int(ptr, len, &type, &version, sizeof(version)))) {
892 DEBUGMSGTL(("smux", "[smux_open_process] version parse failed\n"));
893 *fail = TRUE;
894 return ((ptr += *len));
895 }
896 DEBUGMSGTL(("smux",
897 "[smux_open_process] version %ld, len %" NETSNMP_PRIz
898 "u, type %d\n", version, *len, (int) type));
899
900 oid_name_len = MAX_OID_LEN;
901 if ((ptr = asn_parse_objid(ptr, len, &type, oid_name,
902 &oid_name_len)) == NULL) {
903 DEBUGMSGTL(("smux", "[smux_open_process] oid parse failed\n"));
904 *fail = TRUE;
905 return ((ptr += *len));
906 }
907 snprint_objid(oid_print, sizeof(oid_print), oid_name, oid_name_len);
908
909 if (snmp_get_do_debugging()) {
910 DEBUGMSGTL(("smux", "[smux_open_process] smux peer: %s\n",
911 oid_print));
912 DEBUGMSGTL(("smux", "[smux_open_process] len %" NETSNMP_PRIz
913 "u, type %d\n", *len, (int) type));
914 }
915
916 string_len = SMUXMAXSTRLEN;
917 if ((ptr = asn_parse_string(ptr, len, &type, (u_char *) descr,
918 &string_len)) == NULL) {
919 DEBUGMSGTL(("smux", "[smux_open_process] descr parse failed\n"));
920 *fail = TRUE;
921 return ((ptr += *len));
922 }
923
924 if (snmp_get_do_debugging()) {
925 DEBUGMSGTL(("smux", "[smux_open_process] smux peer descr: "));
926 for (i = 0; i < (int) string_len; i++)
927 DEBUGMSG(("smux", "%c", descr[i]));
928 DEBUGMSG(("smux", "\n"));
929 DEBUGMSGTL(("smux", "[smux_open_process] len %" NETSNMP_PRIz
930 "u, type %d\n", *len, (int) type));
931 }
932 descr[string_len] = 0;
933
934 string_len = SMUXMAXSTRLEN;
935 if ((ptr = asn_parse_string(ptr, len, &type, (u_char *) passwd,
936 &string_len)) == NULL) {
937 DEBUGMSGTL(("smux", "[smux_open_process] passwd parse failed\n"));
938 *fail = TRUE;
939 return ((ptr += *len));
940 }
941
942 if (snmp_get_do_debugging()) {
943 DEBUGMSGTL(("smux", "[smux_open_process] smux peer passwd: "));
944 for (i = 0; i < (int) string_len; i++)
945 DEBUGMSG(("smux", "%c", passwd[i]));
946 DEBUGMSG(("smux", "\n"));
947 DEBUGMSGTL(("smux", "[smux_open_process] len %" NETSNMP_PRIz
948 "u, type %d\n", *len, (int) type));
949 }
950 passwd[string_len] = '\0';
951 if (!smux_auth_peer(oid_name, oid_name_len, passwd, fd)) {
952 snmp_log(LOG_WARNING,
953 "refused smux peer: oid %s, descr %s\n",
954 oid_print, descr);
955 *fail = TRUE;
956 return ptr;
957 }
958 DEBUGMSGTL(("smux",
959 "accepted smux peer: oid %s, descr %s\n",
960 oid_print, descr));
961 *fail = FALSE;
962 return ptr;
963 }
964
965 static void
smux_send_close(int fd,int reason)966 smux_send_close(int fd, int reason)
967 {
968 u_char outpacket[3], *ptr;
969
970 ptr = outpacket;
971
972 *(ptr++) = (u_char) SMUX_CLOSE;
973 *(ptr++) = (u_char) 1;
974 *ptr = (u_char) (reason & 0xFF);
975
976 if (snmp_get_do_debugging())
977 DEBUGMSGTL(("smux",
978 "[smux_close] sending close to fd %d, reason %d\n", fd,
979 reason));
980
981 /*
982 * send a response back
983 */
984 if (sendto(fd, (char *) outpacket, 3, 0, NULL, 0) < 0) {
985 snmp_log_perror("[smux_snmp_close] send failed");
986 }
987 }
988
989
990 static int
smux_auth_peer(oid * name,size_t namelen,char * passwd,int fd)991 smux_auth_peer(oid * name, size_t namelen, char *passwd, int fd)
992 {
993 int i;
994 char oid_print[SMUXMAXSTRLEN];
995
996 if (snmp_get_do_debugging()) {
997 snprint_objid(oid_print, sizeof(oid_print), name, namelen);
998 DEBUGMSGTL(("smux:auth", "[smux_auth_peer] Authorizing: %s, %s\n",
999 oid_print, passwd));
1000 }
1001
1002 for (i = 0; i < nauths; i++) {
1003 if (snmp_get_do_debugging()) {
1004 snprint_objid(oid_print, sizeof(oid_print),
1005 Auths[i]->sa_oid, Auths[i]->sa_oid_len);
1006 DEBUGMSGTL(("smux:auth", "[smux_auth_peer] Checking OID: %s (%d)\n",
1007 oid_print, i));
1008 }
1009 if (snmp_oid_compare(Auths[i]->sa_oid, Auths[i]->sa_oid_len,
1010 name, namelen) == 0) {
1011 if (snmp_get_do_debugging()) {
1012 DEBUGMSGTL(("smux:auth", "[smux_auth_peer] Checking P/W: %s (%d)\n",
1013 Auths[i]->sa_passwd, Auths[i]->sa_active_fd));
1014 }
1015 if (!(strcmp(Auths[i]->sa_passwd, passwd)) &&
1016 (Auths[i]->sa_active_fd == -1)) {
1017 /*
1018 * matched, mark the auth
1019 */
1020 Auths[i]->sa_active_fd = fd;
1021 return 1;
1022 }
1023 }
1024 }
1025 /*
1026 * did not match oid and passwd
1027 */
1028 return 0;
1029 }
1030
1031
1032 /*
1033 * XXX - Bells and Whistles:
1034 * Need to catch signal when snmpd goes down and send close pdu to gated
1035 */
1036 static u_char *
smux_close_process(int fd,u_char * ptr,size_t * len)1037 smux_close_process(int fd, u_char * ptr, size_t * len)
1038 {
1039 long down = 0;
1040 int length = *len;
1041
1042 /*
1043 * This is the integer part of the close pdu
1044 */
1045 while (length--) {
1046 down = (down << 8) | (long) *ptr;
1047 ptr++;
1048 }
1049
1050 DEBUGMSGTL(("smux",
1051 "[smux_close_process] close from peer on fd %d reason %ld\n",
1052 fd, down));
1053 smux_peer_cleanup(fd);
1054
1055 return NULL;
1056 }
1057
1058 static u_char *
smux_rreq_process(int sd,u_char * ptr,size_t * len)1059 smux_rreq_process(int sd, u_char * ptr, size_t * len)
1060 {
1061 long priority, rpriority;
1062 long operation;
1063 oid oid_name[MAX_OID_LEN];
1064 size_t oid_name_len;
1065 int i, result;
1066 u_char type;
1067 smux_reg *rptr, *nrptr;
1068 netsnmp_handler_registration *reg;
1069
1070 oid_name_len = MAX_OID_LEN;
1071 ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len);
1072
1073 DEBUGMSGTL(("smux", "[smux_rreq_process] smux subtree: "));
1074 DEBUGMSGOID(("smux", oid_name, oid_name_len));
1075 DEBUGMSG(("smux", "\n"));
1076
1077 if ((ptr = asn_parse_int(ptr, len, &type, &priority,
1078 sizeof(priority))) == NULL) {
1079 DEBUGMSGTL(("smux",
1080 "[smux_rreq_process] priority parse failed\n"));
1081 smux_send_rrsp(sd, -1);
1082 return NULL;
1083 }
1084 DEBUGMSGTL(("smux", "[smux_rreq_process] priority %ld\n", priority));
1085
1086 if ((ptr = asn_parse_int(ptr, len, &type, &operation,
1087 sizeof(operation))) == NULL) {
1088 DEBUGMSGTL(("smux",
1089 "[smux_rreq_process] operation parse failed\n"));
1090 smux_send_rrsp(sd, -1);
1091 return NULL;
1092 }
1093 DEBUGMSGTL(("smux", "[smux_rreq_process] operation %ld\n", operation));
1094
1095 if (operation == SMUX_REGOP_DELETE) {
1096 /*
1097 * search the active list for this registration
1098 */
1099 rptr =
1100 smux_find_match(ActiveRegs, sd, oid_name, oid_name_len,
1101 priority);
1102 if (rptr) {
1103 rpriority = rptr->sr_priority;
1104 /*
1105 * unregister the mib
1106 */
1107 unregister_mib(rptr->sr_name, rptr->sr_name_len);
1108 /*
1109 * find a replacement
1110 */
1111 nrptr =
1112 smux_find_replacement(rptr->sr_name, rptr->sr_name_len);
1113 if (nrptr) {
1114 /*
1115 * found one
1116 */
1117 smux_replace_active(rptr, nrptr);
1118 } else {
1119 /*
1120 * no replacement found
1121 */
1122 smux_list_detach(&ActiveRegs, rptr);
1123 free(rptr);
1124 }
1125 smux_send_rrsp(sd, rpriority);
1126 return ptr;
1127 }
1128 /*
1129 * search the passive list for this registration
1130 */
1131 rptr =
1132 smux_find_match(PassiveRegs, sd, oid_name, oid_name_len,
1133 priority);
1134 if (rptr) {
1135 rpriority = rptr->sr_priority;
1136 smux_list_detach(&PassiveRegs, rptr);
1137 free(rptr);
1138 smux_send_rrsp(sd, rpriority);
1139 return ptr;
1140 }
1141 /*
1142 * This peer cannot unregister the tree, it does not
1143 * * belong to him. Send him an error.
1144 */
1145 smux_send_rrsp(sd, -1);
1146 return ptr;
1147
1148 } else if ((operation == SMUX_REGOP_REGISTER_RO) ||
1149 (operation == SMUX_REGOP_REGISTER_RW)) {
1150 if (priority < -1) {
1151 DEBUGMSGTL(("smux",
1152 "[smux_rreq_process] peer fd %d invalid priority %ld",
1153 sd, priority));
1154 smux_send_rrsp(sd, -1);
1155 return NULL;
1156 }
1157 if ((nrptr = malloc(sizeof(smux_reg))) == NULL) {
1158 snmp_log_perror("[smux_rreq_process] malloc");
1159 smux_send_rrsp(sd, -1);
1160 return NULL;
1161 }
1162 nrptr->sr_priority = priority;
1163 nrptr->sr_name_len = oid_name_len;
1164 nrptr->sr_fd = sd;
1165 for (i = 0; i < (int) oid_name_len; i++)
1166 nrptr->sr_name[i] = oid_name[i];
1167
1168 /*
1169 * See if this tree matches or scopes any of the
1170 * * active trees.
1171 */
1172 for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
1173 result =
1174 snmp_oid_compare(oid_name, oid_name_len, rptr->sr_name,
1175 rptr->sr_name_len);
1176 if (result == 0) {
1177 if (oid_name_len == rptr->sr_name_len) {
1178 if (nrptr->sr_priority == -1) {
1179 nrptr->sr_priority = rptr->sr_priority;
1180 do {
1181 nrptr->sr_priority++;
1182 } while (smux_list_add(&PassiveRegs, nrptr));
1183 goto done;
1184 } else if (nrptr->sr_priority < rptr->sr_priority) {
1185 /*
1186 * Better priority. There are no better
1187 * * priorities for this tree in the passive list,
1188 * * so replace the current active tree.
1189 */
1190 smux_replace_active(rptr, nrptr);
1191 goto done;
1192 } else {
1193 /*
1194 * Equal or worse priority
1195 */
1196 do {
1197 nrptr->sr_priority++;
1198 } while (smux_list_add(&PassiveRegs, nrptr) == -1);
1199 goto done;
1200 }
1201 } else if (oid_name_len < rptr->sr_name_len) {
1202 /*
1203 * This tree scopes a current active
1204 * * tree. Replace the current active tree.
1205 */
1206 smux_replace_active(rptr, nrptr);
1207 goto done;
1208 } else { /* oid_name_len > rptr->sr_name_len */
1209 /*
1210 * This tree is scoped by a current
1211 * * active tree.
1212 */
1213 do {
1214 nrptr->sr_priority++;
1215 } while (smux_list_add(&PassiveRegs, nrptr) == -1);
1216 goto done;
1217 }
1218 }
1219 }
1220 /*
1221 * We didn't find it in the active list. Add it at
1222 * * the requested priority.
1223 */
1224 if (nrptr->sr_priority == -1)
1225 nrptr->sr_priority = 0;
1226
1227 reg = netsnmp_create_handler_registration("smux",
1228 smux_handler,
1229 nrptr->sr_name,
1230 nrptr->sr_name_len,
1231 HANDLER_CAN_RWRITE);
1232 if (reg == NULL) {
1233 snmp_log(LOG_ERR, "SMUX: cannot create new smux peer "
1234 "registration\n");
1235 smux_send_rrsp(sd, -1);
1236 free(nrptr);
1237 return NULL;
1238 }
1239 if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) {
1240 snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n");
1241 smux_send_rrsp(sd, -1);
1242 free(nrptr);
1243 return NULL;
1244 }
1245 nrptr->reginfo = reg;
1246 smux_list_add(&ActiveRegs, nrptr);
1247
1248 done:
1249 smux_send_rrsp(sd, nrptr->sr_priority);
1250 return ptr;
1251 } else {
1252 DEBUGMSGTL(("smux", "[smux_rreq_process] unknown operation\n"));
1253 smux_send_rrsp(sd, -1);
1254 return NULL;
1255 }
1256 }
1257
1258 /*
1259 * Find the registration with a matching descriptor, OID and priority. If
1260 * the priority is -1 then find a registration with a matching descriptor,
1261 * a matching OID, and the highest priority.
1262 */
1263 static smux_reg *
smux_find_match(smux_reg * regs,int sd,oid * oid_name,size_t oid_name_len,long priority)1264 smux_find_match(smux_reg * regs, int sd, oid * oid_name,
1265 size_t oid_name_len, long priority)
1266 {
1267 smux_reg *rptr, *bestrptr;
1268
1269 bestrptr = NULL;
1270 for (rptr = regs; rptr; rptr = rptr->sr_next) {
1271 if (rptr->sr_fd != sd)
1272 continue;
1273 if (snmp_oid_compare
1274 (rptr->sr_name, rptr->sr_name_len, oid_name, oid_name_len))
1275 continue;
1276 if (rptr->sr_priority == priority)
1277 return rptr;
1278 if (priority != -1)
1279 continue;
1280 if (bestrptr) {
1281 if (bestrptr->sr_priority > rptr->sr_priority)
1282 bestrptr = rptr;
1283 } else {
1284 bestrptr = rptr;
1285 }
1286 }
1287 return bestrptr;
1288 }
1289
1290 static void
smux_replace_active(smux_reg * actptr,smux_reg * pasptr)1291 smux_replace_active(smux_reg * actptr, smux_reg * pasptr)
1292 {
1293 netsnmp_handler_registration *reg;
1294
1295 smux_list_detach(&ActiveRegs, actptr);
1296 if (actptr->reginfo) {
1297 netsnmp_unregister_handler(actptr->reginfo);
1298 actptr->reginfo = NULL;
1299 }
1300
1301 smux_list_detach(&PassiveRegs, pasptr);
1302
1303 (void) smux_list_add(&ActiveRegs, pasptr);
1304 free(actptr);
1305
1306 reg = netsnmp_create_handler_registration("smux",
1307 smux_handler,
1308 pasptr->sr_name,
1309 pasptr->sr_name_len,
1310 HANDLER_CAN_RWRITE);
1311 if (reg == NULL) {
1312 snmp_log(LOG_ERR, "SMUX: cannot create new smux peer registration\n");
1313 pasptr->reginfo = NULL;
1314 return;
1315 }
1316 if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) {
1317 snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n");
1318 pasptr->reginfo = NULL;
1319 return;
1320 }
1321 pasptr->reginfo = reg;
1322 }
1323
1324 static void
smux_list_detach(smux_reg ** head,smux_reg * m_remove)1325 smux_list_detach(smux_reg ** head, smux_reg * m_remove)
1326 {
1327 smux_reg *rptr, *rptr2;
1328
1329 if (*head == NULL) {
1330 DEBUGMSGTL(("smux", "[smux_list_detach] Ouch!"));
1331 return;
1332 }
1333 if (*head == m_remove) {
1334 *head = (*head)->sr_next;
1335 return;
1336 }
1337 for (rptr = *head, rptr2 = rptr->sr_next; rptr2;
1338 rptr2 = rptr2->sr_next, rptr = rptr->sr_next) {
1339 if (rptr2 == m_remove) {
1340 rptr->sr_next = rptr2->sr_next;
1341 return;
1342 }
1343 }
1344 }
1345
1346 /*
1347 * Attempt to add a registration (in order) to a list. If the
1348 * add fails (because of an existing registration with equal
1349 * priority) return -1.
1350 */
1351 static int
smux_list_add(smux_reg ** head,smux_reg * add)1352 smux_list_add(smux_reg ** head, smux_reg * add)
1353 {
1354 smux_reg *rptr, *prev;
1355 int result;
1356
1357 if (*head == NULL) {
1358 *head = add;
1359 (*head)->sr_next = NULL;
1360 return 0;
1361 }
1362 prev = NULL;
1363 for (rptr = *head; rptr; rptr = rptr->sr_next) {
1364 result = snmp_oid_compare(add->sr_name, add->sr_name_len,
1365 rptr->sr_name, rptr->sr_name_len);
1366 if (result == 0) {
1367 /*
1368 * Same tree...
1369 */
1370 if (add->sr_priority == rptr->sr_priority) {
1371 /*
1372 * ... same pri : nope
1373 */
1374 return -1;
1375 } else if (add->sr_priority < rptr->sr_priority) {
1376 /*
1377 * ... lower pri : insert and return
1378 */
1379 add->sr_next = rptr;
1380 if ( prev ) { prev->sr_next = add; }
1381 else { *head = add; }
1382 return 0;
1383 #ifdef XXX
1384 } else {
1385 /*
1386 * ... higher pri : put after
1387 */
1388 add->sr_next = rptr->sr_next;
1389 rptr->sr_next = add;
1390 #endif
1391 }
1392 } else if (result < 0) {
1393 /*
1394 * Earlier tree : insert and return
1395 */
1396 add->sr_next = rptr;
1397 if ( prev ) { prev->sr_next = add; }
1398 else { *head = add; }
1399 return 0;
1400 #ifdef XXX
1401 } else {
1402 /*
1403 * Later tree : put after
1404 */
1405 add->sr_next = rptr->sr_next;
1406 rptr->sr_next = add;
1407 return 0;
1408 #endif
1409 }
1410 prev = rptr;
1411 }
1412 /*
1413 * Otherwise, this entry must come last
1414 */
1415 if ( prev ) { prev->sr_next = add; }
1416 else { *head = add; }
1417 add->sr_next = NULL;
1418 return 0;
1419 }
1420
1421 /*
1422 * Find a replacement for this registration. In order
1423 * of preference:
1424 *
1425 * - Least difference in subtree length
1426 * - Best (lowest) priority
1427 *
1428 * For example, if we need to replace .1.3.6.1.69,
1429 * we would pick .1.3.6.1.69.1 instead of .1.3.6.69.1.1
1430 *
1431 */
1432 static smux_reg *
smux_find_replacement(oid * name,size_t name_len)1433 smux_find_replacement(oid * name, size_t name_len)
1434 {
1435 smux_reg *rptr, *bestptr;
1436 int bestlen, difflen;
1437
1438 bestlen = SMUX_MAX_PRIORITY;
1439 bestptr = NULL;
1440
1441 for (rptr = PassiveRegs; rptr; rptr = rptr->sr_next) {
1442 if (!snmp_oidtree_compare(rptr->sr_name, rptr->sr_name_len,
1443 name, name_len)) {
1444 if ((difflen = rptr->sr_name_len - name_len)
1445 < bestlen || !bestptr) {
1446 bestlen = difflen;
1447 bestptr = rptr;
1448 } else if ((difflen == bestlen) &&
1449 (rptr->sr_priority < bestptr->sr_priority))
1450 bestptr = rptr;
1451 }
1452 }
1453 return bestptr;
1454 }
1455
1456 u_char *
smux_snmp_process(int exact,oid * objid,size_t * len,size_t * return_len,u_char * return_type,int sd)1457 smux_snmp_process(int exact,
1458 oid * objid,
1459 size_t * len,
1460 size_t * return_len, u_char * return_type, int sd)
1461 {
1462 u_char packet[SMUXMAXPKTSIZE], *ptr, result[SMUXMAXPKTSIZE];
1463 ssize_t length = SMUXMAXPKTSIZE;
1464 int tmp_length;
1465 u_char type;
1466 size_t packet_len;
1467
1468 /*
1469 * Send the query to the peer
1470 */
1471 if (exact)
1472 type = SMUX_GET;
1473 else
1474 type = SMUX_GETNEXT;
1475
1476 if (smux_build(type, smux_reqid, objid, len, 0, NULL,
1477 *len, packet, (size_t *) &length) < 0) {
1478 snmp_log(LOG_ERR, "[smux_snmp_process]: smux_build failed\n");
1479 return NULL;
1480 }
1481 DEBUGMSGTL(("smux", "[smux_snmp_process] oid from build: "));
1482 DEBUGMSGOID(("smux", objid, *len));
1483 DEBUGMSG(("smux", "\n"));
1484
1485 if (sendto(sd, (char *) packet, length, 0, NULL, 0) < 0) {
1486 snmp_log_perror("[smux_snmp_process] send failed");
1487 }
1488
1489 DEBUGMSGTL(("smux",
1490 "[smux_snmp_process] Sent %d request to peer; %" NETSNMP_PRIz "d bytes\n",
1491 (int) type, length));
1492
1493 while (1) {
1494 /*
1495 * peek at what's received
1496 */
1497 length = recvfrom(sd, (char *) result, SMUXMAXPKTSIZE, MSG_PEEK, NULL,
1498 NULL);
1499 if (length <= 0) {
1500 if ((length == -1) && ((errno == EINTR) || (errno == EAGAIN)))
1501 {
1502 continue;
1503 }
1504 else
1505 {
1506 snmp_log_perror("[smux_snmp_process] peek failed");
1507 smux_peer_cleanup(sd);
1508 smux_snmp_select_list_del(sd);
1509 return NULL;
1510 }
1511 }
1512
1513 DEBUGMSGTL(("smux", "[smux_snmp_process] Peeked at %" NETSNMP_PRIz "d bytes\n",
1514 length));
1515 DEBUGDUMPSETUP("smux_snmp_process", result, length);
1516
1517 /*
1518 * determine if we received more than one packet
1519 */
1520 packet_len = length;
1521 ptr = asn_parse_header(result, &packet_len, &type);
1522 if (ptr == NULL)
1523 return NULL;
1524 packet_len += (ptr - result);
1525 if (length > packet_len) {
1526 /*
1527 * set length to receive only the first packet
1528 */
1529 length = packet_len;
1530 }
1531
1532 /*
1533 * receive the first packet
1534 */
1535 tmp_length = length;
1536 do
1537 {
1538 length = tmp_length;
1539 length = recvfrom(sd, (char *) result, length, 0, NULL, NULL);
1540 }
1541 while((length == -1) && ((errno == EINTR) || (errno == EAGAIN)));
1542
1543 if (length <= 0) {
1544 snmp_log_perror("[smux_snmp_process] recv failed");
1545 smux_peer_cleanup(sd);
1546 smux_snmp_select_list_del(sd);
1547 return NULL;
1548 }
1549
1550 DEBUGMSGTL(("smux", "[smux_snmp_process] Received %" NETSNMP_PRIz "d bytes\n",
1551 length));
1552
1553 if (result[0] == SMUX_TRAP) {
1554 DEBUGMSGTL(("smux", "[smux_snmp_process] Received trap\n"));
1555 DEBUGMSGTL(("smux", "Got trap from peer on fd %d\n", sd));
1556 ptr = asn_parse_header(result, (size_t *) &length, &type);
1557 if (ptr == NULL)
1558 return NULL;
1559 smux_trap_process(ptr, (size_t *) &length);
1560
1561 /*
1562 * go and peek at received data again
1563 */
1564 /*
1565 * we could receive the reply or another trap
1566 */
1567 } else {
1568 /*
1569 * Interpret reply
1570 */
1571 ptr = smux_parse(result, objid, len, return_len, return_type);
1572 /*
1573 * ptr will point to query result or NULL if error
1574 */
1575 break;
1576 }
1577 } /* while (1) */
1578
1579 return ptr;
1580 }
1581
1582 static u_char *
smux_parse(u_char * rsp,oid * objid,size_t * oidlen,size_t * return_len,u_char * return_type)1583 smux_parse(u_char * rsp,
1584 oid * objid,
1585 size_t * oidlen, size_t * return_len, u_char * return_type)
1586 {
1587 size_t length = SMUXMAXPKTSIZE;
1588 u_char *ptr, type;
1589 long reqid, errstat, errindex;
1590
1591 ptr = rsp;
1592
1593 /*
1594 * Return pointer to the snmp/smux return value.
1595 * return_len should contain the number of bytes in the value
1596 * returned above.
1597 * objid is the next object, with len for GETNEXT.
1598 * objid and len are not changed for GET
1599 */
1600 ptr = asn_parse_header(ptr, &length, &type);
1601 if (ptr == NULL || type != SNMP_MSG_RESPONSE)
1602 return NULL;
1603
1604 if ((ptr = asn_parse_int(ptr, &length, &type, &reqid,
1605 sizeof(reqid))) == NULL) {
1606 DEBUGMSGTL(("smux", "[smux_parse] parse of reqid failed\n"));
1607 return NULL;
1608 }
1609 if ((ptr = asn_parse_int(ptr, &length, &type, &errstat,
1610 sizeof(errstat))) == NULL) {
1611 DEBUGMSGTL(("smux",
1612 "[smux_parse] parse of error status failed\n"));
1613 return NULL;
1614 }
1615 if ((ptr = asn_parse_int(ptr, &length, &type, &errindex,
1616 sizeof(errindex))) == NULL) {
1617 DEBUGMSGTL(("smux", "[smux_parse] parse of error index failed\n"));
1618 return NULL;
1619 }
1620
1621 /*
1622 * XXX How to send something intelligent back in case of an error
1623 */
1624 DEBUGMSGTL(("smux",
1625 "[smux_parse] Message type %d, reqid %ld, errstat %ld, \n\terrindex %ld\n",
1626 (int) type, reqid, errstat, errindex));
1627 if (ptr == NULL || errstat != SNMP_ERR_NOERROR)
1628 return NULL;
1629
1630 /*
1631 * stuff to return
1632 */
1633 return (smux_parse_var
1634 (ptr, &length, objid, oidlen, return_len, return_type));
1635 }
1636
1637
1638 static u_char *
smux_parse_var(u_char * varbind,size_t * varbindlength,oid * objid,size_t * oidlen,size_t * varlength,u_char * vartype)1639 smux_parse_var(u_char * varbind,
1640 size_t * varbindlength,
1641 oid * objid,
1642 size_t * oidlen, size_t * varlength, u_char * vartype)
1643 {
1644 oid var_name[MAX_OID_LEN];
1645 size_t var_name_len;
1646 size_t var_val_len;
1647 u_char *var_val;
1648 size_t str_len, objid_len;
1649 size_t len;
1650 u_char *ptr;
1651 u_char type;
1652
1653 ptr = varbind;
1654 len = *varbindlength;
1655
1656 DEBUGMSGTL(("smux", "[smux_parse_var] before any processing: "));
1657 DEBUGMSGOID(("smux", objid, *oidlen));
1658 DEBUGMSG(("smux", "\n"));
1659
1660 ptr = asn_parse_header(ptr, &len, &type);
1661 if (ptr == NULL || type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
1662 snmp_log(LOG_NOTICE, "[smux_parse_var] Panic: type %d\n",
1663 (int) type);
1664 return NULL;
1665 }
1666
1667 /*
1668 * get hold of the objid and the asn1 coded value
1669 */
1670 var_name_len = MAX_OID_LEN;
1671 ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, vartype,
1672 &var_val_len, &var_val, &len);
1673
1674 *oidlen = var_name_len;
1675 memcpy(objid, var_name, var_name_len * sizeof(oid));
1676
1677 DEBUGMSGTL(("smux", "[smux_parse_var] returning oid : "));
1678 DEBUGMSGOID(("smux", objid, *oidlen));
1679 DEBUGMSG(("smux", "\n"));
1680 /*
1681 * XXX
1682 */
1683 len = SMUXMAXPKTSIZE;
1684 DEBUGMSGTL(("smux",
1685 "[smux_parse_var] Asn coded len of var %" NETSNMP_PRIz
1686 "u, type %d\n", var_val_len, (int) *vartype));
1687
1688 switch ((short) *vartype) {
1689 case ASN_INTEGER:
1690 *varlength = sizeof(long);
1691 asn_parse_int(var_val, &len, vartype,
1692 (long *) &smux_long, *varlength);
1693 return (u_char *) & smux_long;
1694 break;
1695 case ASN_COUNTER:
1696 case ASN_GAUGE:
1697 case ASN_TIMETICKS:
1698 case ASN_UINTEGER:
1699 *varlength = sizeof(u_long);
1700 asn_parse_unsigned_int(var_val, &len, vartype,
1701 (u_long *) & smux_ulong, *varlength);
1702 return (u_char *) & smux_ulong;
1703 break;
1704 case ASN_COUNTER64:
1705 *varlength = sizeof(smux_counter64);
1706 asn_parse_unsigned_int64(var_val, &len, vartype,
1707 (struct counter64 *) &smux_counter64,
1708 *varlength);
1709 return (u_char *) & smux_counter64;
1710 break;
1711 case ASN_IPADDRESS:
1712 *varlength = 4;
1713 /*
1714 * consume the tag and length, but just copy here
1715 * because we know it is an ip address
1716 */
1717 if ((var_val = asn_parse_header(var_val, &len, &type)) == NULL)
1718 return NULL;
1719 memcpy((u_char *) & (smux_sa.sin_addr.s_addr), var_val,
1720 *varlength);
1721 return (u_char *) & (smux_sa.sin_addr.s_addr);
1722 break;
1723 case ASN_OCTET_STR:
1724 /*
1725 * XXX
1726 */
1727 if (len == 0)
1728 return NULL;
1729 str_len = SMUXMAXSTRLEN;
1730 asn_parse_string(var_val, &len, vartype, smux_str, &str_len);
1731 *varlength = str_len;
1732 return smux_str;
1733 break;
1734 case ASN_OPAQUE:
1735 case ASN_NSAP:
1736 case ASN_OBJECT_ID:
1737 objid_len = MAX_OID_LEN;
1738 asn_parse_objid(var_val, &len, vartype, smux_objid, &objid_len);
1739 *varlength = objid_len * sizeof(oid);
1740 return (u_char *) smux_objid;
1741 break;
1742 case SNMP_NOSUCHOBJECT:
1743 case SNMP_NOSUCHINSTANCE:
1744 case SNMP_ENDOFMIBVIEW:
1745 case ASN_NULL:
1746 return NULL;
1747 break;
1748 case ASN_BIT_STR:
1749 /*
1750 * XXX
1751 */
1752 if (len == 0)
1753 return NULL;
1754 str_len = SMUXMAXSTRLEN;
1755 asn_parse_bitstring(var_val, &len, vartype, smux_str, &str_len);
1756 *varlength = str_len;
1757 return (u_char *) smux_str;
1758 break;
1759 default:
1760 snmp_log(LOG_ERR, "bad type returned (%x)\n", *vartype);
1761 return NULL;
1762 break;
1763 }
1764 }
1765
1766 /*
1767 * XXX This is a bad hack - do not want to muck with ucd code
1768 */
1769 static int
smux_build(u_char type,long reqid,oid * objid,size_t * oidlen,u_char val_type,u_char * val,size_t val_len,u_char * packet,size_t * length)1770 smux_build(u_char type,
1771 long reqid,
1772 oid * objid,
1773 size_t * oidlen,
1774 u_char val_type,
1775 u_char * val, size_t val_len, u_char * packet, size_t * length)
1776 {
1777 u_char *ptr, *save1, *save2;
1778 size_t len;
1779 long errstat = 0;
1780 long errindex = 0;
1781
1782 /*
1783 * leave space for Seq and length
1784 */
1785 save1 = packet;
1786 ptr = packet + 4;
1787 len = *length - 4;
1788
1789 /*
1790 * build reqid
1791 */
1792 ptr = asn_build_int(ptr, &len,
1793 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1794 ASN_INTEGER), &reqid,
1795 sizeof(reqid));
1796 if (ptr == NULL) {
1797 return -1;
1798 }
1799
1800 /*
1801 * build err stat
1802 */
1803 ptr = asn_build_int(ptr, &len,
1804 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1805 ASN_INTEGER), &errstat, sizeof(errstat));
1806 if (ptr == NULL) {
1807 return -1;
1808 }
1809
1810 /*
1811 * build err index
1812 */
1813 ptr = asn_build_int(ptr, &len,
1814 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1815 ASN_INTEGER), &errindex,
1816 sizeof(errindex));
1817 if (ptr == NULL) {
1818 return -1;
1819 }
1820
1821 save2 = ptr;
1822 ptr += 4;
1823 len -= 4;
1824
1825 if (type != SMUX_SET) {
1826 val_type = ASN_NULL;
1827 val_len = 0;
1828 }
1829
1830 /*
1831 * build var list : snmp_build_var_op not liked by gated XXX
1832 */
1833 ptr = snmp_build_var_op(ptr, objid, oidlen, val_type, val_len,
1834 val, &len);
1835 if (ptr == NULL) {
1836 return -1;
1837 }
1838
1839 len = ptr - save1;
1840 asn_build_sequence(save1, &len, type, (ptr - save1 - 4));
1841
1842 len = ptr - save2;
1843 asn_build_sequence(save2, &len,
1844 (ASN_SEQUENCE | ASN_CONSTRUCTOR),
1845 (ptr - save2 - 4));
1846
1847 *length = ptr - packet;
1848
1849 return 0;
1850 }
1851
1852 static void
smux_peer_cleanup(int sd)1853 smux_peer_cleanup(int sd)
1854 {
1855 smux_reg *nrptr, *rptr, *rptr2;
1856 int i;
1857 netsnmp_handler_registration *reg;
1858
1859 /*
1860 * close the descriptor
1861 */
1862 close(sd);
1863
1864 /*
1865 * delete all of the passive registrations that this peer owns
1866 */
1867 for (rptr = PassiveRegs; rptr; rptr = nrptr) {
1868 nrptr = rptr->sr_next;
1869 if (rptr->sr_fd == sd) {
1870 smux_list_detach(&PassiveRegs, rptr);
1871 free(rptr);
1872 }
1873 rptr = nrptr;
1874 }
1875 /*
1876 * find replacements for all of the active registrations found
1877 */
1878 for (rptr = ActiveRegs; rptr; rptr = rptr2) {
1879 rptr2 = rptr->sr_next;
1880 if (rptr->sr_fd == sd) {
1881 smux_list_detach(&ActiveRegs, rptr);
1882 if (rptr->reginfo) {
1883 netsnmp_unregister_handler(rptr->reginfo);
1884 rptr->reginfo = NULL;
1885 }
1886 if ((nrptr = smux_find_replacement(rptr->sr_name,
1887 rptr->sr_name_len)) !=
1888 NULL) {
1889 smux_list_detach(&PassiveRegs, nrptr);
1890 reg = netsnmp_create_handler_registration("smux",
1891 smux_handler,
1892 nrptr->sr_name,
1893 nrptr->sr_name_len,
1894 HANDLER_CAN_RWRITE);
1895 if (reg == NULL) {
1896 snmp_log(LOG_ERR, "SMUX: cannot create new smux peer "
1897 "registration\n");
1898 continue;
1899 }
1900 if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) {
1901 snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n");
1902 continue;
1903 }
1904 nrptr->reginfo = reg;
1905 smux_list_add(&ActiveRegs, nrptr);
1906 }
1907 free(rptr);
1908 }
1909 }
1910
1911 /*
1912 * decrement the peer count
1913 */
1914 npeers--;
1915
1916 /*
1917 * make his auth available again
1918 */
1919 for (i = 0; i < nauths; i++) {
1920 if (Auths[i]->sa_active_fd == sd) {
1921 char oid_name[128];
1922 Auths[i]->sa_active_fd = -1;
1923 snprint_objid(oid_name, sizeof(oid_name), Auths[i]->sa_oid,
1924 Auths[i]->sa_oid_len);
1925 DEBUGMSGTL(("smux", "peer disconnected: %s\n", oid_name));
1926 }
1927 }
1928 }
1929
1930 int
smux_send_rrsp(int sd,int pri)1931 smux_send_rrsp(int sd, int pri)
1932 {
1933 u_char outdata[2 + sizeof(int)];
1934 u_char *ptr = outdata;
1935 int intsize = sizeof(int);
1936 u_int mask = ((u_int) 0xFF) << (8 * (sizeof(int) - 1));
1937 /*
1938 * e.g. mask is 0xFF000000 on a 32-bit machine
1939 */
1940 int sent;
1941
1942 /*
1943 * This is kind of like calling asn_build_int(), but the
1944 * encoding will always be the size of an integer on this
1945 * machine, never shorter.
1946 */
1947 *ptr++ = (u_char) SMUX_RRSP;
1948 *ptr++ = (u_char) intsize;
1949
1950 /*
1951 * Copy each byte, most significant first.
1952 */
1953 while (intsize--) {
1954 *ptr++ = (u_char) ((pri & mask) >> (8 * (sizeof(int) - 1)));
1955 pri <<= 8;
1956 }
1957
1958 sent = sendto(sd, (char *) outdata, sizeof outdata, 0, NULL, 0);
1959 if (sent < 0) {
1960 DEBUGMSGTL(("smux", "[smux_send_rrsp] send failed\n"));
1961 }
1962 return (sent);
1963 }
1964
1965 static u_char *
smux_trap_process(u_char * rsp,size_t * len)1966 smux_trap_process(u_char * rsp, size_t * len)
1967 {
1968 oid sa_enterpriseoid[MAX_OID_LEN], var_name[MAX_OID_LEN];
1969 size_t datalen, var_name_len, var_val_len, maxlen;
1970 size_t sa_enterpriseoid_len;
1971 u_char vartype, *ptr, *var_val;
1972
1973 long trap, specific;
1974 u_long timestamp;
1975
1976 netsnmp_variable_list *snmptrap_head, *snmptrap_ptr, *snmptrap_tmp;
1977 snmptrap_head = NULL;
1978 snmptrap_ptr = NULL;
1979
1980 ptr = rsp;
1981
1982 /*
1983 * parse the sub-agent enterprise oid
1984 */
1985 sa_enterpriseoid_len = MAX_OID_LEN;
1986 if ((ptr = asn_parse_objid(ptr, len,
1987 &vartype, (oid *) & sa_enterpriseoid,
1988 &sa_enterpriseoid_len)) == NULL) {
1989 DEBUGMSGTL(("smux",
1990 "[smux_trap_process] asn_parse_objid failed\n"));
1991 return NULL;
1992 }
1993
1994 /*
1995 * parse the agent-addr ipAddress
1996 */
1997 datalen = SMUXMAXSTRLEN;
1998 if (((ptr = asn_parse_string(ptr, len,
1999 &vartype, smux_str,
2000 &datalen)) == NULL) ||
2001 (vartype != (u_char) ASN_IPADDRESS)) {
2002 DEBUGMSGTL(("smux",
2003 "[smux_trap_process] asn_parse_string failed\n"));
2004 return NULL;
2005 }
2006
2007 /*
2008 * parse the generic trap int
2009 */
2010 datalen = sizeof(long);
2011 if ((ptr = asn_parse_int(ptr, len, &vartype, &trap, datalen)) == NULL) {
2012 DEBUGMSGTL(("smux",
2013 "[smux_trap_process] asn_parse_int generic failed\n"));
2014 return NULL;
2015 }
2016
2017 /*
2018 * parse the specific trap int
2019 */
2020 datalen = sizeof(long);
2021 if ((ptr = asn_parse_int(ptr, len,
2022 &vartype, &specific, datalen)) == NULL) {
2023 DEBUGMSGTL(("smux",
2024 "[smux_trap_process] asn_parse_int specific failed\n"));
2025 return NULL;
2026 }
2027
2028 /*
2029 * parse the timeticks timestamp
2030 */
2031 datalen = sizeof(u_long);
2032 if (((ptr = asn_parse_unsigned_int(ptr, len,
2033 &vartype, (u_long *) & timestamp,
2034 datalen)) == NULL) ||
2035 (vartype != (u_char) ASN_TIMETICKS)) {
2036 DEBUGMSGTL(("smux",
2037 "[smux_trap_process] asn_parse_unsigned_int (timestamp) failed\n"));
2038 return NULL;
2039 }
2040
2041 /*
2042 * parse out the overall sequence
2043 */
2044 ptr = asn_parse_header(ptr, len, &vartype);
2045 if (ptr == NULL || vartype != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
2046 return NULL;
2047 }
2048
2049 /*
2050 * parse the variable bindings
2051 */
2052 while (ptr && *len) {
2053
2054 /*
2055 * get the objid and the asn1 coded value
2056 */
2057 var_name_len = MAX_OID_LEN;
2058 ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, &vartype,
2059 &var_val_len, (u_char **) & var_val, len);
2060
2061 if (ptr == NULL)
2062 goto err;
2063
2064 maxlen = SMUXMAXPKTSIZE;
2065 switch ((short) vartype) {
2066 case ASN_INTEGER:
2067 var_val_len = sizeof(long);
2068 asn_parse_int(var_val, &maxlen, &vartype,
2069 (long *) &smux_long, var_val_len);
2070 var_val = (u_char *) & smux_long;
2071 break;
2072 case ASN_COUNTER:
2073 case ASN_GAUGE:
2074 case ASN_TIMETICKS:
2075 case ASN_UINTEGER:
2076 var_val_len = sizeof(u_long);
2077 asn_parse_unsigned_int(var_val, &maxlen, &vartype,
2078 (u_long *) & smux_ulong, var_val_len);
2079 var_val = (u_char *) & smux_ulong;
2080 break;
2081 case ASN_COUNTER64:
2082 var_val_len = sizeof(smux_counter64);
2083 asn_parse_unsigned_int64(var_val, &maxlen, &vartype,
2084 (struct counter64 *) &smux_counter64,
2085 var_val_len);
2086 var_val = (u_char *) & smux_counter64;
2087 break;
2088 case ASN_IPADDRESS:
2089 var_val_len = 4;
2090 /*
2091 * consume the tag and length, but just copy here
2092 * because we know it is an ip address
2093 */
2094 if ((var_val =
2095 asn_parse_header(var_val, &maxlen, &vartype)) == NULL)
2096 goto err;
2097 memcpy((u_char *) & (smux_sa.sin_addr.s_addr), var_val,
2098 var_val_len);
2099 var_val = (u_char *) & (smux_sa.sin_addr.s_addr);
2100 break;
2101 case ASN_OPAQUE:
2102 case ASN_OCTET_STR:
2103 /*
2104 * XXX
2105 */
2106 var_val_len = SMUXMAXSTRLEN;
2107 asn_parse_string(var_val, &maxlen, &vartype,
2108 smux_str, &var_val_len);
2109 var_val = smux_str;
2110 break;
2111 case ASN_OBJECT_ID:
2112 var_val_len = MAX_OID_LEN;
2113 asn_parse_objid(var_val, &maxlen, &vartype,
2114 smux_objid, &var_val_len);
2115 var_val_len *= sizeof(oid);
2116 var_val = (u_char *) smux_objid;
2117 break;
2118 case SNMP_NOSUCHOBJECT:
2119 case SNMP_NOSUCHINSTANCE:
2120 case SNMP_ENDOFMIBVIEW:
2121 case ASN_NULL:
2122 var_val = NULL;
2123 break;
2124 case ASN_BIT_STR:
2125 /*
2126 * XXX
2127 */
2128 var_val_len = SMUXMAXSTRLEN;
2129 asn_parse_bitstring(var_val, &maxlen, &vartype,
2130 smux_str, &var_val_len);
2131 var_val = (u_char *) smux_str;
2132 break;
2133 case ASN_NSAP:
2134 default:
2135 snmp_log(LOG_ERR, "bad type returned (%x)\n", vartype);
2136 var_val = NULL;
2137 break;
2138 }
2139
2140 snmptrap_tmp = calloc(1, sizeof(netsnmp_variable_list));
2141 if (snmptrap_tmp == NULL)
2142 goto err;
2143 if (snmptrap_head == NULL) {
2144 snmptrap_head = snmptrap_tmp;
2145 snmptrap_ptr = snmptrap_head;
2146 } else {
2147 snmptrap_ptr->next_variable = snmptrap_tmp;
2148 snmptrap_ptr = snmptrap_ptr->next_variable;
2149 }
2150
2151 snmptrap_ptr->type = vartype;
2152 snmptrap_ptr->next_variable = NULL;
2153 snmp_set_var_objid(snmptrap_ptr, var_name, var_name_len);
2154 snmp_set_var_value(snmptrap_ptr, (char *) var_val, var_val_len);
2155
2156 }
2157
2158 /*
2159 * send the traps
2160 */
2161 send_enterprise_trap_vars(trap, specific, (oid *) & sa_enterpriseoid,
2162 sa_enterpriseoid_len, snmptrap_head);
2163
2164 /*
2165 * free trap variables
2166 */
2167 snmp_free_varbind(snmptrap_head);
2168
2169 return ptr;
2170
2171 err:
2172 snmp_free_varbind(snmptrap_head);
2173 return NULL;
2174 }
2175
2176 #define NUM_SOCKETS 32
2177 static int sdlist[NUM_SOCKETS], sdlen = 0;
2178
smux_snmp_select_list_add(int sd)2179 int smux_snmp_select_list_add(int sd)
2180 {
2181 if (sdlen < NUM_SOCKETS)
2182 {
2183 sdlist[sdlen++] = sd;
2184 return(1);
2185 }
2186 return(0);
2187 }
2188
smux_snmp_select_list_del(int sd)2189 int smux_snmp_select_list_del(int sd)
2190 {
2191 int i, found=0;
2192
2193 for (i = 0; i < (sdlen); i++) {
2194 if (sdlist[i] == sd)
2195 {
2196 sdlist[i] = 0;
2197 found = 1;
2198 }
2199 if ((found) &&(i < (sdlen - 1)))
2200 sdlist[i] = sdlist[i + 1];
2201 }
2202 if (found)
2203 {
2204 sdlen--;
2205 return(1);
2206 }
2207 return(0);
2208 }
2209
smux_snmp_select_list_get_length(void)2210 int smux_snmp_select_list_get_length(void)
2211 {
2212 return(sdlen);
2213 }
2214
smux_snmp_select_list_get_SD_from_List(int pos)2215 int smux_snmp_select_list_get_SD_from_List(int pos)
2216 {
2217 if (pos < NUM_SOCKETS)
2218 {
2219 return(sdlist[pos]);
2220 }
2221 return(0);
2222 }
2223