00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00036
00037
00038
00039 #include <net-snmp/net-snmp-config.h>
00040
00041 #include <stdio.h>
00042 #include <ctype.h>
00043 #if HAVE_STDLIB_H
00044 #include <stdlib.h>
00045 #endif
00046 #if HAVE_STRING_H
00047 #include <string.h>
00048 #else
00049 #include <strings.h>
00050 #endif
00051 #if HAVE_UNISTD_H
00052 #include <unistd.h>
00053 #endif
00054 #include <sys/types.h>
00055 #if HAVE_SYS_PARAM_H
00056 #include <sys/param.h>
00057 #endif
00058 #if TIME_WITH_SYS_TIME
00059 # ifdef WIN32
00060 # include <sys/timeb.h>
00061 # else
00062 # include <sys/time.h>
00063 # endif
00064 # include <time.h>
00065 #else
00066 # if HAVE_SYS_TIME_H
00067 # include <sys/time.h>
00068 # else
00069 # include <time.h>
00070 # endif
00071 #endif
00072 #if HAVE_NETINET_IN_H
00073 #include <netinet/in.h>
00074 #endif
00075 #if HAVE_ARPA_INET_H
00076 #include <arpa/inet.h>
00077 #endif
00078 #if HAVE_SYS_SELECT_H
00079 #include <sys/select.h>
00080 #endif
00081 #if HAVE_IO_H
00082 #include <io.h>
00083 #endif
00084 #if HAVE_WINSOCK_H
00085 #include <winsock.h>
00086 #endif
00087 #if HAVE_SYS_SOCKET_H
00088 #include <sys/socket.h>
00089 #endif
00090 #if HAVE_SYS_UN_H
00091 #include <sys/un.h>
00092 #endif
00093 #if HAVE_NETDB_H
00094 #include <netdb.h>
00095 #endif
00096 #if HAVE_NET_IF_DL_H
00097 #ifndef dynix
00098 #include <net/if_dl.h>
00099 #else
00100 #include <sys/net/if_dl.h>
00101 #endif
00102 #endif
00103 #include <errno.h>
00104
00105 #if HAVE_LOCALE_H
00106 #include <locale.h>
00107 #endif
00108
00109 #if HAVE_DMALLOC_H
00110 #include <dmalloc.h>
00111 #endif
00112
00113 #define SNMP_NEED_REQUEST_LIST
00114 #include <net-snmp/types.h>
00115 #include <net-snmp/output_api.h>
00116 #include <net-snmp/config_api.h>
00117 #include <net-snmp/utilities.h>
00118
00119 #include <net-snmp/library/asn1.h>
00120 #include <net-snmp/library/snmp.h>
00121 #include <net-snmp/library/snmp_api.h>
00122 #include <net-snmp/library/snmp_client.h>
00123 #include <net-snmp/library/parse.h>
00124 #include <net-snmp/library/mib.h>
00125 #include <net-snmp/library/int64.h>
00126 #include <net-snmp/library/snmpv3.h>
00127 #include <net-snmp/library/callback.h>
00128 #include <net-snmp/library/container.h>
00129 #include <net-snmp/library/snmp_secmod.h>
00130 #include <net-snmp/library/large_fd_set.h>
00131 #ifdef NETSNMP_SECMOD_USM
00132 #include <net-snmp/library/snmpusm.h>
00133 #endif
00134 #ifdef NETSNMP_SECMOD_KSM
00135 #include <net-snmp/library/snmpksm.h>
00136 #endif
00137 #include <net-snmp/library/keytools.h>
00138 #include <net-snmp/library/lcd_time.h>
00139 #include <net-snmp/library/snmp_alarm.h>
00140 #include <net-snmp/library/snmp_transport.h>
00141 #include <net-snmp/library/snmp_service.h>
00142 #include <net-snmp/library/vacm.h>
00143
00144 static void _init_snmp(void);
00145
00146 #include "../agent/mibgroup/agentx/protocol.h"
00147 #include <net-snmp/library/transform_oids.h>
00148 #ifndef timercmp
00149 #define timercmp(tvp, uvp, cmp) \
00150 \
00151 ((tvp)->tv_sec cmp (uvp)->tv_sec || \
00152 ((tvp)->tv_sec == (uvp)->tv_sec && \
00153 \
00154 (tvp)->tv_usec cmp (uvp)->tv_usec))
00155 #endif
00156 #ifndef timerclear
00157 #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
00158 #endif
00159
00160
00161
00162
00163 #define MAX_PACKET_LENGTH (0x7fffffff)
00164 #ifndef NETSNMP_STREAM_QUEUE_LEN
00165 #define NETSNMP_STREAM_QUEUE_LEN 5
00166 #endif
00167
00168 #ifndef BSD4_3
00169 #define BSD4_2
00170 #endif
00171
00172 #ifndef FD_SET
00173
00174 typedef long fd_mask;
00175 #define NFDBITS (sizeof(fd_mask) * NBBY)
00176
00177 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
00178 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
00179 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
00180 #define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
00181 #endif
00182
00183 static oid default_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
00184
00185
00186
00187
00188 #define DEFAULT_COMMUNITY "public"
00189 #define DEFAULT_RETRIES 5
00190 #define DEFAULT_TIMEOUT 1000000L
00191 #define DEFAULT_REMPORT SNMP_PORT
00192 #define DEFAULT_ENTERPRISE default_enterprise
00193 #define DEFAULT_TIME 0
00194
00195
00196
00197
00198
00199 #define MAXIMUM_PACKET_SIZE 0x7fffffff
00200
00201
00202
00203
00204 struct snmp_internal_session {
00205 netsnmp_request_list *requests;
00206 netsnmp_request_list *requestsEnd;
00207 int (*hook_pre) (netsnmp_session *, netsnmp_transport *,
00208 void *, int);
00209 int (*hook_parse) (netsnmp_session *, netsnmp_pdu *,
00210 u_char *, size_t);
00211 int (*hook_post) (netsnmp_session *, netsnmp_pdu *, int);
00212 int (*hook_build) (netsnmp_session *, netsnmp_pdu *,
00213 u_char *, size_t *);
00214 int (*hook_realloc_build) (netsnmp_session *,
00215 netsnmp_pdu *, u_char **,
00216 size_t *, size_t *);
00217 int (*check_packet) (u_char *, size_t);
00218 netsnmp_pdu *(*hook_create_pdu) (netsnmp_transport *,
00219 void *, size_t);
00220
00221 u_char *packet;
00222 size_t packet_len, packet_size;
00223 };
00224
00225
00226
00227
00228 struct session_list {
00229 struct session_list *next;
00230 netsnmp_session *session;
00231 netsnmp_transport *transport;
00232 struct snmp_internal_session *internal;
00233 };
00234
00235
00236
00237 static const char *api_errors[-SNMPERR_MAX + 1] = {
00238 "No error",
00239 "Generic error",
00240 "Invalid local port",
00241 "Unknown host",
00242 "Unknown session",
00243 "Too long",
00244 "No socket",
00245 "Cannot send V2 PDU on V1 session",
00246 "Cannot send V1 PDU on V2 session",
00247 "Bad value for non-repeaters",
00248 "Bad value for max-repetitions",
00249 "Error building ASN.1 representation",
00250 "Failure in sendto",
00251 "Bad parse of ASN.1 type",
00252 "Bad version specified",
00253 "Bad source party specified",
00254 "Bad destination party specified",
00255 "Bad context specified",
00256 "Bad community specified",
00257 "Cannot send noAuth/Priv",
00258 "Bad ACL definition",
00259 "Bad Party definition",
00260 "Session abort failure",
00261 "Unknown PDU type",
00262 "Timeout",
00263 "Failure in recvfrom",
00264 "Unable to determine contextEngineID",
00265 "No securityName specified",
00266 "Unable to determine securityLevel",
00267 "ASN.1 parse error in message",
00268 "Unknown security model in message",
00269 "Invalid message (e.g. msgFlags)",
00270 "Unknown engine ID",
00271 "Unknown user name",
00272 "Unsupported security level",
00273 "Authentication failure (incorrect password, community or key)",
00274 "Not in time window",
00275 "Decryption error",
00276 "SCAPI general failure",
00277 "SCAPI sub-system not configured",
00278 "Key tools not available",
00279 "Unknown Report message",
00280 "USM generic error",
00281 "USM unknown security name (no such user exists)",
00282 "USM unsupported security level (this user has not been configured for that level of security)",
00283 "USM encryption error",
00284 "USM authentication failure (incorrect password or key)",
00285 "USM parse error",
00286 "USM unknown engineID",
00287 "USM not in time window",
00288 "USM decryption error",
00289 "MIB not initialized",
00290 "Value out of range",
00291 "Sub-id out of range",
00292 "Bad sub-id in object identifier",
00293 "Object identifier too long",
00294 "Bad value name",
00295 "Bad value notation",
00296 "Unknown Object Identifier",
00297 "No PDU in snmp_send",
00298 "Missing variables in PDU",
00299 "Bad variable type",
00300 "Out of memory (malloc failure)",
00301 "Kerberos related error",
00302 "Protocol error",
00303 "OID not increasing",
00304 };
00305
00306 static const char *secLevelName[] = {
00307 "BAD_SEC_LEVEL",
00308 "noAuthNoPriv",
00309 "authNoPriv",
00310 "authPriv"
00311 };
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 struct session_list *Sessions = NULL;
00327 static long Reqid = 0;
00328 static long Msgid = 0;
00329 static long Sessid = 0;
00330 static long Transid = 0;
00331 int snmp_errno = 0;
00332
00333
00334
00335
00336
00337
00338
00339 static char snmp_detail[192];
00340 static int snmp_detail_f = 0;
00341
00342
00343
00344
00345 int snmp_build(u_char ** pkt, size_t * pkt_len,
00346 size_t * offset, netsnmp_session * pss,
00347 netsnmp_pdu *pdu);
00348 static int snmp_parse(void *, netsnmp_session *, netsnmp_pdu *,
00349 u_char *, size_t);
00350
00351 static void snmpv3_calc_msg_flags(int, int, u_char *);
00352 static int snmpv3_verify_msg(netsnmp_request_list *, netsnmp_pdu *);
00353 static int snmpv3_build_probe_pdu(netsnmp_pdu **);
00354 static int snmpv3_build(u_char ** pkt, size_t * pkt_len,
00355 size_t * offset, netsnmp_session * session,
00356 netsnmp_pdu *pdu);
00357 static int snmp_parse_version(u_char *, size_t);
00358 static int snmp_resend_request(struct session_list *slp,
00359 netsnmp_request_list *rp,
00360 int incr_retries);
00361 static void register_default_handlers(void);
00362 static struct session_list *snmp_sess_copy(netsnmp_session * pss);
00363 int snmp_get_errno(void);
00364 void snmp_synch_reset(netsnmp_session * notused);
00365 void snmp_synch_setup(netsnmp_session * notused);
00366
00367 #ifndef HAVE_STRERROR
00368 const char *
00369 strerror(int err)
00370 {
00371 extern const char *sys_errlist[];
00372 extern int sys_nerr;
00373
00374 if (err < 0 || err >= sys_nerr)
00375 return "Unknown error";
00376 return sys_errlist[err];
00377 }
00378 #endif
00379
00380 const char *
00381 snmp_pdu_type(int type)
00382 {
00383 static char unknown[20];
00384 switch(type) {
00385 case SNMP_MSG_GET:
00386 return "GET";
00387 case SNMP_MSG_GETNEXT:
00388 return "GETNEXT";
00389 case SNMP_MSG_RESPONSE:
00390 return "RESPONSE";
00391 case SNMP_MSG_SET:
00392 return "SET";
00393 case SNMP_MSG_GETBULK:
00394 return "GETBULK";
00395 case SNMP_MSG_INFORM:
00396 return "INFORM";
00397 case SNMP_MSG_TRAP2:
00398 return "TRAP2";
00399 case SNMP_MSG_REPORT:
00400 return "REPORT";
00401 default:
00402 snprintf(unknown, sizeof(unknown), "?0x%2X?", type);
00403 return unknown;
00404 }
00405 }
00406
00407 #define DEBUGPRINTPDUTYPE(token, type) \
00408 DEBUGDUMPSECTION(token, snmp_pdu_type(type))
00409
00410 long
00411 snmp_get_next_reqid(void)
00412 {
00413 long retVal;
00414 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00415 retVal = 1 + Reqid;
00416 if (!retVal)
00417 retVal = 2;
00418 Reqid = retVal;
00419 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00420 retVal &= 0x7fff;
00421 else
00422 retVal &= 0x7fffffff;
00423
00424 if (!retVal) {
00425 Reqid = retVal = 2;
00426 }
00427 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00428 return retVal;
00429 }
00430
00431 long
00432 snmp_get_next_msgid(void)
00433 {
00434 long retVal;
00435 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00436 retVal = 1 + Msgid;
00437 if (!retVal)
00438 retVal = 2;
00439 Msgid = retVal;
00440 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00441 retVal &= 0x7fff;
00442 else
00443 retVal &= 0x7fffffff;
00444
00445 if (!retVal) {
00446 Msgid = retVal = 2;
00447 }
00448 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00449 return retVal;
00450 }
00451
00452 long
00453 snmp_get_next_sessid(void)
00454 {
00455 long retVal;
00456 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00457 retVal = 1 + Sessid;
00458 if (!retVal)
00459 retVal = 2;
00460 Sessid = retVal;
00461 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00462 retVal &= 0x7fff;
00463 else
00464 retVal &= 0x7fffffff;
00465
00466 if (!retVal) {
00467 Sessid = retVal = 2;
00468 }
00469 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00470 return retVal;
00471 }
00472
00473 long
00474 snmp_get_next_transid(void)
00475 {
00476 long retVal;
00477 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00478 retVal = 1 + Transid;
00479 if (!retVal)
00480 retVal = 2;
00481 Transid = retVal;
00482 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00483 retVal &= 0x7fff;
00484 else
00485 retVal &= 0x7fffffff;
00486
00487 if (!retVal) {
00488 Transid = retVal = 2;
00489 }
00490 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00491 return retVal;
00492 }
00493
00494 void
00495 snmp_perror(const char *prog_string)
00496 {
00497 const char *str;
00498 int xerr;
00499 xerr = snmp_errno;
00500 str = snmp_api_errstring(xerr);
00501 snmp_log(LOG_ERR, "%s: %s\n", prog_string, str);
00502 }
00503
00504 void
00505 snmp_set_detail(const char *detail_string)
00506 {
00507 if (detail_string != NULL) {
00508 strncpy((char *) snmp_detail, detail_string, sizeof(snmp_detail));
00509 snmp_detail[sizeof(snmp_detail) - 1] = '\0';
00510 snmp_detail_f = 1;
00511 }
00512 }
00513
00514
00515
00516
00517
00518
00519
00520 const char *
00521 snmp_api_errstring(int snmp_errnumber)
00522 {
00523 const char *msg = "";
00524 static char msg_buf[SPRINT_MAX_LEN];
00525 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00526 msg = api_errors[-snmp_errnumber];
00527 } else if (snmp_errnumber != SNMPERR_SUCCESS) {
00528 msg = NULL;
00529 }
00530 if (!msg)
00531 snprintf(msg_buf, sizeof(msg_buf), "Unknown error: %d", snmp_errnumber);
00532 else if (snmp_detail_f) {
00533 snprintf(msg_buf, sizeof(msg_buf), "%s (%s)", msg, snmp_detail);
00534 snmp_detail_f = 0;
00535 } else {
00536 strncpy(msg_buf, msg, sizeof(msg_buf));
00537 }
00538 msg_buf[sizeof(msg_buf)-1] = '\0';
00539
00540 return (msg_buf);
00541 }
00542
00543
00544
00545
00546
00547
00548 void
00549 snmp_error(netsnmp_session * psess,
00550 int *p_errno, int *p_snmp_errno, char **p_str)
00551 {
00552 char buf[SPRINT_MAX_LEN];
00553 int snmp_errnumber;
00554
00555 if (p_errno)
00556 *p_errno = psess->s_errno;
00557 if (p_snmp_errno)
00558 *p_snmp_errno = psess->s_snmp_errno;
00559 if (p_str == NULL)
00560 return;
00561
00562 strcpy(buf, "");
00563 snmp_errnumber = psess->s_snmp_errno;
00564 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00565 if (snmp_detail_f) {
00566 snprintf(buf, sizeof(buf), "%s (%s)", api_errors[-snmp_errnumber],
00567 snmp_detail);
00568 snmp_detail_f = 0;
00569 }
00570 else
00571 strncpy(buf, api_errors[-snmp_errnumber], sizeof(buf));
00572 } else {
00573 if (snmp_errnumber)
00574 snprintf(buf, sizeof(buf), "Unknown Error %d", snmp_errnumber);
00575 }
00576 buf[sizeof(buf)-1] = '\0';
00577
00578
00579
00580
00581 if (psess->s_errno) {
00582 const char* error = strerror(psess->s_errno);
00583 if(error == NULL)
00584 error = "Unknown Error";
00585 snprintf (&buf[strlen(buf)], sizeof(buf)-strlen(buf),
00586 " (%s)", error);
00587 }
00588 buf[sizeof(buf)-1] = '\0';
00589 *p_str = strdup(buf);
00590 }
00591
00592
00593
00594
00595 void
00596 snmp_sess_error(void *sessp, int *p_errno, int *p_snmp_errno, char **p_str)
00597 {
00598 struct session_list *slp = (struct session_list *) sessp;
00599
00600 if ((slp) && (slp->session))
00601 snmp_error(slp->session, p_errno, p_snmp_errno, p_str);
00602 }
00603
00604
00605
00606
00607 void
00608 netsnmp_sess_log_error(int priority,
00609 const char *prog_string, netsnmp_session * ss)
00610 {
00611 char *err;
00612 snmp_error(ss, NULL, NULL, &err);
00613 snmp_log(priority, "%s: %s\n", prog_string, err);
00614 SNMP_FREE(err);
00615 }
00616
00617
00618
00619
00620 void
00621 snmp_sess_perror(const char *prog_string, netsnmp_session * ss)
00622 {
00623 netsnmp_sess_log_error(LOG_ERR, prog_string, ss);
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 static char _init_snmp_init_done = 0;
00639 static void
00640 _init_snmp(void)
00641 {
00642
00643 struct timeval tv;
00644 long tmpReqid, tmpMsgid;
00645
00646 if (_init_snmp_init_done)
00647 return;
00648 _init_snmp_init_done = 1;
00649 Reqid = 1;
00650
00651 snmp_res_init();
00652 #ifndef NETSNMP_DISABLE_MIB_LOADING
00653 netsnmp_init_mib_internals();
00654 #endif
00655 netsnmp_tdomain_init();
00656
00657 gettimeofday(&tv, (struct timezone *) 0);
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 #ifdef SVR4
00669 srand48(tv.tv_sec ^ tv.tv_usec);
00670 tmpReqid = lrand48();
00671 tmpMsgid = lrand48();
00672 #else
00673 srandom(tv.tv_sec ^ tv.tv_usec);
00674 tmpReqid = random();
00675 tmpMsgid = random();
00676 #endif
00677
00678 if (tmpReqid == 0)
00679 tmpReqid = 1;
00680 if (tmpMsgid == 0)
00681 tmpMsgid = 1;
00682 Reqid = tmpReqid;
00683 Msgid = tmpMsgid;
00684
00685 netsnmp_register_default_domain("snmp", "udp udp6");
00686 netsnmp_register_default_domain("snmptrap", "udp udp6");
00687
00688 netsnmp_register_default_target("snmp", "udp", ":161");
00689 netsnmp_register_default_target("snmp", "tcp", ":161");
00690 netsnmp_register_default_target("snmp", "udp6", ":161");
00691 netsnmp_register_default_target("snmp", "tcp6", ":161");
00692 netsnmp_register_default_target("snmp", "ipx", "/36879");
00693 netsnmp_register_default_target("snmptrap", "udp", ":162");
00694 netsnmp_register_default_target("snmptrap", "tcp", ":162");
00695 netsnmp_register_default_target("snmptrap", "udp6", ":162");
00696 netsnmp_register_default_target("snmptrap", "tcp6", ":162");
00697 netsnmp_register_default_target("snmptrap", "ipx", "/36880");
00698
00699 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00700 NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH, 16);
00701
00702 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
00703 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
00704 NETSNMP_DS_LIB_REVERSE_ENCODE,
00705 NETSNMP_DEFAULT_ASNENCODING_DIRECTION);
00706 #endif
00707 }
00708
00709
00710
00711
00712
00713
00714 void
00715 snmp_sess_init(netsnmp_session * session)
00716 {
00717 _init_snmp();
00718
00719
00720
00721
00722
00723 memset(session, 0, sizeof(netsnmp_session));
00724 session->remote_port = SNMP_DEFAULT_REMPORT;
00725 session->timeout = SNMP_DEFAULT_TIMEOUT;
00726 session->retries = SNMP_DEFAULT_RETRIES;
00727 session->version = SNMP_DEFAULT_VERSION;
00728 session->securityModel = SNMP_DEFAULT_SECMODEL;
00729 session->rcvMsgMaxSize = SNMP_MAX_MSG_SIZE;
00730 session->flags |= SNMP_FLAGS_DONT_PROBE;
00731 }
00732
00733
00734 static void
00735 register_default_handlers(void)
00736 {
00737 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "dumpPacket",
00738 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET);
00739 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "reverseEncodeBER",
00740 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE);
00741 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "defaultPort",
00742 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT);
00743 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
00744 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defCommunity",
00745 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_COMMUNITY);
00746 #endif
00747 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "noTokenWarnings",
00748 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_TOKEN_WARNINGS);
00749 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noRangeCheck",
00750 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
00751 netsnmp_ds_register_premib(ASN_OCTET_STR, "snmp", "persistentDir",
00752 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PERSISTENT_DIR);
00753 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tempFilePattern",
00754 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_TEMP_FILE_PATTERN);
00755 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noDisplayHint",
00756 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
00757 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "16bitIDs",
00758 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS);
00759 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "clientaddr",
00760 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENT_ADDR);
00761 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverSendBuf",
00762 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERSENDBUF);
00763 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverRecvBuf",
00764 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERRECVBUF);
00765 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientSendBuf",
00766 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTSENDBUF);
00767 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientRecvBuf",
00768 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTRECVBUF);
00769 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentLoad",
00770 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD);
00771 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentSave",
00772 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE);
00773 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp",
00774 "noContextEngineIDDiscovery",
00775 NETSNMP_DS_LIBRARY_ID,
00776 NETSNMP_DS_LIB_NO_DISCOVERY);
00777
00778 netsnmp_register_service_handlers();
00779 }
00780
00781 static int init_snmp_init_done = 0;
00792 void
00793 init_snmp(const char *type)
00794 {
00795 if (init_snmp_init_done) {
00796 return;
00797 }
00798
00799 init_snmp_init_done = 1;
00800
00801
00802
00803
00804 if (type && !netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00805 NETSNMP_DS_LIB_APPTYPE)) {
00806 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
00807 NETSNMP_DS_LIB_APPTYPE, type);
00808 }
00809
00810 _init_snmp();
00811
00812
00813
00814
00815 #ifdef HAVE_SETLOCALE
00816 setlocale(LC_CTYPE, "");
00817 #endif
00818
00819 snmp_debug_init();
00820 netsnmp_container_init_list();
00821 init_callbacks();
00822 init_snmp_logging();
00823 snmp_init_statistics();
00824 register_mib_handlers();
00825 register_default_handlers();
00826 init_snmpv3(type);
00827 init_snmp_alarm();
00828 init_snmp_enum(type);
00829 init_vacm();
00830
00831 read_premib_configs();
00832 #ifndef NETSNMP_DISABLE_MIB_LOADING
00833 netsnmp_init_mib();
00834 #endif
00835
00836 read_configs();
00837
00838 }
00839
00840 void
00841 snmp_store(const char *type)
00842 {
00843 DEBUGMSGTL(("snmp_store", "storing stuff...\n"));
00844 snmp_save_persistent(type);
00845 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL);
00846 snmp_clean_persistent(type);
00847 }
00848
00849
00858 void
00859 snmp_shutdown(const char *type)
00860 {
00861 snmp_store(type);
00862 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, NULL);
00863 shutdown_snmp_logging();
00864 snmp_alarm_unregister_all();
00865 snmp_close_sessions();
00866 #ifndef NETSNMP_DISABLE_MIB_LOADING
00867 shutdown_mib();
00868 #endif
00869 unregister_all_config_handlers();
00870 netsnmp_container_free_list();
00871 clear_sec_mod();
00872 clear_snmp_enum();
00873 netsnmp_clear_tdomain_list();
00874 clear_callback();
00875 netsnmp_ds_shutdown();
00876 clear_user_list();
00877 netsnmp_clear_default_target();
00878 netsnmp_clear_default_domain();
00879 free_etimelist();
00880
00881 init_snmp_init_done = 0;
00882 _init_snmp_init_done = 0;
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 netsnmp_session *
00894 snmp_open(netsnmp_session *session)
00895 {
00896 struct session_list *slp;
00897 slp = (struct session_list *) snmp_sess_open(session);
00898 if (!slp) {
00899 return NULL;
00900 }
00901
00902 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00903 slp->next = Sessions;
00904 Sessions = slp;
00905 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00906
00907 return (slp->session);
00908 }
00909
00910
00911
00912
00913 netsnmp_session *
00914 snmp_open_ex(netsnmp_session *session,
00915 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
00916 void *, int),
00917 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
00918 size_t),
00919 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
00920
00921 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
00922 size_t *),
00923 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
00924 u_char **, size_t *, size_t *),
00925 int (*fcheck) (u_char *, size_t)
00926 )
00927 {
00928 struct session_list *slp;
00929 slp = (struct session_list *) snmp_sess_open(session);
00930 if (!slp) {
00931 return NULL;
00932 }
00933 slp->internal->hook_pre = fpre_parse;
00934 slp->internal->hook_parse = fparse;
00935 slp->internal->hook_post = fpost_parse;
00936 slp->internal->hook_build = fbuild;
00937 slp->internal->hook_realloc_build = frbuild;
00938 slp->internal->check_packet = fcheck;
00939
00940 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00941 slp->next = Sessions;
00942 Sessions = slp;
00943 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00944
00945 return (slp->session);
00946 }
00947
00948 static struct session_list *
00949 _sess_copy(netsnmp_session * in_session)
00950 {
00951 struct session_list *slp;
00952 struct snmp_internal_session *isp;
00953 netsnmp_session *session;
00954 struct snmp_secmod_def *sptr;
00955 char *cp;
00956 u_char *ucp;
00957 size_t i;
00958
00959 in_session->s_snmp_errno = 0;
00960 in_session->s_errno = 0;
00961
00962
00963
00964
00965 slp = (struct session_list *) calloc(1, sizeof(struct session_list));
00966 if (slp == NULL) {
00967 in_session->s_snmp_errno = SNMPERR_MALLOC;
00968 return (NULL);
00969 }
00970
00971 slp->transport = NULL;
00972
00973 isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session));
00974
00975 if (isp == NULL) {
00976 snmp_sess_close(slp);
00977 in_session->s_snmp_errno = SNMPERR_MALLOC;
00978 return (NULL);
00979 }
00980
00981 slp->internal = isp;
00982 slp->session = (netsnmp_session *)malloc(sizeof(netsnmp_session));
00983 if (slp->session == NULL) {
00984 snmp_sess_close(slp);
00985 in_session->s_snmp_errno = SNMPERR_MALLOC;
00986 return (NULL);
00987 }
00988 memmove(slp->session, in_session, sizeof(netsnmp_session));
00989 session = slp->session;
00990
00991
00992
00993
00994
00995 session->peername = NULL;
00996 session->community = NULL;
00997 session->contextEngineID = NULL;
00998 session->contextName = NULL;
00999 session->securityEngineID = NULL;
01000 session->securityName = NULL;
01001 session->securityAuthProto = NULL;
01002 session->securityPrivProto = NULL;
01003
01004
01005
01006
01007
01008
01009 if (in_session->peername != NULL) {
01010 session->peername = (char *)malloc(strlen(in_session->peername) + 1);
01011 if (session->peername == NULL) {
01012 snmp_sess_close(slp);
01013 in_session->s_snmp_errno = SNMPERR_MALLOC;
01014 return (NULL);
01015 }
01016 strcpy(session->peername, in_session->peername);
01017 }
01018
01019
01020
01021
01022 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
01023 if (in_session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) {
01024 ucp = (u_char *) malloc(in_session->community_len);
01025 if (ucp != NULL)
01026 memmove(ucp, in_session->community, in_session->community_len);
01027 } else {
01028 if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01029 NETSNMP_DS_LIB_COMMUNITY)) != NULL) {
01030 session->community_len = strlen(cp);
01031 ucp = (u_char *) malloc(session->community_len);
01032 if (ucp)
01033 memmove(ucp, cp, session->community_len);
01034 } else {
01035 #ifdef NETSNMP_NO_ZEROLENGTH_COMMUNITY
01036 session->community_len = strlen(DEFAULT_COMMUNITY);
01037 ucp = (u_char *) malloc(session->community_len);
01038 if (ucp)
01039 memmove(ucp, DEFAULT_COMMUNITY, session->community_len);
01040 #else
01041 ucp = (u_char *) strdup("");
01042 #endif
01043 }
01044 }
01045
01046 if (ucp == NULL) {
01047 snmp_sess_close(slp);
01048 in_session->s_snmp_errno = SNMPERR_MALLOC;
01049 return (NULL);
01050 }
01051 session->community = ucp;
01052 #endif
01053
01054 if (session->securityLevel <= 0) {
01055 session->securityLevel =
01056 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECLEVEL);
01057 }
01058
01059 if (session->securityLevel == 0)
01060 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
01061
01062 if (in_session->securityAuthProtoLen > 0) {
01063 session->securityAuthProto =
01064 snmp_duplicate_objid(in_session->securityAuthProto,
01065 in_session->securityAuthProtoLen);
01066 if (session->securityAuthProto == NULL) {
01067 snmp_sess_close(slp);
01068 in_session->s_snmp_errno = SNMPERR_MALLOC;
01069 return (NULL);
01070 }
01071 } else if (get_default_authtype(&i) != NULL) {
01072 session->securityAuthProto =
01073 snmp_duplicate_objid(get_default_authtype(NULL), i);
01074 session->securityAuthProtoLen = i;
01075 }
01076
01077 if (in_session->securityPrivProtoLen > 0) {
01078 session->securityPrivProto =
01079 snmp_duplicate_objid(in_session->securityPrivProto,
01080 in_session->securityPrivProtoLen);
01081 if (session->securityPrivProto == NULL) {
01082 snmp_sess_close(slp);
01083 in_session->s_snmp_errno = SNMPERR_MALLOC;
01084 return (NULL);
01085 }
01086 } else if (get_default_privtype(&i) != NULL) {
01087 session->securityPrivProto =
01088 snmp_duplicate_objid(get_default_privtype(NULL), i);
01089 session->securityPrivProtoLen = i;
01090 }
01091
01092 if (in_session->securityEngineIDLen > 0) {
01093 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01094 if (ucp == NULL) {
01095 snmp_sess_close(slp);
01096 in_session->s_snmp_errno = SNMPERR_MALLOC;
01097 return (NULL);
01098 }
01099 memmove(ucp, in_session->securityEngineID,
01100 in_session->securityEngineIDLen);
01101 session->securityEngineID = ucp;
01102
01103 }
01104
01105 if (in_session->contextEngineIDLen > 0) {
01106 ucp = (u_char *) malloc(in_session->contextEngineIDLen);
01107 if (ucp == NULL) {
01108 snmp_sess_close(slp);
01109 in_session->s_snmp_errno = SNMPERR_MALLOC;
01110 return (NULL);
01111 }
01112 memmove(ucp, in_session->contextEngineID,
01113 in_session->contextEngineIDLen);
01114 session->contextEngineID = ucp;
01115 } else if (in_session->securityEngineIDLen > 0) {
01116
01117
01118
01119 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01120 if (ucp == NULL) {
01121 snmp_sess_close(slp);
01122 in_session->s_snmp_errno = SNMPERR_MALLOC;
01123 return (NULL);
01124 }
01125 memmove(ucp, in_session->securityEngineID,
01126 in_session->securityEngineIDLen);
01127 session->contextEngineID = ucp;
01128 session->contextEngineIDLen = in_session->securityEngineIDLen;
01129 }
01130
01131 if (in_session->contextName) {
01132 session->contextName = strdup(in_session->contextName);
01133 if (session->contextName == NULL) {
01134 snmp_sess_close(slp);
01135 return (NULL);
01136 }
01137 } else {
01138 if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01139 NETSNMP_DS_LIB_CONTEXT)) != NULL)
01140 cp = strdup(cp);
01141 else
01142 cp = strdup(SNMP_DEFAULT_CONTEXT);
01143 if (cp == NULL) {
01144 snmp_sess_close(slp);
01145 return (NULL);
01146 }
01147 session->contextName = cp;
01148 session->contextNameLen = strlen(cp);
01149 }
01150
01151 if (in_session->securityName) {
01152 session->securityName = strdup(in_session->securityName);
01153 if (session->securityName == NULL) {
01154 snmp_sess_close(slp);
01155 return (NULL);
01156 }
01157 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01158 NETSNMP_DS_LIB_SECNAME)) != NULL) {
01159 cp = strdup(cp);
01160 if (cp == NULL) {
01161 snmp_sess_close(slp);
01162 return (NULL);
01163 }
01164 session->securityName = cp;
01165 session->securityNameLen = strlen(cp);
01166 }
01167
01168 if ((in_session->securityAuthKeyLen <= 0) &&
01169 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01170 NETSNMP_DS_LIB_AUTHMASTERKEY)))) {
01171 size_t buflen = sizeof(session->securityAuthKey);
01172 u_char *tmpp = session->securityAuthKey;
01173 session->securityAuthKeyLen = 0;
01174
01175 if (!snmp_hex_to_binary(&tmpp, &buflen,
01176 &session->securityAuthKeyLen, 0, cp)) {
01177 snmp_set_detail("error parsing authentication master key");
01178 snmp_sess_close(slp);
01179 return NULL;
01180 }
01181 } else if ((in_session->securityAuthKeyLen <= 0) &&
01182 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01183 NETSNMP_DS_LIB_AUTHPASSPHRASE)) ||
01184 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01185 NETSNMP_DS_LIB_PASSPHRASE)))) {
01186 session->securityAuthKeyLen = USM_AUTH_KU_LEN;
01187 if (generate_Ku(session->securityAuthProto,
01188 session->securityAuthProtoLen,
01189 (u_char *) cp, strlen(cp),
01190 session->securityAuthKey,
01191 &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
01192 snmp_set_detail
01193 ("Error generating a key (Ku) from the supplied authentication pass phrase.");
01194 snmp_sess_close(slp);
01195 return NULL;
01196 }
01197 }
01198
01199
01200 if ((in_session->securityPrivKeyLen <= 0) &&
01201 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01202 NETSNMP_DS_LIB_PRIVMASTERKEY)))) {
01203 size_t buflen = sizeof(session->securityPrivKey);
01204 u_char *tmpp = session->securityPrivKey;
01205 session->securityPrivKeyLen = 0;
01206
01207 if (!snmp_hex_to_binary(&tmpp, &buflen,
01208 &session->securityPrivKeyLen, 0, cp)) {
01209 snmp_set_detail("error parsing encryption master key");
01210 snmp_sess_close(slp);
01211 return NULL;
01212 }
01213 } else if ((in_session->securityPrivKeyLen <= 0) &&
01214 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01215 NETSNMP_DS_LIB_PRIVPASSPHRASE)) ||
01216 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01217 NETSNMP_DS_LIB_PASSPHRASE)))) {
01218 session->securityPrivKeyLen = USM_PRIV_KU_LEN;
01219 if (generate_Ku(session->securityAuthProto,
01220 session->securityAuthProtoLen,
01221 (u_char *) cp, strlen(cp),
01222 session->securityPrivKey,
01223 &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
01224 snmp_set_detail
01225 ("Error generating a key (Ku) from the supplied privacy pass phrase.");
01226 snmp_sess_close(slp);
01227 return NULL;
01228 }
01229 }
01230
01231 if (session->retries == SNMP_DEFAULT_RETRIES)
01232 session->retries = DEFAULT_RETRIES;
01233 if (session->timeout == SNMP_DEFAULT_TIMEOUT)
01234 session->timeout = DEFAULT_TIMEOUT;
01235 session->sessid = snmp_get_next_sessid();
01236
01237 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SESSION_INIT,
01238 session);
01239
01240 if ((sptr = find_sec_mod(session->securityModel)) != NULL &&
01241 sptr->session_open != NULL) {
01242
01243
01244
01245 (*sptr->session_open) (session);
01246 }
01247
01248 return (slp);
01249 }
01250
01251 static struct session_list *
01252 snmp_sess_copy(netsnmp_session * pss)
01253 {
01254 struct session_list *psl;
01255 psl = _sess_copy(pss);
01256 if (!psl) {
01257 if (!pss->s_snmp_errno) {
01258 pss->s_snmp_errno = SNMPERR_GENERR;
01259 }
01260 SET_SNMP_ERROR(pss->s_snmp_errno);
01261 }
01262 return psl;
01263 }
01264
01273 int
01274 snmpv3_probe_contextEngineID_rfc5343(void *slp, netsnmp_session *session) {
01275 netsnmp_pdu *pdu = NULL, *response = NULL;
01276 static oid snmpEngineIDoid[] = { 1,3,6,1,6,3,10,2,1,1,0};
01277 static size_t snmpEngineIDoid_len = 11;
01278
01279 static char probeEngineID[] = { (char)0x80, 0, 0, 0, 6 };
01280 static size_t probeEngineID_len = sizeof(probeEngineID);
01281
01282 int status;
01283
01284 pdu = snmp_pdu_create(SNMP_MSG_GET);
01285 if (!pdu)
01286 return SNMP_ERR_GENERR;
01287 pdu->version = SNMP_VERSION_3;
01288
01289 if (session->securityName) {
01290 pdu->securityName = strdup(session->securityName);
01291 pdu->securityNameLen = strlen(pdu->securityName);
01292 }
01293 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
01294 pdu->securityModel = session->securityModel;
01295 if (memdup(&pdu->contextEngineID, probeEngineID, probeEngineID_len) !=
01296 SNMPERR_SUCCESS) {
01297 snmp_log(LOG_ERR, "failed to clone memory for rfc5343 probe\n");
01298 return SNMP_ERR_GENERR;
01299 }
01300 pdu->contextEngineIDLen = probeEngineID_len;
01301
01302 snmp_add_null_var(pdu, snmpEngineIDoid, snmpEngineIDoid_len);
01303
01304 DEBUGMSGTL(("snmp_api", "probing for engineID using rfc5343 methods...\n"));
01305 session->flags |= SNMP_FLAGS_DONT_PROBE;
01306 status = snmp_sess_synch_response(slp, pdu, &response);
01307
01308 if ((response == NULL) || (status != STAT_SUCCESS)) {
01309 snmp_log(LOG_ERR, "failed rfc5343 contextEngineID probing\n");
01310 return SNMP_ERR_GENERR;
01311 }
01312
01313
01314 if (NULL != response->variables &&
01315 NULL != response->variables->name &&
01316 snmp_oid_compare(response->variables->name,
01317 response->variables->name_length,
01318 snmpEngineIDoid, snmpEngineIDoid_len) == 0 &&
01319 ASN_OCTET_STR == response->variables->type &&
01320 NULL != response->variables->val.string &&
01321 response->variables->val_len > 0) {
01322 if (memdup(&session->contextEngineID,
01323 response->variables->val.string,
01324 response->variables->val_len) != SNMPERR_SUCCESS) {
01325 snmp_log(LOG_ERR, "failed rfc5343 contextEngineID probing: memory allocation failed\n");
01326 return SNMP_ERR_GENERR;
01327 }
01328
01329
01330
01331 if (memdup(&session->securityEngineID,
01332 response->variables->val.string,
01333 response->variables->val_len) != SNMPERR_SUCCESS) {
01334 snmp_log(LOG_ERR, "failed rfc5343 securityEngineID probing: memory allocation failed\n");
01335 return SNMP_ERR_GENERR;
01336 }
01337
01338 session->securityEngineIDLen = session->contextEngineIDLen =
01339 response->variables->val_len;
01340
01341 if (snmp_get_do_debugging()) {
01342 int i;
01343 DEBUGMSGTL(("snmp_sess_open",
01344 " probe found engineID: "));
01345 for (i = 0; i < session->securityEngineIDLen; i++)
01346 DEBUGMSG(("snmp_sess_open", "%02x",
01347 session->securityEngineID[i]));
01348 DEBUGMSG(("snmp_sess_open", "\n"));
01349 }
01350 }
01351 return SNMPERR_SUCCESS;
01352 }
01353
01354
01370 int
01371 snmpv3_engineID_probe(struct session_list *slp,
01372 netsnmp_session * in_session)
01373 {
01374 netsnmp_pdu *pdu = NULL, *response = NULL;
01375 netsnmp_session *session;
01376 unsigned int i;
01377 int status;
01378
01379 if (slp == NULL || slp->session == NULL) {
01380 return 0;
01381 }
01382
01383 session = slp->session;
01384
01385
01386
01387
01388
01389
01390
01391 if ((session->flags & SNMP_FLAGS_DONT_PROBE) == SNMP_FLAGS_DONT_PROBE)
01392 return 1;
01393
01394 if (session->version == SNMP_VERSION_3) {
01395 struct snmp_secmod_def *sptr = find_sec_mod(session->securityModel);
01396
01397 if (NULL != sptr && NULL != sptr->probe_engineid) {
01398 DEBUGMSGTL(("snmp_api", "probing for engineID using security model callback...\n"));
01399
01400 status = (*sptr->probe_engineid) (slp, session);
01401 if (status)
01402 return 0;
01403 return 1;
01404 } else if (session->securityEngineIDLen == 0) {
01405 if (snmpv3_build_probe_pdu(&pdu) != 0) {
01406 DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n"));
01407 return 0;
01408 }
01409 DEBUGMSGTL(("snmp_api", "probing for engineID...\n"));
01410 session->flags |= SNMP_FLAGS_DONT_PROBE;
01411 status = snmp_sess_synch_response(slp, pdu, &response);
01412
01413 if ((response == NULL) && (status == STAT_SUCCESS)) {
01414 status = STAT_ERROR;
01415 }
01416
01417 switch (status) {
01418 case STAT_SUCCESS:
01419 in_session->s_snmp_errno = SNMPERR_INVALID_MSG;
01420 DEBUGMSGTL(("snmp_sess_open",
01421 "error: expected Report as response to probe: %s (%ld)\n",
01422 snmp_errstring(response->errstat),
01423 response->errstat));
01424 break;
01425 case STAT_ERROR:
01426 in_session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
01427 break;
01428 case STAT_TIMEOUT:
01429 in_session->s_snmp_errno = SNMPERR_TIMEOUT;
01430 default:
01431 DEBUGMSGTL(("snmp_sess_open",
01432 "unable to connect with remote engine: %s (%d)\n",
01433 snmp_api_errstring(session->s_snmp_errno),
01434 session->s_snmp_errno));
01435 break;
01436 }
01437
01438 if (slp->session->securityEngineIDLen == 0) {
01439 DEBUGMSGTL(("snmp_api",
01440 "unable to determine remote engine ID\n"));
01441 return 0;
01442 }
01443
01444 in_session->s_snmp_errno = SNMPERR_SUCCESS;
01445 if (snmp_get_do_debugging()) {
01446 DEBUGMSGTL(("snmp_sess_open",
01447 " probe found engineID: "));
01448 for (i = 0; i < slp->session->securityEngineIDLen; i++)
01449 DEBUGMSG(("snmp_sess_open", "%02x",
01450 slp->session->securityEngineID[i]));
01451 DEBUGMSG(("snmp_sess_open", "\n"));
01452 }
01453 }
01454
01455
01456
01457
01458 if (session->engineBoots || session->engineTime) {
01459 set_enginetime(session->securityEngineID,
01460 session->securityEngineIDLen,
01461 session->engineBoots, session->engineTime,
01462 TRUE);
01463 }
01464
01465 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01466 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01467 DEBUGMSGTL(("snmp_api",
01468 "snmpv3_engine_probe(): failed(2) to create a new user from session\n"));
01469 return 0;
01470 }
01471 }
01472
01473 return 1;
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490 static void *
01491 _sess_open(netsnmp_session * in_session)
01492 {
01493 netsnmp_transport *transport = NULL;
01494
01495 in_session->s_snmp_errno = 0;
01496 in_session->s_errno = 0;
01497
01498 _init_snmp();
01499
01500 {
01501 char *clientaddr_save = NULL;
01502
01503 if (NULL != in_session->localname) {
01504 clientaddr_save =
01505 netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01506 NETSNMP_DS_LIB_CLIENT_ADDR);
01507 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01508 NETSNMP_DS_LIB_CLIENT_ADDR,
01509 in_session->localname);
01510 }
01511
01512 if (in_session->flags & SNMP_FLAGS_STREAM_SOCKET) {
01513 transport =
01514 netsnmp_tdomain_transport_full("snmp", in_session->peername,
01515 in_session->local_port, "tcp",
01516 NULL);
01517 } else {
01518 transport =
01519 netsnmp_tdomain_transport_full("snmp", in_session->peername,
01520 in_session->local_port, "udp",
01521 NULL);
01522 }
01523
01524 if (NULL != clientaddr_save)
01525 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01526 NETSNMP_DS_LIB_CLIENT_ADDR, clientaddr_save);
01527 }
01528
01529 #if defined(SO_BROADCAST) && defined(SOL_SOCKET)
01530 if ( transport != 0 && (in_session->flags & SNMP_FLAGS_UDP_BROADCAST) ) {
01531 int b = 1;
01532 int rc;
01533
01534 rc = setsockopt(transport->sock, SOL_SOCKET, SO_BROADCAST,
01535 (char *)&b, sizeof(b));
01536
01537 if ( rc != 0 ) {
01538 in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
01539 in_session->s_errno = errno;
01540
01541 DEBUGMSGTL(("_sess_open", "couldn't enable UDP_BROADCAST\n"));
01542 return NULL;
01543 }
01544 }
01545 #endif
01546
01547 if (transport == NULL) {
01548 DEBUGMSGTL(("_sess_open", "couldn't interpret peername\n"));
01549 in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
01550 in_session->s_errno = errno;
01551 snmp_set_detail(in_session->peername);
01552 return NULL;
01553 }
01554
01555 return snmp_sess_add(in_session, transport, NULL, NULL);
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 netsnmp_session *
01571 snmp_add(netsnmp_session * in_session,
01572 netsnmp_transport *transport,
01573 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *, void *,
01574 int), int (*fpost_parse) (netsnmp_session *,
01575 netsnmp_pdu *, int))
01576 {
01577 struct session_list *slp;
01578 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01579 fpre_parse, NULL,
01580 fpost_parse, NULL, NULL,
01581 NULL, NULL);
01582 if (slp == NULL) {
01583 return NULL;
01584 }
01585
01586 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01587 slp->next = Sessions;
01588 Sessions = slp;
01589 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01590
01591 return (slp->session);
01592 }
01593
01594 netsnmp_session *
01595 snmp_add_full(netsnmp_session * in_session,
01596 netsnmp_transport *transport,
01597 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01598 void *, int),
01599 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01600 size_t),
01601 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
01602 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01603 size_t *), int (*frbuild) (netsnmp_session *,
01604 netsnmp_pdu *,
01605 u_char **,
01606 size_t *,
01607 size_t *),
01608 int (*fcheck) (u_char *, size_t),
01609 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01610 size_t))
01611 {
01612 struct session_list *slp;
01613 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01614 fpre_parse, fparse,
01615 fpost_parse, fbuild,
01616 frbuild, fcheck,
01617 fcreate_pdu);
01618 if (slp == NULL) {
01619 return NULL;
01620 }
01621
01622 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01623 slp->next = Sessions;
01624 Sessions = slp;
01625 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01626
01627 return (slp->session);
01628 }
01629
01630
01631
01632 void *
01633 snmp_sess_add_ex(netsnmp_session * in_session,
01634 netsnmp_transport *transport,
01635 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01636 void *, int),
01637 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01638 size_t),
01639 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *,
01640 int),
01641 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01642 size_t *),
01643 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
01644 u_char **, size_t *, size_t *),
01645 int (*fcheck) (u_char *, size_t),
01646 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01647 size_t))
01648 {
01649 struct session_list *slp;
01650
01651 _init_snmp();
01652
01653 if (transport == NULL)
01654 return NULL;
01655
01656 if (in_session == NULL) {
01657 transport->f_close(transport);
01658 netsnmp_transport_free(transport);
01659 return NULL;
01660 }
01661
01662 DEBUGMSGTL(("snmp_sess_add", "fd %d\n", transport->sock));
01663
01664 if ((slp = snmp_sess_copy(in_session)) == NULL) {
01665 transport->f_close(transport);
01666 netsnmp_transport_free(transport);
01667 return (NULL);
01668 }
01669
01670 slp->transport = transport;
01671 slp->internal->hook_pre = fpre_parse;
01672 slp->internal->hook_parse = fparse;
01673 slp->internal->hook_post = fpost_parse;
01674 slp->internal->hook_build = fbuild;
01675 slp->internal->hook_realloc_build = frbuild;
01676 slp->internal->check_packet = fcheck;
01677 slp->internal->hook_create_pdu = fcreate_pdu;
01678
01679 slp->session->rcvMsgMaxSize = transport->msgMaxSize;
01680
01681 if (slp->session->version == SNMP_VERSION_3) {
01682 DEBUGMSGTL(("snmp_sess_add",
01683 "adding v3 session -- maybe engineID probe now\n"));
01684 if (!snmpv3_engineID_probe(slp, in_session)) {
01685 DEBUGMSGTL(("snmp_sess_add", "engine ID probe failed\n"));
01686 snmp_sess_close(slp);
01687 return NULL;
01688 }
01689 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01690 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01691 DEBUGMSGTL(("snmp_api",
01692 "snmp_sess_add(): failed(2) to create a new user from session\n"));
01693 snmp_sess_close(slp);
01694 return NULL;
01695 }
01696 }
01697
01698 slp->session->flags &= ~SNMP_FLAGS_DONT_PROBE;
01699
01700 return (void *) slp;
01701 }
01702
01703
01704
01705 void *
01706 snmp_sess_add(netsnmp_session * in_session,
01707 netsnmp_transport *transport,
01708 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01709 void *, int),
01710 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int))
01711 {
01712 return snmp_sess_add_ex(in_session, transport, fpre_parse, NULL,
01713 fpost_parse, NULL, NULL, NULL, NULL);
01714 }
01715
01716
01717
01718 void *
01719 snmp_sess_open(netsnmp_session * pss)
01720 {
01721 void *pvoid;
01722 pvoid = _sess_open(pss);
01723 if (!pvoid) {
01724 SET_SNMP_ERROR(pss->s_snmp_errno);
01725 }
01726 return pvoid;
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 int
01746 create_user_from_session(netsnmp_session * session)
01747 {
01748 struct usmUser *user;
01749 int user_just_created = 0;
01750 char *cp;
01751
01752
01753
01754
01755
01756 if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) ||
01757 session->securityModel != SNMP_SEC_MODEL_USM ||
01758 session->version != SNMP_VERSION_3 ||
01759 session->securityNameLen == 0 ||
01760 session->securityEngineIDLen == 0)
01761 return SNMPERR_SUCCESS;
01762
01763 session->flags |= SNMP_FLAGS_USER_CREATED;
01764
01765
01766
01767
01768
01769 user = usm_get_user_from_list(session->securityEngineID,
01770 session->securityEngineIDLen,
01771 session->securityName,
01772 usm_get_userList(), 0);
01773 if (user == NULL) {
01774 DEBUGMSGTL(("snmp_api", "Building user %s...\n",
01775 session->securityName));
01776
01777
01778
01779 user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
01780 if (user == NULL)
01781 return SNMPERR_GENERR;
01782
01783
01784
01785
01786 if (session->securityName) {
01787 user->name = strdup(session->securityName);
01788 user->secName = strdup(session->securityName);
01789 if (user->name == NULL || user->secName == NULL) {
01790 usm_free_user(user);
01791 return SNMPERR_GENERR;
01792 }
01793 }
01794
01795
01796
01797
01798 if (memdup(&user->engineID, session->securityEngineID,
01799 session->securityEngineIDLen) != SNMPERR_SUCCESS) {
01800 usm_free_user(user);
01801 return SNMPERR_GENERR;
01802 }
01803 user->engineIDLen = session->securityEngineIDLen;
01804
01805 user_just_created = 1;
01806 }
01807
01808
01809
01810 if (session->securityAuthProto != NULL) {
01811 SNMP_FREE(user->authProtocol);
01812 user->authProtocol =
01813 snmp_duplicate_objid(session->securityAuthProto,
01814 session->securityAuthProtoLen);
01815 if (user->authProtocol == NULL) {
01816 usm_free_user(user);
01817 return SNMPERR_GENERR;
01818 }
01819 user->authProtocolLen = session->securityAuthProtoLen;
01820 }
01821
01822
01823
01824
01825 if (session->securityPrivProto != NULL) {
01826 SNMP_FREE(user->privProtocol);
01827 user->privProtocol =
01828 snmp_duplicate_objid(session->securityPrivProto,
01829 session->securityPrivProtoLen);
01830 if (user->privProtocol == NULL) {
01831 usm_free_user(user);
01832 return SNMPERR_GENERR;
01833 }
01834 user->privProtocolLen = session->securityPrivProtoLen;
01835 }
01836
01837
01838
01839
01840 if (session->securityAuthLocalKey != NULL
01841 && session->securityAuthLocalKeyLen != 0) {
01842
01843 SNMP_FREE(user->authKey);
01844 if (memdup(&user->authKey, session->securityAuthLocalKey,
01845 session->securityAuthLocalKeyLen) != SNMPERR_SUCCESS) {
01846 usm_free_user(user);
01847 return SNMPERR_GENERR;
01848 }
01849 user->authKeyLen = session->securityAuthLocalKeyLen;
01850 } else if (session->securityAuthKey != NULL
01851 && session->securityAuthKeyLen != 0) {
01852 SNMP_FREE(user->authKey);
01853 user->authKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
01854 if (user->authKey == NULL) {
01855 usm_free_user(user);
01856 return SNMPERR_GENERR;
01857 }
01858 user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
01859 if (generate_kul(user->authProtocol, user->authProtocolLen,
01860 session->securityEngineID,
01861 session->securityEngineIDLen,
01862 session->securityAuthKey,
01863 session->securityAuthKeyLen, user->authKey,
01864 &user->authKeyLen) != SNMPERR_SUCCESS) {
01865 usm_free_user(user);
01866 return SNMPERR_GENERR;
01867 }
01868 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01869 NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) {
01870 size_t buflen = USM_AUTH_KU_LEN;
01871 SNMP_FREE(user->authKey);
01872 user->authKey = (u_char *)malloc(buflen);
01873 user->authKeyLen = 0;
01874
01875 if (!snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen,
01876 0, cp)) {
01877 usm_free_user(user);
01878 return SNMPERR_GENERR;
01879 }
01880 }
01881
01882
01883
01884
01885 if (session->securityPrivLocalKey != NULL
01886 && session->securityPrivLocalKeyLen != 0) {
01887
01888 SNMP_FREE(user->privKey);
01889 if (memdup(&user->privKey, session->securityPrivLocalKey,
01890 session->securityPrivLocalKeyLen) != SNMPERR_SUCCESS) {
01891 usm_free_user(user);
01892 return SNMPERR_GENERR;
01893 }
01894 user->privKeyLen = session->securityPrivLocalKeyLen;
01895 } else if (session->securityPrivKey != NULL
01896 && session->securityPrivKeyLen != 0) {
01897 SNMP_FREE(user->privKey);
01898 user->privKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
01899 if (user->privKey == NULL) {
01900 usm_free_user(user);
01901 return SNMPERR_GENERR;
01902 }
01903 user->privKeyLen = USM_LENGTH_KU_HASHBLOCK;
01904 if (generate_kul(user->authProtocol, user->authProtocolLen,
01905 session->securityEngineID,
01906 session->securityEngineIDLen,
01907 session->securityPrivKey,
01908 session->securityPrivKeyLen, user->privKey,
01909 &user->privKeyLen) != SNMPERR_SUCCESS) {
01910 usm_free_user(user);
01911 return SNMPERR_GENERR;
01912 }
01913 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01914 NETSNMP_DS_LIB_PRIVLOCALIZEDKEY))) {
01915 size_t buflen = USM_PRIV_KU_LEN;
01916 SNMP_FREE(user->privKey);
01917 user->privKey = (u_char *)malloc(buflen);
01918 user->privKeyLen = 0;
01919
01920 if (!snmp_hex_to_binary(&user->privKey, &buflen, &user->privKeyLen,
01921 0, cp)) {
01922 usm_free_user(user);
01923 return SNMPERR_GENERR;
01924 }
01925 }
01926
01927 if (user_just_created) {
01928
01929
01930
01931 user->userStatus = RS_ACTIVE;
01932 user->userStorageType = ST_READONLY;
01933 usm_add_user(user);
01934 }
01935
01936 return SNMPERR_SUCCESS;
01937
01938
01939 }
01940
01941
01942
01943
01944
01945
01946
01947
01948 static void
01949 snmp_free_session(netsnmp_session * s)
01950 {
01951 if (s) {
01952 SNMP_FREE(s->peername);
01953 SNMP_FREE(s->community);
01954 SNMP_FREE(s->contextEngineID);
01955 SNMP_FREE(s->contextName);
01956 SNMP_FREE(s->securityEngineID);
01957 SNMP_FREE(s->securityName);
01958 SNMP_FREE(s->securityAuthProto);
01959 SNMP_FREE(s->securityPrivProto);
01960 SNMP_FREE(s->paramName);
01961
01962
01963
01964
01965 netsnmp_callback_clear_client_arg(s, 0, 0);
01966
01967 free((char *) s);
01968 }
01969 }
01970
01971
01972
01973
01974
01975
01976 int
01977 snmp_sess_close(void *sessp)
01978 {
01979 struct session_list *slp = (struct session_list *) sessp;
01980 netsnmp_transport *transport;
01981 struct snmp_internal_session *isp;
01982 netsnmp_session *sesp = NULL;
01983 struct snmp_secmod_def *sptr;
01984
01985 if (slp == NULL) {
01986 return 0;
01987 }
01988
01989 if (slp->session != NULL &&
01990 (sptr = find_sec_mod(slp->session->securityModel)) != NULL &&
01991 sptr->session_close != NULL) {
01992 (*sptr->session_close) (slp->session);
01993 }
01994
01995 isp = slp->internal;
01996 slp->internal = NULL;
01997
01998 if (isp) {
01999 netsnmp_request_list *rp, *orp;
02000
02001 SNMP_FREE(isp->packet);
02002
02003
02004
02005
02006 rp = isp->requests;
02007 while (rp) {
02008 orp = rp;
02009 rp = rp->next_request;
02010 snmp_free_pdu(orp->pdu);
02011 free((char *) orp);
02012 }
02013
02014 free((char *) isp);
02015 }
02016
02017 transport = slp->transport;
02018 slp->transport = NULL;
02019
02020 if (transport) {
02021 transport->f_close(transport);
02022 netsnmp_transport_free(transport);
02023 }
02024
02025 sesp = slp->session;
02026 slp->session = NULL;
02027
02028
02029
02030
02031
02032
02033
02034 if (sesp != NULL && sesp->subsession != NULL) {
02035 netsnmp_session *subsession = sesp->subsession, *tmpsub;
02036
02037 while (subsession != NULL) {
02038 DEBUGMSGTL(("snmp_sess_close",
02039 "closing session %p, subsession %p\n", sesp,
02040 subsession));
02041 tmpsub = subsession->next;
02042 snmp_free_session(subsession);
02043 subsession = tmpsub;
02044 }
02045 }
02046
02047 snmp_free_session(sesp);
02048 free((char *) slp);
02049 return 1;
02050 }
02051
02052 int
02053 snmp_close(netsnmp_session * session)
02054 {
02055 struct session_list *slp = NULL, *oslp = NULL;
02056
02057 {
02058 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
02059 if (Sessions && Sessions->session == session) {
02060 slp = Sessions;
02061 Sessions = slp->next;
02062 } else {
02063 for (slp = Sessions; slp; slp = slp->next) {
02064 if (slp->session == session) {
02065 if (oslp)
02066 oslp->next = slp->next;
02067 break;
02068 }
02069 oslp = slp;
02070 }
02071 }
02072 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
02073 }
02074 if (slp == NULL) {
02075 return 0;
02076 }
02077 return snmp_sess_close((void *) slp);
02078 }
02079
02080 int
02081 snmp_close_sessions(void)
02082 {
02083 struct session_list *slp;
02084
02085 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
02086 while (Sessions) {
02087 slp = Sessions;
02088 Sessions = Sessions->next;
02089 snmp_sess_close((void *) slp);
02090 }
02091 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
02092 return 1;
02093 }
02094
02095 static int
02096 snmpv3_build_probe_pdu(netsnmp_pdu **pdu)
02097 {
02098 struct usmUser *user;
02099
02100
02101
02102
02103 if (!pdu)
02104 return -1;
02105 *pdu = snmp_pdu_create(SNMP_MSG_GET);
02106 if (!(*pdu))
02107 return -1;
02108 (*pdu)->version = SNMP_VERSION_3;
02109 (*pdu)->securityName = strdup("");
02110 (*pdu)->securityNameLen = strlen((*pdu)->securityName);
02111 (*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
02112 (*pdu)->securityModel = SNMP_SEC_MODEL_USM;
02113
02114
02115
02116
02117 user = usm_get_user(NULL, 0, (*pdu)->securityName);
02118 if (user == NULL) {
02119 user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
02120 if (user == NULL) {
02121 snmp_free_pdu(*pdu);
02122 *pdu = (netsnmp_pdu *) NULL;
02123 return -1;
02124 }
02125 user->name = strdup((*pdu)->securityName);
02126 user->secName = strdup((*pdu)->securityName);
02127 user->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid);
02128 user->authProtocol =
02129 snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen);
02130 user->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid);
02131 user->privProtocol =
02132 snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen);
02133 usm_add_user(user);
02134 }
02135 return 0;
02136 }
02137
02138 static void
02139 snmpv3_calc_msg_flags(int sec_level, int msg_command, u_char * flags)
02140 {
02141 *flags = 0;
02142 if (sec_level == SNMP_SEC_LEVEL_AUTHNOPRIV)
02143 *flags = SNMP_MSG_FLAG_AUTH_BIT;
02144 else if (sec_level == SNMP_SEC_LEVEL_AUTHPRIV)
02145 *flags = SNMP_MSG_FLAG_AUTH_BIT | SNMP_MSG_FLAG_PRIV_BIT;
02146
02147 if (SNMP_CMD_CONFIRMED(msg_command))
02148 *flags |= SNMP_MSG_FLAG_RPRT_BIT;
02149
02150 return;
02151 }
02152
02153 static int
02154 snmpv3_verify_msg(netsnmp_request_list *rp, netsnmp_pdu *pdu)
02155 {
02156 netsnmp_pdu *rpdu;
02157
02158 if (!rp || !rp->pdu || !pdu)
02159 return 0;
02160
02161
02162
02163 if (pdu->command == SNMP_MSG_REPORT)
02164 return 1;
02165 rpdu = rp->pdu;
02166 if (rp->request_id != pdu->reqid || rpdu->reqid != pdu->reqid)
02167 return 0;
02168 if (rpdu->version != pdu->version)
02169 return 0;
02170 if (rpdu->securityModel != pdu->securityModel)
02171 return 0;
02172 if (rpdu->securityLevel != pdu->securityLevel)
02173 return 0;
02174
02175 if (rpdu->contextEngineIDLen != pdu->contextEngineIDLen ||
02176 memcmp(rpdu->contextEngineID, pdu->contextEngineID,
02177 pdu->contextEngineIDLen))
02178 return 0;
02179 if (rpdu->contextNameLen != pdu->contextNameLen ||
02180 memcmp(rpdu->contextName, pdu->contextName, pdu->contextNameLen))
02181 return 0;
02182
02183
02184
02185 if (pdu->securityModel == SNMP_SEC_MODEL_USM &&
02186 (rpdu->securityEngineIDLen != pdu->securityEngineIDLen ||
02187 memcmp(rpdu->securityEngineID, pdu->securityEngineID,
02188 pdu->securityEngineIDLen)))
02189 return 0;
02190
02191
02192 if (rpdu->securityNameLen != pdu->securityNameLen ||
02193 memcmp(rpdu->securityName, pdu->securityName,
02194 pdu->securityNameLen))
02195 return 0;
02196 return 1;
02197 }
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207 static int
02208 snmpv3_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
02209 netsnmp_session * session, netsnmp_pdu *pdu)
02210 {
02211 int ret;
02212
02213 session->s_snmp_errno = 0;
02214 session->s_errno = 0;
02215
02216
02217
02218
02219 switch (pdu->command) {
02220 case SNMP_MSG_RESPONSE:
02221 case SNMP_MSG_TRAP2:
02222 case SNMP_MSG_REPORT:
02223 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02224
02225
02226
02227 case SNMP_MSG_GET:
02228 case SNMP_MSG_GETNEXT:
02229 case SNMP_MSG_SET:
02230 case SNMP_MSG_INFORM:
02231 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02232 pdu->errstat = 0;
02233 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02234 pdu->errindex = 0;
02235 break;
02236
02237 case SNMP_MSG_GETBULK:
02238 if (pdu->max_repetitions < 0) {
02239 session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
02240 return -1;
02241 }
02242 if (pdu->non_repeaters < 0) {
02243 session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
02244 return -1;
02245 }
02246 break;
02247
02248 case SNMP_MSG_TRAP:
02249 session->s_snmp_errno = SNMPERR_V1_IN_V2;
02250 return -1;
02251
02252 default:
02253 session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
02254 return -1;
02255 }
02256
02257
02258 if (pdu->securityEngineIDLen == 0) {
02259 if (session->securityEngineIDLen) {
02260 snmpv3_clone_engineID(&pdu->securityEngineID,
02261 &pdu->securityEngineIDLen,
02262 session->securityEngineID,
02263 session->securityEngineIDLen);
02264 }
02265 }
02266
02267
02268 if (pdu->contextEngineIDLen == 0) {
02269 if (session->contextEngineIDLen) {
02270 snmpv3_clone_engineID(&pdu->contextEngineID,
02271 &pdu->contextEngineIDLen,
02272 session->contextEngineID,
02273 session->contextEngineIDLen);
02274 } else if (pdu->securityEngineIDLen) {
02275 snmpv3_clone_engineID(&pdu->contextEngineID,
02276 &pdu->contextEngineIDLen,
02277 pdu->securityEngineID,
02278 pdu->securityEngineIDLen);
02279 }
02280 }
02281
02282 if (pdu->contextName == NULL) {
02283 if (!session->contextName) {
02284 session->s_snmp_errno = SNMPERR_BAD_CONTEXT;
02285 return -1;
02286 }
02287 pdu->contextName = strdup(session->contextName);
02288 if (pdu->contextName == NULL) {
02289 session->s_snmp_errno = SNMPERR_GENERR;
02290 return -1;
02291 }
02292 pdu->contextNameLen = session->contextNameLen;
02293 }
02294 if (pdu->securityModel == SNMP_DEFAULT_SECMODEL) {
02295 pdu->securityModel = session->securityModel;
02296 if (pdu->securityModel == SNMP_DEFAULT_SECMODEL) {
02297 pdu->securityModel = se_find_value_in_slist("snmp_secmods", netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL));
02298
02299 if (pdu->securityModel <= 0) {
02300 pdu->securityModel = SNMP_SEC_MODEL_USM;
02301 }
02302 }
02303 }
02304 if (pdu->securityNameLen == 0 && pdu->securityName == NULL) {
02305 if (session->securityModel != NETSNMP_TSM_SECURITY_MODEL &&
02306 session->securityNameLen == 0) {
02307 session->s_snmp_errno = SNMPERR_BAD_SEC_NAME;
02308 return -1;
02309 }
02310 if (session->securityName) {
02311 pdu->securityName = strdup(session->securityName);
02312 if (pdu->securityName == NULL) {
02313 session->s_snmp_errno = SNMPERR_GENERR;
02314 return -1;
02315 }
02316 pdu->securityNameLen = session->securityNameLen;
02317 }
02318 }
02319 if (pdu->securityLevel == 0) {
02320 if (session->securityLevel == 0) {
02321 session->s_snmp_errno = SNMPERR_BAD_SEC_LEVEL;
02322 return -1;
02323 }
02324 pdu->securityLevel = session->securityLevel;
02325 }
02326 DEBUGMSGTL(("snmp_build",
02327 "Building SNMPv3 message (secName:\"%s\", secLevel:%s)...\n",
02328 ((session->securityName) ? (char *) session->securityName :
02329 ((pdu->securityName) ? (char *) pdu->securityName :
02330 "ERROR: undefined")), secLevelName[pdu->securityLevel]));
02331
02332 DEBUGDUMPSECTION("send", "SNMPv3 Message");
02333 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02334 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
02335 ret = snmpv3_packet_realloc_rbuild(pkt, pkt_len, offset,
02336 session, pdu, NULL, 0);
02337 } else {
02338 #endif
02339 ret = snmpv3_packet_build(session, pdu, *pkt, pkt_len, NULL, 0);
02340 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02341 }
02342 #endif
02343 DEBUGINDENTLESS();
02344 if (-1 != ret) {
02345 session->s_snmp_errno = ret;
02346 }
02347
02348 return ret;
02349
02350 }
02351
02352
02353
02354
02355 static u_char *
02356 snmpv3_header_build(netsnmp_session * session, netsnmp_pdu *pdu,
02357 u_char * packet, size_t * out_length,
02358 size_t length, u_char ** msg_hdr_e)
02359 {
02360 u_char *global_hdr, *global_hdr_e;
02361 u_char *cp;
02362 u_char msg_flags;
02363 long max_size;
02364 long sec_model;
02365 u_char *pb, *pb0e;
02366
02367
02368
02369
02370
02371 cp = asn_build_sequence(packet, out_length,
02372 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02373 length);
02374 if (cp == NULL)
02375 return NULL;
02376 if (msg_hdr_e != NULL)
02377 *msg_hdr_e = cp;
02378 pb0e = cp;
02379
02380
02381
02382
02383
02384 DEBUGDUMPHEADER("send", "SNMP Version Number");
02385 cp = asn_build_int(cp, out_length,
02386 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02387 ASN_INTEGER), (long *) &pdu->version,
02388 sizeof(pdu->version));
02389 DEBUGINDENTLESS();
02390 if (cp == NULL)
02391 return NULL;
02392
02393 global_hdr = cp;
02394
02395
02396
02397 DEBUGDUMPSECTION("send", "msgGlobalData");
02398 cp = asn_build_sequence(cp, out_length,
02399 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
02400 if (cp == NULL)
02401 return NULL;
02402 global_hdr_e = cp;
02403
02404
02405
02406
02407
02408 DEBUGDUMPHEADER("send", "msgID");
02409 cp = asn_build_int(cp, out_length,
02410 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02411 ASN_INTEGER), &pdu->msgid,
02412 sizeof(pdu->msgid));
02413 DEBUGINDENTLESS();
02414 if (cp == NULL)
02415 return NULL;
02416
02417
02418
02419
02420 max_size = session->rcvMsgMaxSize;
02421 DEBUGDUMPHEADER("send", "msgMaxSize");
02422 cp = asn_build_int(cp, out_length,
02423 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02424 ASN_INTEGER), &max_size,
02425 sizeof(max_size));
02426 DEBUGINDENTLESS();
02427 if (cp == NULL)
02428 return NULL;
02429
02430
02431
02432
02433 snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
02434 DEBUGDUMPHEADER("send", "msgFlags");
02435 cp = asn_build_string(cp, out_length,
02436 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02437 ASN_OCTET_STR), &msg_flags,
02438 sizeof(msg_flags));
02439 DEBUGINDENTLESS();
02440 if (cp == NULL)
02441 return NULL;
02442
02443
02444
02445
02446 sec_model = pdu->securityModel;
02447 DEBUGDUMPHEADER("send", "msgSecurityModel");
02448 cp = asn_build_int(cp, out_length,
02449 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02450 ASN_INTEGER), &sec_model,
02451 sizeof(sec_model));
02452 DEBUGINDENTADD(-4);
02453 if (cp == NULL)
02454 return NULL;
02455
02456
02457
02458
02459
02460 pb = asn_build_sequence(global_hdr, out_length,
02461 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02462 cp - global_hdr_e);
02463 if (pb == NULL)
02464 return NULL;
02465
02466
02467
02468
02469
02470 pb = asn_build_sequence(packet, out_length,
02471 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02472 length + (cp - pb0e));
02473 if (pb == NULL)
02474 return NULL;
02475
02476 return cp;
02477
02478 }
02479
02480 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02481
02482 int
02483 snmpv3_header_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02484 size_t * offset, netsnmp_session * session,
02485 netsnmp_pdu *pdu)
02486 {
02487 size_t start_offset = *offset;
02488 u_char msg_flags;
02489 long max_size, sec_model;
02490 int rc = 0;
02491
02492
02493
02494
02495 sec_model = pdu->securityModel;
02496 DEBUGDUMPHEADER("send", "msgSecurityModel");
02497 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02498 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02499 ASN_INTEGER), &sec_model,
02500 sizeof(sec_model));
02501 DEBUGINDENTLESS();
02502 if (rc == 0) {
02503 return 0;
02504 }
02505
02506
02507
02508
02509 snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
02510 DEBUGDUMPHEADER("send", "msgFlags");
02511 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02512 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02513 | ASN_OCTET_STR), &msg_flags,
02514 sizeof(msg_flags));
02515 DEBUGINDENTLESS();
02516 if (rc == 0) {
02517 return 0;
02518 }
02519
02520
02521
02522
02523 max_size = session->rcvMsgMaxSize;
02524 DEBUGDUMPHEADER("send", "msgMaxSize");
02525 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02526 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02527 ASN_INTEGER), &max_size,
02528 sizeof(max_size));
02529 DEBUGINDENTLESS();
02530 if (rc == 0) {
02531 return 0;
02532 }
02533
02534
02535
02536
02537 DEBUGDUMPHEADER("send", "msgID");
02538 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02539 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02540 ASN_INTEGER), &pdu->msgid,
02541 sizeof(pdu->msgid));
02542 DEBUGINDENTLESS();
02543 if (rc == 0) {
02544 return 0;
02545 }
02546
02547
02548
02549
02550 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
02551 (u_char) (ASN_SEQUENCE |
02552 ASN_CONSTRUCTOR),
02553 *offset - start_offset);
02554 if (rc == 0) {
02555 return 0;
02556 }
02557
02558
02559
02560
02561 DEBUGDUMPHEADER("send", "SNMP Version Number");
02562 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02563 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02564 ASN_INTEGER),
02565 (long *) &pdu->version,
02566 sizeof(pdu->version));
02567 DEBUGINDENTLESS();
02568 return rc;
02569 }
02570 #endif
02571
02572 static u_char *
02573 snmpv3_scopedPDU_header_build(netsnmp_pdu *pdu,
02574 u_char * packet, size_t * out_length,
02575 u_char ** spdu_e)
02576 {
02577 size_t init_length;
02578 u_char *scopedPdu, *pb;
02579
02580
02581 init_length = *out_length;
02582
02583 pb = scopedPdu = packet;
02584 pb = asn_build_sequence(pb, out_length,
02585 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
02586 if (pb == NULL)
02587 return NULL;
02588 if (spdu_e)
02589 *spdu_e = pb;
02590
02591 DEBUGDUMPHEADER("send", "contextEngineID");
02592 pb = asn_build_string(pb, out_length,
02593 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
02594 pdu->contextEngineID, pdu->contextEngineIDLen);
02595 DEBUGINDENTLESS();
02596 if (pb == NULL)
02597 return NULL;
02598
02599 DEBUGDUMPHEADER("send", "contextName");
02600 pb = asn_build_string(pb, out_length,
02601 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
02602 (u_char *) pdu->contextName,
02603 pdu->contextNameLen);
02604 DEBUGINDENTLESS();
02605 if (pb == NULL)
02606 return NULL;
02607
02608 return pb;
02609
02610 }
02611
02612
02613 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02614 int
02615 snmpv3_scopedPDU_header_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02616 size_t * offset, netsnmp_pdu *pdu,
02617 size_t body_len)
02618 {
02619 size_t start_offset = *offset;
02620 int rc = 0;
02621
02622
02623
02624
02625 DEBUGDUMPHEADER("send", "contextName");
02626 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02627 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02628 | ASN_OCTET_STR),
02629 (u_char *) pdu->contextName,
02630 pdu->contextNameLen);
02631 DEBUGINDENTLESS();
02632 if (rc == 0) {
02633 return 0;
02634 }
02635
02636
02637
02638
02639 DEBUGDUMPHEADER("send", "contextEngineID");
02640 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02641 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02642 | ASN_OCTET_STR),
02643 pdu->contextEngineID,
02644 pdu->contextEngineIDLen);
02645 DEBUGINDENTLESS();
02646 if (rc == 0) {
02647 return 0;
02648 }
02649
02650 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
02651 (u_char) (ASN_SEQUENCE |
02652 ASN_CONSTRUCTOR),
02653 *offset - start_offset + body_len);
02654
02655 return rc;
02656 }
02657 #endif
02658
02659 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02660
02661
02662
02663 int
02664 snmpv3_packet_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02665 size_t * offset, netsnmp_session * session,
02666 netsnmp_pdu *pdu, u_char * pdu_data,
02667 size_t pdu_data_len)
02668 {
02669 u_char *scoped_pdu, *hdrbuf = NULL, *hdr = NULL;
02670 size_t hdrbuf_len = SNMP_MAX_MSG_V3_HDRS, hdr_offset =
02671 0, spdu_offset = 0;
02672 size_t body_end_offset = *offset, body_len = 0;
02673 struct snmp_secmod_def *sptr = NULL;
02674 int rc = 0;
02675
02676
02677
02678
02679 DEBUGPRINTPDUTYPE("send", pdu->command);
02680 if (pdu_data) {
02681 while ((*pkt_len - *offset) < pdu_data_len) {
02682 if (!asn_realloc(pkt, pkt_len)) {
02683 return -1;
02684 }
02685 }
02686
02687 *offset += pdu_data_len;
02688 memcpy(*pkt + *pkt_len - *offset, pdu_data, pdu_data_len);
02689 } else {
02690 rc = snmp_pdu_realloc_rbuild(pkt, pkt_len, offset, pdu);
02691 if (rc == 0) {
02692 return -1;
02693 }
02694 }
02695 body_len = *offset - body_end_offset;
02696
02697 DEBUGDUMPSECTION("send", "ScopedPdu");
02698 rc = snmpv3_scopedPDU_header_realloc_rbuild(pkt, pkt_len, offset,
02699 pdu, body_len);
02700 if (rc == 0) {
02701 return -1;
02702 }
02703 spdu_offset = *offset;
02704 DEBUGINDENTADD(-4);
02705
02706 if ((hdrbuf = (u_char *) malloc(hdrbuf_len)) == NULL) {
02707 return -1;
02708 }
02709
02710 rc = snmpv3_header_realloc_rbuild(&hdrbuf, &hdrbuf_len, &hdr_offset,
02711 session, pdu);
02712 if (rc == 0) {
02713 SNMP_FREE(hdrbuf);
02714 return -1;
02715 }
02716 hdr = hdrbuf + hdrbuf_len - hdr_offset;
02717 scoped_pdu = *pkt + *pkt_len - spdu_offset;
02718
02719
02720
02721
02722
02723
02724 sptr = find_sec_mod(pdu->securityModel);
02725 DEBUGDUMPSECTION("send", "SM msgSecurityParameters");
02726 if (sptr && sptr->encode_reverse) {
02727 struct snmp_secmod_outgoing_params parms;
02728
02729 parms.msgProcModel = pdu->msgParseModel;
02730 parms.globalData = hdr;
02731 parms.globalDataLen = hdr_offset;
02732 parms.maxMsgSize = SNMP_MAX_MSG_SIZE;
02733 parms.secModel = pdu->securityModel;
02734 parms.secEngineID = pdu->securityEngineID;
02735 parms.secEngineIDLen = pdu->securityEngineIDLen;
02736 parms.secName = pdu->securityName;
02737 parms.secNameLen = pdu->securityNameLen;
02738 parms.secLevel = pdu->securityLevel;
02739 parms.scopedPdu = scoped_pdu;
02740 parms.scopedPduLen = spdu_offset;
02741 parms.secStateRef = pdu->securityStateRef;
02742 parms.wholeMsg = pkt;
02743 parms.wholeMsgLen = pkt_len;
02744 parms.wholeMsgOffset = offset;
02745 parms.session = session;
02746 parms.pdu = pdu;
02747
02748 rc = (*sptr->encode_reverse) (&parms);
02749 } else {
02750 if (!sptr) {
02751 snmp_log(LOG_ERR,
02752 "no such security service available: %d\n",
02753 pdu->securityModel);
02754 } else if (!sptr->encode_reverse) {
02755 snmp_log(LOG_ERR,
02756 "security service %d doesn't support reverse encoding.\n",
02757 pdu->securityModel);
02758 }
02759 rc = -1;
02760 }
02761
02762 DEBUGINDENTLESS();
02763 SNMP_FREE(hdrbuf);
02764 return rc;
02765 }
02766 #endif
02767
02768
02769
02770
02771 int
02772 snmpv3_packet_build(netsnmp_session * session, netsnmp_pdu *pdu,
02773 u_char * packet, size_t * out_length,
02774 u_char * pdu_data, size_t pdu_data_len)
02775 {
02776 u_char *global_data, *sec_params, *spdu_hdr_e;
02777 size_t global_data_len, sec_params_len;
02778 u_char spdu_buf[SNMP_MAX_MSG_SIZE];
02779 size_t spdu_buf_len, spdu_len;
02780 u_char *cp;
02781 int result;
02782 struct snmp_secmod_def *sptr;
02783
02784 global_data = packet;
02785
02786
02787
02788
02789 sec_params = snmpv3_header_build(session, pdu, global_data,
02790 out_length, 0, NULL);
02791 if (sec_params == NULL)
02792 return -1;
02793 global_data_len = sec_params - global_data;
02794 sec_params_len = *out_length;
02795
02796
02797
02798
02799
02800 spdu_buf_len = SNMP_MAX_MSG_SIZE;
02801 DEBUGDUMPSECTION("send", "ScopedPdu");
02802 cp = snmpv3_scopedPDU_header_build(pdu, spdu_buf, &spdu_buf_len,
02803 &spdu_hdr_e);
02804 if (cp == NULL)
02805 return -1;
02806
02807
02808
02809
02810 DEBUGPRINTPDUTYPE("send", ((pdu_data) ? *pdu_data : 0x00));
02811 if (pdu_data) {
02812 memcpy(cp, pdu_data, pdu_data_len);
02813 cp += pdu_data_len;
02814 } else {
02815 cp = snmp_pdu_build(pdu, cp, &spdu_buf_len);
02816 if (cp == NULL)
02817 return -1;
02818 }
02819 DEBUGINDENTADD(-4);
02820
02821
02822
02823
02824 spdu_len = cp - spdu_hdr_e;
02825 spdu_buf_len = SNMP_MAX_MSG_SIZE;
02826 if (asn_build_sequence(spdu_buf, &spdu_buf_len,
02827 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02828 spdu_len) == NULL)
02829 return -1;
02830 spdu_len = cp - spdu_buf;
02831
02832
02833
02834
02835
02836
02837 cp = NULL;
02838 *out_length = SNMP_MAX_MSG_SIZE;
02839 DEBUGDUMPSECTION("send", "SM msgSecurityParameters");
02840 sptr = find_sec_mod(pdu->securityModel);
02841 if (sptr && sptr->encode_forward) {
02842 struct snmp_secmod_outgoing_params parms;
02843 parms.msgProcModel = pdu->msgParseModel;
02844 parms.globalData = global_data;
02845 parms.globalDataLen = global_data_len;
02846 parms.maxMsgSize = SNMP_MAX_MSG_SIZE;
02847 parms.secModel = pdu->securityModel;
02848 parms.secEngineID = pdu->securityEngineID;
02849 parms.secEngineIDLen = pdu->securityEngineIDLen;
02850 parms.secName = pdu->securityName;
02851 parms.secNameLen = pdu->securityNameLen;
02852 parms.secLevel = pdu->securityLevel;
02853 parms.scopedPdu = spdu_buf;
02854 parms.scopedPduLen = spdu_len;
02855 parms.secStateRef = pdu->securityStateRef;
02856 parms.secParams = sec_params;
02857 parms.secParamsLen = &sec_params_len;
02858 parms.wholeMsg = &cp;
02859 parms.wholeMsgLen = out_length;
02860 parms.session = session;
02861 parms.pdu = pdu;
02862 result = (*sptr->encode_forward) (&parms);
02863 } else {
02864 if (!sptr) {
02865 snmp_log(LOG_ERR, "no such security service available: %d\n",
02866 pdu->securityModel);
02867 } else if (!sptr->encode_forward) {
02868 snmp_log(LOG_ERR,
02869 "security service %d doesn't support forward out encoding.\n",
02870 pdu->securityModel);
02871 }
02872 result = -1;
02873 }
02874 DEBUGINDENTLESS();
02875 return result;
02876
02877 }
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887 static int
02888 _snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
02889 netsnmp_session * session, netsnmp_pdu *pdu)
02890 {
02891 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
02892 u_char *h0e = NULL;
02893 size_t start_offset = *offset;
02894 long version;
02895 int rc = 0;
02896 #endif
02897
02898 u_char *h0, *h1;
02899 u_char *cp;
02900 size_t length;
02901
02902 session->s_snmp_errno = 0;
02903 session->s_errno = 0;
02904
02905 if (pdu->version == SNMP_VERSION_3) {
02906 return snmpv3_build(pkt, pkt_len, offset, session, pdu);
02907 }
02908
02909 switch (pdu->command) {
02910 case SNMP_MSG_RESPONSE:
02911 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02912
02913
02914
02915 case SNMP_MSG_GET:
02916 case SNMP_MSG_GETNEXT:
02917 case SNMP_MSG_SET:
02918
02919
02920
02921
02922
02923
02924
02925 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02926 pdu->errstat = 0;
02927 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02928 pdu->errindex = 0;
02929 break;
02930
02931 case SNMP_MSG_TRAP2:
02932 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02933
02934
02935
02936 case SNMP_MSG_INFORM:
02937 #ifndef NETSNMP_DISABLE_SNMPV1
02938
02939
02940
02941 if (pdu->version == SNMP_VERSION_1) {
02942 session->s_snmp_errno = SNMPERR_V2_IN_V1;
02943 return -1;
02944 }
02945 #endif
02946 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02947 pdu->errstat = 0;
02948 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02949 pdu->errindex = 0;
02950 break;
02951
02952 case SNMP_MSG_GETBULK:
02953
02954
02955
02956 #ifndef NETSNMP_DISABLE_SNMPV1
02957 if (pdu->version == SNMP_VERSION_1) {
02958 session->s_snmp_errno = SNMPERR_V2_IN_V1;
02959 return -1;
02960 }
02961 #endif
02962 if (pdu->max_repetitions < 0) {
02963 session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
02964 return -1;
02965 }
02966 if (pdu->non_repeaters < 0) {
02967 session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
02968 return -1;
02969 }
02970 break;
02971
02972 case SNMP_MSG_TRAP:
02973
02974
02975
02976 #ifndef NETSNMP_DISABLE_SNMPV1
02977 if (pdu->version != SNMP_VERSION_1) {
02978 session->s_snmp_errno = SNMPERR_V1_IN_V2;
02979 return -1;
02980 }
02981 #endif
02982
02983
02984
02985 pdu->reqid = 1;
02986 if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH) {
02987 pdu->enterprise = (oid *) malloc(sizeof(DEFAULT_ENTERPRISE));
02988 if (pdu->enterprise == NULL) {
02989 session->s_snmp_errno = SNMPERR_MALLOC;
02990 return -1;
02991 }
02992 memmove(pdu->enterprise, DEFAULT_ENTERPRISE,
02993 sizeof(DEFAULT_ENTERPRISE));
02994 pdu->enterprise_length =
02995 sizeof(DEFAULT_ENTERPRISE) / sizeof(oid);
02996 }
02997 if (pdu->time == SNMP_DEFAULT_TIME)
02998 pdu->time = DEFAULT_TIME;
02999
03000
03001
03002 pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE);
03003 break;
03004
03005 case SNMP_MSG_REPORT:
03006 default:
03007 session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
03008 return -1;
03009 }
03010
03011
03012
03013
03014 length = *pkt_len;
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024 h0 = *pkt;
03025 switch (pdu->version) {
03026 #ifndef NETSNMP_DISABLE_SNMPV1
03027 case SNMP_VERSION_1:
03028 #endif
03029 #ifndef NETSNMP_DISABLE_SNMPV2C
03030 case SNMP_VERSION_2c:
03031 #endif
03032 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
03033 #ifdef NETSNMP_NO_ZEROLENGTH_COMMUNITY
03034 if (pdu->community_len == 0) {
03035 if (session->community_len == 0) {
03036 session->s_snmp_errno = SNMPERR_BAD_COMMUNITY;
03037 return -1;
03038 }
03039 pdu->community = (u_char *) malloc(session->community_len);
03040 if (pdu->community == NULL) {
03041 session->s_snmp_errno = SNMPERR_MALLOC;
03042 return -1;
03043 }
03044 memmove(pdu->community,
03045 session->community, session->community_len);
03046 pdu->community_len = session->community_len;
03047 }
03048 #else
03049 if (pdu->community_len == 0 && pdu->command != SNMP_MSG_RESPONSE) {
03050
03051
03052
03053 if (0 == session->community_len) {
03054 SNMP_FREE(pdu->community);
03055 pdu->community = NULL;
03056 } else if (pdu->community_len == session->community_len) {
03057 memmove(pdu->community,
03058 session->community, session->community_len);
03059 } else {
03060 SNMP_FREE(pdu->community);
03061 pdu->community = (u_char *) malloc(session->community_len);
03062 if (pdu->community == NULL) {
03063 session->s_snmp_errno = SNMPERR_MALLOC;
03064 return -1;
03065 }
03066 memmove(pdu->community,
03067 session->community, session->community_len);
03068 }
03069 pdu->community_len = session->community_len;
03070 }
03071 #endif
03072
03073 DEBUGMSGTL(("snmp_send", "Building SNMPv%ld message...\n",
03074 (1 + pdu->version)));
03075 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03076 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
03077 DEBUGPRINTPDUTYPE("send", pdu->command);
03078 rc = snmp_pdu_realloc_rbuild(pkt, pkt_len, offset, pdu);
03079 if (rc == 0) {
03080 return -1;
03081 }
03082
03083 DEBUGDUMPHEADER("send", "Community String");
03084 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
03085 (u_char) (ASN_UNIVERSAL |
03086 ASN_PRIMITIVE |
03087 ASN_OCTET_STR),
03088 pdu->community,
03089 pdu->community_len);
03090 DEBUGINDENTLESS();
03091 if (rc == 0) {
03092 return -1;
03093 }
03094
03095
03096
03097
03098
03099 DEBUGDUMPHEADER("send", "SNMP Version Number");
03100
03101 version = pdu->version;
03102 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03103 (u_char) (ASN_UNIVERSAL |
03104 ASN_PRIMITIVE |
03105 ASN_INTEGER),
03106 (long *) &version,
03107 sizeof(version));
03108 DEBUGINDENTLESS();
03109 if (rc == 0) {
03110 return -1;
03111 }
03112
03113
03114
03115
03116 #ifndef NETSNMP_DISABLE_SNMPV1
03117 if (pdu->version == SNMP_VERSION_1) {
03118 DEBUGDUMPSECTION("send", "SNMPv1 Message");
03119 } else {
03120 #endif
03121 DEBUGDUMPSECTION("send", "SNMPv2c Message");
03122 #ifndef NETSNMP_DISABLE_SNMPV1
03123 }
03124 #endif
03125 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03126 (u_char) (ASN_SEQUENCE |
03127 ASN_CONSTRUCTOR),
03128 *offset - start_offset);
03129 DEBUGINDENTLESS();
03130
03131 if (rc == 0) {
03132 return -1;
03133 }
03134 return 0;
03135 } else {
03136
03137 #endif
03138
03139
03140
03141
03142
03143 cp = asn_build_sequence(*pkt, pkt_len,
03144 (u_char) (ASN_SEQUENCE |
03145 ASN_CONSTRUCTOR), 0);
03146 if (cp == NULL) {
03147 return -1;
03148 }
03149 h0e = cp;
03150
03151 #ifndef NETSNMP_DISABLE_SNMPV1
03152 if (pdu->version == SNMP_VERSION_1) {
03153 DEBUGDUMPSECTION("send", "SNMPv1 Message");
03154 } else {
03155 #endif
03156 DEBUGDUMPSECTION("send", "SNMPv2c Message");
03157 #ifndef NETSNMP_DISABLE_SNMPV1
03158 }
03159 #endif
03160
03161
03162
03163
03164 DEBUGDUMPHEADER("send", "SNMP Version Number");
03165
03166 version = pdu->version;
03167 cp = asn_build_int(cp, pkt_len,
03168 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03169 ASN_INTEGER), (long *) &version,
03170 sizeof(version));
03171 DEBUGINDENTLESS();
03172 if (cp == NULL)
03173 return -1;
03174
03175
03176
03177
03178 DEBUGDUMPHEADER("send", "Community String");
03179 cp = asn_build_string(cp, pkt_len,
03180 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03181 ASN_OCTET_STR), pdu->community,
03182 pdu->community_len);
03183 DEBUGINDENTLESS();
03184 if (cp == NULL)
03185 return -1;
03186 break;
03187
03188 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03189 }
03190 #endif
03191 break;
03192 #endif
03193 case SNMP_VERSION_2p:
03194 case SNMP_VERSION_sec:
03195 case SNMP_VERSION_2u:
03196 case SNMP_VERSION_2star:
03197 default:
03198 session->s_snmp_errno = SNMPERR_BAD_VERSION;
03199 return -1;
03200 }
03201
03202 h1 = cp;
03203 DEBUGPRINTPDUTYPE("send", pdu->command);
03204 cp = snmp_pdu_build(pdu, cp, pkt_len);
03205 DEBUGINDENTADD(-4);
03206 if (cp == NULL)
03207 return -1;
03208
03209
03210
03211
03212 switch (pdu->version) {
03213 #ifndef NETSNMP_DISABLE_SNMPV1
03214 case SNMP_VERSION_1:
03215 #endif
03216 #ifndef NETSNMP_DISABLE_SNMPV2C
03217 case SNMP_VERSION_2c:
03218 #endif
03219 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
03220 asn_build_sequence(*pkt, &length,
03221 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03222 cp - h0e);
03223 break;
03224 #endif
03225
03226 case SNMP_VERSION_2p:
03227 case SNMP_VERSION_sec:
03228 case SNMP_VERSION_2u:
03229 case SNMP_VERSION_2star:
03230 default:
03231 session->s_snmp_errno = SNMPERR_BAD_VERSION;
03232 return -1;
03233 }
03234 *pkt_len = cp - *pkt;
03235 return 0;
03236 }
03237
03238 int
03239 snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
03240 netsnmp_session * pss, netsnmp_pdu *pdu)
03241 {
03242 int rc;
03243 rc = _snmp_build(pkt, pkt_len, offset, pss, pdu);
03244 if (rc) {
03245 if (!pss->s_snmp_errno) {
03246 snmp_log(LOG_ERR, "snmp_build: unknown failure");
03247 pss->s_snmp_errno = SNMPERR_BAD_ASN1_BUILD;
03248 }
03249 SET_SNMP_ERROR(pss->s_snmp_errno);
03250 rc = -1;
03251 }
03252 return rc;
03253 }
03254
03255
03256
03257
03258 u_char *
03259 snmp_pdu_build(netsnmp_pdu *pdu, u_char * cp, size_t * out_length)
03260 {
03261 u_char *h1, *h1e, *h2, *h2e;
03262 netsnmp_variable_list *vp;
03263 size_t length;
03264
03265 length = *out_length;
03266
03267
03268
03269
03270 h1 = cp;
03271 cp = asn_build_sequence(cp, out_length, (u_char) pdu->command, 0);
03272 if (cp == NULL)
03273 return NULL;
03274 h1e = cp;
03275
03276
03277
03278
03279 if (pdu->command != SNMP_MSG_TRAP) {
03280
03281
03282
03283
03284 DEBUGDUMPHEADER("send", "request_id");
03285
03286
03287
03288 cp = asn_build_int(cp, out_length,
03289 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03290 ASN_INTEGER), &pdu->reqid,
03291 sizeof(pdu->reqid));
03292 DEBUGINDENTLESS();
03293 if (cp == NULL)
03294 return NULL;
03295
03296
03297
03298
03299 DEBUGDUMPHEADER("send", "error status");
03300 cp = asn_build_int(cp, out_length,
03301 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03302 ASN_INTEGER), &pdu->errstat,
03303 sizeof(pdu->errstat));
03304 DEBUGINDENTLESS();
03305 if (cp == NULL)
03306 return NULL;
03307
03308
03309
03310
03311 DEBUGDUMPHEADER("send", "error index");
03312 cp = asn_build_int(cp, out_length,
03313 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03314 ASN_INTEGER), &pdu->errindex,
03315 sizeof(pdu->errindex));
03316 DEBUGINDENTLESS();
03317 if (cp == NULL)
03318 return NULL;
03319 } else {
03320
03321
03322
03323
03324
03325
03326
03327 DEBUGDUMPHEADER("send", "enterprise OBJID");
03328 cp = asn_build_objid(cp, out_length,
03329 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03330 ASN_OBJECT_ID),
03331 (oid *) pdu->enterprise,
03332 pdu->enterprise_length);
03333 DEBUGINDENTLESS();
03334 if (cp == NULL)
03335 return NULL;
03336
03337
03338
03339
03340 DEBUGDUMPHEADER("send", "agent Address");
03341 cp = asn_build_string(cp, out_length,
03342 (u_char) (ASN_IPADDRESS | ASN_PRIMITIVE),
03343 (u_char *) pdu->agent_addr, 4);
03344 DEBUGINDENTLESS();
03345 if (cp == NULL)
03346 return NULL;
03347
03348
03349
03350
03351 DEBUGDUMPHEADER("send", "generic trap number");
03352 cp = asn_build_int(cp, out_length,
03353 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03354 ASN_INTEGER),
03355 (long *) &pdu->trap_type,
03356 sizeof(pdu->trap_type));
03357 DEBUGINDENTLESS();
03358 if (cp == NULL)
03359 return NULL;
03360
03361
03362
03363
03364 DEBUGDUMPHEADER("send", "specific trap number");
03365 cp = asn_build_int(cp, out_length,
03366 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03367 ASN_INTEGER),
03368 (long *) &pdu->specific_type,
03369 sizeof(pdu->specific_type));
03370 DEBUGINDENTLESS();
03371 if (cp == NULL)
03372 return NULL;
03373
03374
03375
03376
03377 DEBUGDUMPHEADER("send", "timestamp");
03378 cp = asn_build_unsigned_int(cp, out_length,
03379 (u_char) (ASN_TIMETICKS |
03380 ASN_PRIMITIVE), &pdu->time,
03381 sizeof(pdu->time));
03382 DEBUGINDENTLESS();
03383 if (cp == NULL)
03384 return NULL;
03385 }
03386
03387
03388
03389
03390
03391
03392 h2 = cp;
03393 cp = asn_build_sequence(cp, out_length,
03394 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
03395 if (cp == NULL)
03396 return NULL;
03397 h2e = cp;
03398
03399
03400
03401
03402 DEBUGDUMPSECTION("send", "VarBindList");
03403 for (vp = pdu->variables; vp; vp = vp->next_variable) {
03404 DEBUGDUMPSECTION("send", "VarBind");
03405 cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type,
03406 vp->val_len, (u_char *) vp->val.string,
03407 out_length);
03408 DEBUGINDENTLESS();
03409 if (cp == NULL)
03410 return NULL;
03411 }
03412 DEBUGINDENTLESS();
03413
03414
03415
03416
03417 asn_build_sequence(h2, &length,
03418 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03419 cp - h2e);
03420
03421
03422
03423
03424 asn_build_sequence(h1, &length, (u_char) pdu->command, cp - h1e);
03425
03426 return cp;
03427 }
03428
03429 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03430
03431
03432
03433 int
03434 snmp_pdu_realloc_rbuild(u_char ** pkt, size_t * pkt_len, size_t * offset,
03435 netsnmp_pdu *pdu)
03436 {
03437 #ifndef VPCACHE_SIZE
03438 #define VPCACHE_SIZE 50
03439 #endif
03440 netsnmp_variable_list *vpcache[VPCACHE_SIZE];
03441 netsnmp_variable_list *vp, *tmpvp;
03442 size_t start_offset = *offset;
03443 int i, wrapped = 0, notdone, final, rc = 0;
03444
03445 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "starting\n"));
03446 for (vp = pdu->variables, i = VPCACHE_SIZE - 1; vp;
03447 vp = vp->next_variable, i--) {
03448 if (i < 0) {
03449 wrapped = notdone = 1;
03450 i = VPCACHE_SIZE - 1;
03451 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "wrapped\n"));
03452 }
03453 vpcache[i] = vp;
03454 }
03455 final = i + 1;
03456
03457 do {
03458 for (i = final; i < VPCACHE_SIZE; i++) {
03459 vp = vpcache[i];
03460 DEBUGDUMPSECTION("send", "VarBind");
03461 rc = snmp_realloc_rbuild_var_op(pkt, pkt_len, offset, 1,
03462 vp->name, &vp->name_length,
03463 vp->type,
03464 (u_char *) vp->val.string,
03465 vp->val_len);
03466 DEBUGINDENTLESS();
03467 if (rc == 0) {
03468 return 0;
03469 }
03470 }
03471
03472 DEBUGINDENTLESS();
03473 if (wrapped) {
03474 notdone = 1;
03475 for (i = 0; i < final; i++) {
03476 vp = vpcache[i];
03477 DEBUGDUMPSECTION("send", "VarBind");
03478 rc = snmp_realloc_rbuild_var_op(pkt, pkt_len, offset, 1,
03479 vp->name, &vp->name_length,
03480 vp->type,
03481 (u_char *) vp->val.string,
03482 vp->val_len);
03483 DEBUGINDENTLESS();
03484 if (rc == 0) {
03485 return 0;
03486 }
03487 }
03488
03489 if (final == 0) {
03490 tmpvp = vpcache[VPCACHE_SIZE - 1];
03491 } else {
03492 tmpvp = vpcache[final - 1];
03493 }
03494 wrapped = 0;
03495
03496 for (vp = pdu->variables, i = VPCACHE_SIZE - 1;
03497 vp && vp != tmpvp; vp = vp->next_variable, i--) {
03498 if (i < 0) {
03499 wrapped = 1;
03500 i = VPCACHE_SIZE - 1;
03501 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "wrapped\n"));
03502 }
03503 vpcache[i] = vp;
03504 }
03505 final = i + 1;
03506 } else {
03507 notdone = 0;
03508 }
03509 } while (notdone);
03510
03511
03512
03513
03514
03515
03516 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03517 (u_char) (ASN_SEQUENCE |
03518 ASN_CONSTRUCTOR),
03519 *offset - start_offset);
03520
03521
03522
03523
03524 if (pdu->command != SNMP_MSG_TRAP) {
03525
03526
03527
03528 DEBUGDUMPHEADER("send", "error index");
03529 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03530 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03531 | ASN_INTEGER),
03532 &pdu->errindex, sizeof(pdu->errindex));
03533 DEBUGINDENTLESS();
03534 if (rc == 0) {
03535 return 0;
03536 }
03537
03538
03539
03540
03541 DEBUGDUMPHEADER("send", "error status");
03542 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03543 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03544 | ASN_INTEGER),
03545 &pdu->errstat, sizeof(pdu->errstat));
03546 DEBUGINDENTLESS();
03547 if (rc == 0) {
03548 return 0;
03549 }
03550
03551
03552
03553
03554 DEBUGDUMPHEADER("send", "request_id");
03555 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03556 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03557 | ASN_INTEGER), &pdu->reqid,
03558 sizeof(pdu->reqid));
03559 DEBUGINDENTLESS();
03560 if (rc == 0) {
03561 return 0;
03562 }
03563 } else {
03564
03565
03566
03567
03568
03569
03570
03571 DEBUGDUMPHEADER("send", "timestamp");
03572 rc = asn_realloc_rbuild_unsigned_int(pkt, pkt_len, offset, 1,
03573 (u_char) (ASN_TIMETICKS |
03574 ASN_PRIMITIVE),
03575 &pdu->time,
03576 sizeof(pdu->time));
03577 DEBUGINDENTLESS();
03578 if (rc == 0) {
03579 return 0;
03580 }
03581
03582
03583
03584
03585 DEBUGDUMPHEADER("send", "specific trap number");
03586 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03587 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03588 | ASN_INTEGER),
03589 (long *) &pdu->specific_type,
03590 sizeof(pdu->specific_type));
03591 DEBUGINDENTLESS();
03592 if (rc == 0) {
03593 return 0;
03594 }
03595
03596
03597
03598
03599 DEBUGDUMPHEADER("send", "generic trap number");
03600 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03601 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03602 | ASN_INTEGER),
03603 (long *) &pdu->trap_type,
03604 sizeof(pdu->trap_type));
03605 DEBUGINDENTLESS();
03606 if (rc == 0) {
03607 return 0;
03608 }
03609
03610
03611
03612
03613 DEBUGDUMPHEADER("send", "agent Address");
03614 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
03615 (u_char) (ASN_IPADDRESS |
03616 ASN_PRIMITIVE),
03617 (u_char *) pdu->agent_addr, 4);
03618 DEBUGINDENTLESS();
03619 if (rc == 0) {
03620 return 0;
03621 }
03622
03623
03624
03625
03626 DEBUGDUMPHEADER("send", "enterprise OBJID");
03627 rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, 1,
03628 (u_char) (ASN_UNIVERSAL |
03629 ASN_PRIMITIVE |
03630 ASN_OBJECT_ID),
03631 (oid *) pdu->enterprise,
03632 pdu->enterprise_length);
03633 DEBUGINDENTLESS();
03634 if (rc == 0) {
03635 return 0;
03636 }
03637 }
03638
03639
03640
03641
03642 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03643 (u_char) pdu->command,
03644 *offset - start_offset);
03645 return rc;
03646 }
03647 #endif
03648
03649
03650
03651
03652
03653 static int
03654 snmp_parse_version(u_char * data, size_t length)
03655 {
03656 u_char type;
03657 long version = SNMPERR_BAD_VERSION;
03658
03659 data = asn_parse_sequence(data, &length, &type,
03660 (ASN_SEQUENCE | ASN_CONSTRUCTOR), "version");
03661 if (data) {
03662 data =
03663 asn_parse_int(data, &length, &type, &version, sizeof(version));
03664 if (!data || type != ASN_INTEGER) {
03665 return SNMPERR_BAD_VERSION;
03666 }
03667 }
03668 return version;
03669 }
03670
03671
03672 int
03673 snmpv3_parse(netsnmp_pdu *pdu,
03674 u_char * data,
03675 size_t * length,
03676 u_char ** after_header, netsnmp_session * sess)
03677 {
03678 u_char type, msg_flags;
03679 long ver, msg_max_size, msg_sec_model;
03680 size_t max_size_response;
03681 u_char tmp_buf[SNMP_MAX_MSG_SIZE];
03682 size_t tmp_buf_len;
03683 u_char pdu_buf[SNMP_MAX_MSG_SIZE];
03684 u_char *mallocbuf = NULL;
03685 size_t pdu_buf_len = SNMP_MAX_MSG_SIZE;
03686 u_char *sec_params;
03687 u_char *msg_data;
03688 u_char *cp;
03689 size_t asn_len, msg_len;
03690 int ret, ret_val;
03691 struct snmp_secmod_def *sptr;
03692
03693
03694 msg_data = data;
03695 msg_len = *length;
03696
03697
03698
03699
03700
03701 DEBUGDUMPSECTION("recv", "SNMPv3 Message");
03702 data = asn_parse_sequence(data, length, &type,
03703 (ASN_SEQUENCE | ASN_CONSTRUCTOR), "message");
03704 if (data == NULL) {
03705
03706
03707
03708 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03709 DEBUGINDENTLESS();
03710 return SNMPERR_ASN_PARSE_ERR;
03711 }
03712
03713
03714
03715
03716 DEBUGDUMPHEADER("recv", "SNMP Version Number");
03717 data = asn_parse_int(data, length, &type, &ver, sizeof(ver));
03718 DEBUGINDENTLESS();
03719 if (data == NULL) {
03720 ERROR_MSG("bad parse of version");
03721 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03722 DEBUGINDENTLESS();
03723 return SNMPERR_ASN_PARSE_ERR;
03724 }
03725 pdu->version = ver;
03726
03727
03728
03729
03730 cp = data;
03731 asn_len = *length;
03732 DEBUGDUMPSECTION("recv", "msgGlobalData");
03733 data = asn_parse_sequence(data, &asn_len, &type,
03734 (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03735 "msgGlobalData");
03736 if (data == NULL) {
03737
03738
03739
03740 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03741 DEBUGINDENTADD(-4);
03742 return SNMPERR_ASN_PARSE_ERR;
03743 }
03744 *length -= data - cp;
03745
03746
03747
03748
03749 DEBUGDUMPHEADER("recv", "msgID");
03750 data =
03751 asn_parse_int(data, length, &type, &pdu->msgid,
03752 sizeof(pdu->msgid));
03753 DEBUGINDENTLESS();
03754 if (data == NULL || type != ASN_INTEGER) {
03755 ERROR_MSG("error parsing msgID");
03756 DEBUGINDENTADD(-4);
03757 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03758 return SNMPERR_ASN_PARSE_ERR;
03759 }
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769 if (pdu->msgid < 0 || pdu->msgid > 0x7fffffff) {
03770 snmp_log(LOG_ERR, "Received bad msgID (%ld %s %s).\n", pdu->msgid,
03771 (pdu->msgid < 0) ? "<" : ">",
03772 (pdu->msgid < 0) ? "0" : "2^31 - 1");
03773 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03774 DEBUGINDENTADD(-4);
03775 return SNMPERR_ASN_PARSE_ERR;
03776 }
03777
03778
03779
03780
03781 DEBUGDUMPHEADER("recv", "msgMaxSize");
03782 data = asn_parse_int(data, length, &type, &msg_max_size,
03783 sizeof(msg_max_size));
03784 DEBUGINDENTLESS();
03785 if (data == NULL || type != ASN_INTEGER) {
03786 ERROR_MSG("error parsing msgMaxSize");
03787 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03788 DEBUGINDENTADD(-4);
03789 return SNMPERR_ASN_PARSE_ERR;
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805 if (msg_max_size < 484) {
03806 snmp_log(LOG_ERR, "Received bad msgMaxSize (%lu < 484).\n",
03807 msg_max_size);
03808 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03809 DEBUGINDENTADD(-4);
03810 return SNMPERR_ASN_PARSE_ERR;
03811 } else if (msg_max_size > 0x7fffffff) {
03812 snmp_log(LOG_ERR, "Received bad msgMaxSize (%lu > 2^31 - 1).\n",
03813 msg_max_size);
03814 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03815 DEBUGINDENTADD(-4);
03816 return SNMPERR_ASN_PARSE_ERR;
03817 } else {
03818 DEBUGMSGTL(("snmpv3_parse", "msgMaxSize %lu received\n",
03819 msg_max_size));
03820 sess->sndMsgMaxSize = msg_max_size;
03821 }
03822
03823
03824
03825
03826 tmp_buf_len = SNMP_MAX_MSG_SIZE;
03827 DEBUGDUMPHEADER("recv", "msgFlags");
03828 data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len);
03829 DEBUGINDENTLESS();
03830 if (data == NULL || type != ASN_OCTET_STR || tmp_buf_len != 1) {
03831 ERROR_MSG("error parsing msgFlags");
03832 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03833 DEBUGINDENTADD(-4);
03834 return SNMPERR_ASN_PARSE_ERR;
03835 }
03836 msg_flags = *tmp_buf;
03837 if (msg_flags & SNMP_MSG_FLAG_RPRT_BIT)
03838 pdu->flags |= SNMP_MSG_FLAG_RPRT_BIT;
03839 else
03840 pdu->flags &= (~SNMP_MSG_FLAG_RPRT_BIT);
03841
03842
03843
03844
03845 DEBUGDUMPHEADER("recv", "msgSecurityModel");
03846 data = asn_parse_int(data, length, &type, &msg_sec_model,
03847 sizeof(msg_sec_model));
03848 DEBUGINDENTADD(-4);
03849 if (data == NULL || type != ASN_INTEGER ||
03850 msg_sec_model < 1 || msg_sec_model > 0x7fffffff) {
03851 ERROR_MSG("error parsing msgSecurityModel");
03852 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03853 DEBUGINDENTLESS();
03854 return SNMPERR_ASN_PARSE_ERR;
03855 }
03856 sptr = find_sec_mod(msg_sec_model);
03857 if (!sptr) {
03858 snmp_log(LOG_WARNING, "unknown security model: %ld\n",
03859 msg_sec_model);
03860 snmp_increment_statistic(STAT_SNMPUNKNOWNSECURITYMODELS);
03861 DEBUGINDENTLESS();
03862 return SNMPERR_UNKNOWN_SEC_MODEL;
03863 }
03864 pdu->securityModel = msg_sec_model;
03865
03866 if (msg_flags & SNMP_MSG_FLAG_PRIV_BIT &&
03867 !(msg_flags & SNMP_MSG_FLAG_AUTH_BIT)) {
03868 ERROR_MSG("invalid message, illegal msgFlags");
03869 snmp_increment_statistic(STAT_SNMPINVALIDMSGS);
03870 DEBUGINDENTLESS();
03871 return SNMPERR_INVALID_MSG;
03872 }
03873 pdu->securityLevel = ((msg_flags & SNMP_MSG_FLAG_AUTH_BIT)
03874 ? ((msg_flags & SNMP_MSG_FLAG_PRIV_BIT)
03875 ? SNMP_SEC_LEVEL_AUTHPRIV
03876 : SNMP_SEC_LEVEL_AUTHNOPRIV)
03877 : SNMP_SEC_LEVEL_NOAUTH);
03878
03879
03880
03881
03882
03883
03884
03885 sec_params = data;
03886 pdu->contextEngineID = (u_char *) calloc(1, SNMP_MAX_ENG_SIZE);
03887 pdu->contextEngineIDLen = SNMP_MAX_ENG_SIZE;
03888
03889
03890
03891
03892
03893
03894
03895 pdu->securityEngineID = (u_char *) calloc(1, SNMP_MAX_ENG_SIZE * 2);
03896 pdu->securityEngineIDLen = SNMP_MAX_ENG_SIZE * 2;
03897 pdu->securityName = (char *) calloc(1, SNMP_MAX_SEC_NAME_SIZE);
03898 pdu->securityNameLen = SNMP_MAX_SEC_NAME_SIZE;
03899
03900 if ((pdu->securityName == NULL) ||
03901 (pdu->securityEngineID == NULL) ||
03902 (pdu->contextEngineID == NULL)) {
03903 return SNMPERR_MALLOC;
03904 }
03905
03906 if (pdu_buf_len < msg_len
03907 && pdu->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
03908
03909
03910
03911 mallocbuf = (u_char *) calloc(1, msg_len);
03912 pdu_buf_len = msg_len;
03913 cp = mallocbuf;
03914 } else {
03915 memset(pdu_buf, 0, pdu_buf_len);
03916 cp = pdu_buf;
03917 }
03918
03919 DEBUGDUMPSECTION("recv", "SM msgSecurityParameters");
03920 if (sptr->decode) {
03921 struct snmp_secmod_incoming_params parms;
03922 parms.msgProcModel = pdu->msgParseModel;
03923 parms.maxMsgSize = msg_max_size;
03924 parms.secParams = sec_params;
03925 parms.secModel = msg_sec_model;
03926 parms.secLevel = pdu->securityLevel;
03927 parms.wholeMsg = msg_data;
03928 parms.wholeMsgLen = msg_len;
03929 parms.secEngineID = pdu->securityEngineID;
03930 parms.secEngineIDLen = &pdu->securityEngineIDLen;
03931 parms.secName = pdu->securityName;
03932 parms.secNameLen = &pdu->securityNameLen;
03933 parms.scopedPdu = &cp;
03934 parms.scopedPduLen = &pdu_buf_len;
03935 parms.maxSizeResponse = &max_size_response;
03936 parms.secStateRef = &pdu->securityStateRef;
03937 parms.sess = sess;
03938 parms.pdu = pdu;
03939 parms.msg_flags = msg_flags;
03940 ret_val = (*sptr->decode) (&parms);
03941 } else {
03942 SNMP_FREE(mallocbuf);
03943 DEBUGINDENTLESS();
03944 snmp_log(LOG_WARNING, "security service %ld can't decode packets\n",
03945 msg_sec_model);
03946 return (-1);
03947 }
03948
03949 if (ret_val != SNMPERR_SUCCESS) {
03950 DEBUGDUMPSECTION("recv", "ScopedPDU");
03951
03952
03953
03954 if (cp) {
03955 cp = snmpv3_scopedPDU_parse(pdu, cp, &pdu_buf_len);
03956 }
03957 if (cp) {
03958 DEBUGPRINTPDUTYPE("recv", *cp);
03959 snmp_pdu_parse(pdu, cp, &pdu_buf_len);
03960 DEBUGINDENTADD(-8);
03961 } else {
03962 DEBUGINDENTADD(-4);
03963 }
03964
03965 if (mallocbuf) {
03966 SNMP_FREE(mallocbuf);
03967 }
03968 return ret_val;
03969 }
03970
03971
03972
03973
03974 *length = pdu_buf_len;
03975 DEBUGDUMPSECTION("recv", "ScopedPDU");
03976 data = snmpv3_scopedPDU_parse(pdu, cp, length);
03977 if (data == NULL) {
03978 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03979 DEBUGINDENTADD(-4);
03980 if (mallocbuf) {
03981 SNMP_FREE(mallocbuf);
03982 }
03983 return SNMPERR_ASN_PARSE_ERR;
03984 }
03985
03986
03987
03988
03989 if (after_header != NULL) {
03990 *after_header = data;
03991 tmp_buf_len = *length;
03992 }
03993
03994 DEBUGPRINTPDUTYPE("recv", *data);
03995 ret = snmp_pdu_parse(pdu, data, length);
03996 DEBUGINDENTADD(-8);
03997
03998 if (after_header != NULL) {
03999 *length = tmp_buf_len;
04000 }
04001
04002 if (ret != SNMPERR_SUCCESS) {
04003 ERROR_MSG("error parsing PDU");
04004 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04005 if (mallocbuf) {
04006 SNMP_FREE(mallocbuf);
04007 }
04008 return SNMPERR_ASN_PARSE_ERR;
04009 }
04010
04011 if (mallocbuf) {
04012 SNMP_FREE(mallocbuf);
04013 }
04014 return SNMPERR_SUCCESS;
04015 }
04016
04017 #define ERROR_STAT_LENGTH 11
04018
04019 int
04020 snmpv3_make_report(netsnmp_pdu *pdu, int error)
04021 {
04022
04023 long ltmp;
04024 static oid unknownSecurityLevel[] =
04025 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 };
04026 static oid notInTimeWindow[] =
04027 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 };
04028 static oid unknownUserName[] =
04029 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 };
04030 static oid unknownEngineID[] =
04031 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 };
04032 static oid wrongDigest[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 };
04033 static oid decryptionError[] =
04034 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 };
04035 oid *err_var;
04036 int err_var_len;
04037 int stat_ind;
04038 struct snmp_secmod_def *sptr;
04039
04040 switch (error) {
04041 case SNMPERR_USM_UNKNOWNENGINEID:
04042 stat_ind = STAT_USMSTATSUNKNOWNENGINEIDS;
04043 err_var = unknownEngineID;
04044 err_var_len = ERROR_STAT_LENGTH;
04045 break;
04046 case SNMPERR_USM_UNKNOWNSECURITYNAME:
04047 stat_ind = STAT_USMSTATSUNKNOWNUSERNAMES;
04048 err_var = unknownUserName;
04049 err_var_len = ERROR_STAT_LENGTH;
04050 break;
04051 case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
04052 stat_ind = STAT_USMSTATSUNSUPPORTEDSECLEVELS;
04053 err_var = unknownSecurityLevel;
04054 err_var_len = ERROR_STAT_LENGTH;
04055 break;
04056 case SNMPERR_USM_AUTHENTICATIONFAILURE:
04057 stat_ind = STAT_USMSTATSWRONGDIGESTS;
04058 err_var = wrongDigest;
04059 err_var_len = ERROR_STAT_LENGTH;
04060 break;
04061 case SNMPERR_USM_NOTINTIMEWINDOW:
04062 stat_ind = STAT_USMSTATSNOTINTIMEWINDOWS;
04063 err_var = notInTimeWindow;
04064 err_var_len = ERROR_STAT_LENGTH;
04065 break;
04066 case SNMPERR_USM_DECRYPTIONERROR:
04067 stat_ind = STAT_USMSTATSDECRYPTIONERRORS;
04068 err_var = decryptionError;
04069 err_var_len = ERROR_STAT_LENGTH;
04070 break;
04071 default:
04072 return SNMPERR_GENERR;
04073 }
04074
04075 snmp_free_varbind(pdu->variables);
04076
04077 pdu->variables = NULL;
04078 SNMP_FREE(pdu->securityEngineID);
04079 pdu->securityEngineID =
04080 snmpv3_generate_engineID(&pdu->securityEngineIDLen);
04081 SNMP_FREE(pdu->contextEngineID);
04082 pdu->contextEngineID =
04083 snmpv3_generate_engineID(&pdu->contextEngineIDLen);
04084 pdu->command = SNMP_MSG_REPORT;
04085 pdu->errstat = 0;
04086 pdu->errindex = 0;
04087 SNMP_FREE(pdu->contextName);
04088 pdu->contextName = strdup("");
04089 pdu->contextNameLen = strlen(pdu->contextName);
04090
04091
04092
04093
04094
04095
04096
04097
04098 if (pdu->securityStateRef) {
04099 sptr = find_sec_mod(pdu->securityModel);
04100 if (sptr) {
04101 if (sptr->pdu_free_state_ref) {
04102 (*sptr->pdu_free_state_ref) (pdu->securityStateRef);
04103 } else {
04104 snmp_log(LOG_ERR,
04105 "Security Model %d can't free state references\n",
04106 pdu->securityModel);
04107 }
04108 } else {
04109 snmp_log(LOG_ERR,
04110 "Can't find security model to free ptr: %d\n",
04111 pdu->securityModel);
04112 }
04113 pdu->securityStateRef = NULL;
04114 }
04115
04116 if (error == SNMPERR_USM_NOTINTIMEWINDOW) {
04117 pdu->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
04118 } else {
04119 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
04120 }
04121
04122
04123
04124
04125 ltmp = snmp_get_statistic(stat_ind);
04126
04127
04128
04129
04130 snmp_pdu_add_variable(pdu, err_var, err_var_len,
04131 ASN_COUNTER, & ltmp, sizeof(ltmp));
04132
04133 return SNMPERR_SUCCESS;
04134 }
04135
04136
04137 int
04138 snmpv3_get_report_type(netsnmp_pdu *pdu)
04139 {
04140 static oid snmpMPDStats[] = { 1, 3, 6, 1, 6, 3, 11, 2, 1 };
04141 static oid usmStats[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1 };
04142 netsnmp_variable_list *vp;
04143 int rpt_type = SNMPERR_UNKNOWN_REPORT;
04144
04145 if (pdu == NULL || pdu->variables == NULL)
04146 return rpt_type;
04147 vp = pdu->variables;
04148 if (vp->name_length == REPORT_STATS_LEN + 2) {
04149 if (memcmp(snmpMPDStats, vp->name, REPORT_STATS_LEN * sizeof(oid))
04150 == 0) {
04151 switch (vp->name[REPORT_STATS_LEN]) {
04152 case REPORT_snmpUnknownSecurityModels_NUM:
04153 rpt_type = SNMPERR_UNKNOWN_SEC_MODEL;
04154 break;
04155 case REPORT_snmpInvalidMsgs_NUM:
04156 rpt_type = SNMPERR_INVALID_MSG;
04157 break;
04158 }
04159 } else
04160 if (memcmp(usmStats, vp->name, REPORT_STATS_LEN * sizeof(oid))
04161 == 0) {
04162 switch (vp->name[REPORT_STATS_LEN]) {
04163 case REPORT_usmStatsUnsupportedSecLevels_NUM:
04164 rpt_type = SNMPERR_UNSUPPORTED_SEC_LEVEL;
04165 break;
04166 case REPORT_usmStatsNotInTimeWindows_NUM:
04167 rpt_type = SNMPERR_NOT_IN_TIME_WINDOW;
04168 break;
04169 case REPORT_usmStatsUnknownUserNames_NUM:
04170 rpt_type = SNMPERR_UNKNOWN_USER_NAME;
04171 break;
04172 case REPORT_usmStatsUnknownEngineIDs_NUM:
04173 rpt_type = SNMPERR_UNKNOWN_ENG_ID;
04174 break;
04175 case REPORT_usmStatsWrongDigests_NUM:
04176 rpt_type = SNMPERR_AUTHENTICATION_FAILURE;
04177 break;
04178 case REPORT_usmStatsDecryptionErrors_NUM:
04179 rpt_type = SNMPERR_DECRYPTION_ERR;
04180 break;
04181 }
04182 }
04183 }
04184 DEBUGMSGTL(("report", "Report type: %d\n", rpt_type));
04185 return rpt_type;
04186 }
04187
04188
04189
04190
04191
04192
04193
04194 static int
04195 _snmp_parse(void *sessp,
04196 netsnmp_session * session,
04197 netsnmp_pdu *pdu, u_char * data, size_t length)
04198 {
04199 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
04200 u_char community[COMMUNITY_MAX_LEN];
04201 size_t community_length = COMMUNITY_MAX_LEN;
04202 #endif
04203 int result = -1;
04204
04205 static oid snmpEngineIDoid[] = { 1,3,6,1,6,3,10,2,1,1,0};
04206 static size_t snmpEngineIDoid_len = 11;
04207
04208 static char ourEngineID[SNMP_SEC_PARAM_BUF_SIZE];
04209 static size_t ourEngineID_len = sizeof(ourEngineID);
04210
04211 netsnmp_pdu *pdu2 = NULL;
04212
04213 session->s_snmp_errno = 0;
04214 session->s_errno = 0;
04215
04216
04217
04218
04219
04220
04221 pdu->transid = snmp_get_next_transid();
04222
04223 if (session->version != SNMP_DEFAULT_VERSION) {
04224 pdu->version = session->version;
04225 } else {
04226 pdu->version = snmp_parse_version(data, length);
04227 }
04228
04229 switch (pdu->version) {
04230 #ifndef NETSNMP_DISABLE_SNMPV1
04231 case SNMP_VERSION_1:
04232 #endif
04233 #ifndef NETSNMP_DISABLE_SNMPV2C
04234 case SNMP_VERSION_2c:
04235 #endif
04236 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
04237 DEBUGMSGTL(("snmp_api", "Parsing SNMPv%ld message...\n",
04238 (1 + pdu->version)));
04239
04240
04241
04242
04243 #ifndef NETSNMP_DISABLE_SNMPV1
04244 if (pdu->version == SNMP_VERSION_1) {
04245 DEBUGDUMPSECTION("recv", "SNMPv1 message\n");
04246 } else {
04247 #endif
04248 DEBUGDUMPSECTION("recv", "SNMPv2c message\n");
04249 #ifndef NETSNMP_DISABLE_SNMPV1
04250 }
04251 #endif
04252 data = snmp_comstr_parse(data, &length,
04253 community, &community_length,
04254 &pdu->version);
04255 if (data == NULL)
04256 return -1;
04257
04258 if (pdu->version != session->version &&
04259 session->version != SNMP_DEFAULT_VERSION) {
04260 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04261 return -1;
04262 }
04263
04264
04265
04266
04267 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
04268 pdu->securityModel =
04269 #ifndef NETSNMP_DISABLE_SNMPV1
04270 (pdu->version == SNMP_VERSION_1) ? SNMP_SEC_MODEL_SNMPv1 :
04271 #endif
04272 SNMP_SEC_MODEL_SNMPv2c;
04273 SNMP_FREE(pdu->community);
04274 pdu->community_len = 0;
04275 pdu->community = (u_char *) 0;
04276 if (community_length) {
04277 pdu->community_len = community_length;
04278 pdu->community = (u_char *) malloc(community_length);
04279 if (pdu->community == NULL) {
04280 session->s_snmp_errno = SNMPERR_MALLOC;
04281 return -1;
04282 }
04283 memmove(pdu->community, community, community_length);
04284 }
04285 if (session->authenticator) {
04286 data = session->authenticator(data, &length,
04287 community, community_length);
04288 if (data == NULL) {
04289 session->s_snmp_errno = SNMPERR_AUTHENTICATION_FAILURE;
04290 return -1;
04291 }
04292 }
04293
04294 DEBUGDUMPSECTION("recv", "PDU");
04295 result = snmp_pdu_parse(pdu, data, &length);
04296 if (result < 0) {
04297
04298
04299
04300 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04301 }
04302 DEBUGINDENTADD(-6);
04303 break;
04304 #endif
04305
04306 case SNMP_VERSION_3:
04307 result = snmpv3_parse(pdu, data, &length, NULL, session);
04308 DEBUGMSGTL(("snmp_parse",
04309 "Parsed SNMPv3 message (secName:%s, secLevel:%s): %s\n",
04310 pdu->securityName, secLevelName[pdu->securityLevel],
04311 snmp_api_errstring(result)));
04312
04313 if (result) {
04314 struct snmp_secmod_def *secmod =
04315 find_sec_mod(pdu->securityModel);
04316 if (!sessp) {
04317 session->s_snmp_errno = result;
04318 } else {
04319
04320
04321
04322
04323 if (secmod && secmod->handle_report) {
04324 struct session_list *slp = (struct session_list *) sessp;
04325 (*secmod->handle_report)(sessp, slp->transport, session,
04326 result, pdu);
04327 }
04328 }
04329 if (pdu->securityStateRef != NULL) {
04330 if (secmod && secmod->pdu_free_state_ref) {
04331 secmod->pdu_free_state_ref(pdu->securityStateRef);
04332 pdu->securityStateRef = NULL;
04333 }
04334 }
04335 }
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
04368 NETSNMP_DS_LIB_NO_DISCOVERY) &&
04369 SNMP_MSG_RESPONSE != pdu->command &&
04370 NULL != pdu->contextEngineID &&
04371 pdu->contextEngineIDLen == 5 &&
04372 pdu->contextEngineID[0] == 0x80 &&
04373 pdu->contextEngineID[1] == 0x00 &&
04374 pdu->contextEngineID[2] == 0x00 &&
04375 pdu->contextEngineID[3] == 0x00 &&
04376 pdu->contextEngineID[4] == 0x06) {
04377
04378
04379
04380 result = SNMPERR_JUST_A_CONTEXT_PROBE;
04381
04382 DEBUGMSGTL(("snmpv3_contextid", "starting context ID discovery\n"));
04383
04384 if (NULL != pdu->variables &&
04385 NULL == pdu->variables->next_variable &&
04386
04387
04388 ((SNMP_MSG_GET == pdu->command &&
04389 snmp_oid_compare(snmpEngineIDoid,
04390 snmpEngineIDoid_len,
04391 pdu->variables->name,
04392 pdu->variables->name_length) == 0)
04393
04394 ||
04395 (SNMP_MSG_GETNEXT == pdu->command &&
04396 snmp_oid_compare(snmpEngineIDoid,
04397 snmpEngineIDoid_len,
04398 pdu->variables->name,
04399 pdu->variables->name_length) > 0)
04400 )) {
04401
04402 DEBUGMSGTL(("snmpv3_contextid",
04403 " One correct variable found\n"));
04404
04405
04406
04407
04408 pdu2 = snmp_clone_pdu(pdu);
04409
04410
04411 snmp_free_varbind(pdu2->variables);
04412
04413
04414 pdu2->variables = NULL;
04415 pdu2->command = SNMP_MSG_RESPONSE;
04416 pdu2->errstat = 0;
04417 pdu2->errindex = 0;
04418
04419 ourEngineID_len =
04420 snmpv3_get_engineID((u_char*)ourEngineID, ourEngineID_len);
04421 if (0 != ourEngineID_len) {
04422
04423 DEBUGMSGTL(("snmpv3_contextid",
04424 " responding with our engineID\n"));
04425
04426 snmp_pdu_add_variable(pdu2,
04427 snmpEngineIDoid, snmpEngineIDoid_len,
04428 ASN_OCTET_STR,
04429 ourEngineID, ourEngineID_len);
04430
04431
04432 if (0 == snmp_sess_send(sessp, pdu2)) {
04433
04434 DEBUGMSGTL(("snmpv3_contextid",
04435 " sent it off!\n"));
04436
04437 snmp_free_pdu(pdu2);
04438
04439 snmp_log(LOG_ERR, "sending a response to the context engineID probe failed\n");
04440 }
04441 } else {
04442 snmp_log(LOG_ERR, "failed to get our own engineID!\n");
04443 }
04444 } else {
04445 snmp_log(LOG_WARNING,
04446 "received an odd context engineID probe\n");
04447 }
04448 }
04449
04450 break;
04451 case SNMPERR_BAD_VERSION:
04452 ERROR_MSG("error parsing snmp message version");
04453 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04454 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04455 break;
04456 case SNMP_VERSION_sec:
04457 case SNMP_VERSION_2u:
04458 case SNMP_VERSION_2star:
04459 case SNMP_VERSION_2p:
04460 default:
04461 ERROR_MSG("unsupported snmp message version");
04462 snmp_increment_statistic(STAT_SNMPINBADVERSIONS);
04463
04464
04465
04466
04467
04468 if (pdu->version < 0 || pdu->version > 2147483647) {
04469 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04470 }
04471 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04472 break;
04473 }
04474
04475 return result;
04476 }
04477
04478 static int
04479 snmp_parse(void *sessp,
04480 netsnmp_session * pss,
04481 netsnmp_pdu *pdu, u_char * data, size_t length)
04482 {
04483 int rc;
04484
04485 rc = _snmp_parse(sessp, pss, pdu, data, length);
04486 if (rc) {
04487 if (!pss->s_snmp_errno) {
04488 pss->s_snmp_errno = SNMPERR_BAD_PARSE;
04489 }
04490 SET_SNMP_ERROR(pss->s_snmp_errno);
04491 }
04492
04493 return rc;
04494 }
04495
04496 int
04497 snmp_pdu_parse(netsnmp_pdu *pdu, u_char * data, size_t * length)
04498 {
04499 u_char type;
04500 u_char msg_type;
04501 u_char *var_val;
04502 int badtype = 0;
04503 size_t len;
04504 size_t four;
04505 netsnmp_variable_list *vp = NULL;
04506 oid objid[MAX_OID_LEN];
04507
04508
04509
04510
04511 data = asn_parse_header(data, length, &msg_type);
04512 if (data == NULL)
04513 return -1;
04514 DEBUGMSGTL(("dumpv_recv"," Command %s\n", snmp_pdu_type(msg_type)));
04515 pdu->command = msg_type;
04516 pdu->flags &= (~UCD_MSG_FLAG_RESPONSE_PDU);
04517
04518
04519
04520
04521 switch (pdu->command) {
04522 case SNMP_MSG_TRAP:
04523
04524
04525
04526 pdu->enterprise_length = MAX_OID_LEN;
04527 data = asn_parse_objid(data, length, &type, objid,
04528 &pdu->enterprise_length);
04529 if (data == NULL)
04530 return -1;
04531 pdu->enterprise =
04532 (oid *) malloc(pdu->enterprise_length * sizeof(oid));
04533 if (pdu->enterprise == NULL) {
04534 return -1;
04535 }
04536 memmove(pdu->enterprise, objid,
04537 pdu->enterprise_length * sizeof(oid));
04538
04539
04540
04541
04542 four = 4;
04543 data = asn_parse_string(data, length, &type,
04544 (u_char *) pdu->agent_addr, &four);
04545 if (data == NULL)
04546 return -1;
04547
04548
04549
04550
04551 data = asn_parse_int(data, length, &type, (long *) &pdu->trap_type,
04552 sizeof(pdu->trap_type));
04553 if (data == NULL)
04554 return -1;
04555
04556
04557
04558 data =
04559 asn_parse_int(data, length, &type,
04560 (long *) &pdu->specific_type,
04561 sizeof(pdu->specific_type));
04562 if (data == NULL)
04563 return -1;
04564
04565
04566
04567
04568 data = asn_parse_unsigned_int(data, length, &type, &pdu->time,
04569 sizeof(pdu->time));
04570 if (data == NULL)
04571 return -1;
04572
04573 break;
04574
04575 case SNMP_MSG_RESPONSE:
04576 case SNMP_MSG_REPORT:
04577 pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU;
04578
04579
04580
04581
04582 case SNMP_MSG_GET:
04583 case SNMP_MSG_GETNEXT:
04584 case SNMP_MSG_GETBULK:
04585 case SNMP_MSG_TRAP2:
04586 case SNMP_MSG_INFORM:
04587 case SNMP_MSG_SET:
04588
04589
04590
04591
04592
04593
04594
04595 DEBUGDUMPHEADER("recv", "request_id");
04596 data = asn_parse_int(data, length, &type, &pdu->reqid,
04597 sizeof(pdu->reqid));
04598 DEBUGINDENTLESS();
04599 if (data == NULL) {
04600 return -1;
04601 }
04602
04603
04604
04605
04606 DEBUGDUMPHEADER("recv", "error status");
04607 data = asn_parse_int(data, length, &type, &pdu->errstat,
04608 sizeof(pdu->errstat));
04609 DEBUGINDENTLESS();
04610 if (data == NULL) {
04611 return -1;
04612 }
04613
04614
04615
04616
04617 DEBUGDUMPHEADER("recv", "error index");
04618 data = asn_parse_int(data, length, &type, &pdu->errindex,
04619 sizeof(pdu->errindex));
04620 DEBUGINDENTLESS();
04621 if (data == NULL) {
04622 return -1;
04623 }
04624 break;
04625
04626 default:
04627 snmp_log(LOG_ERR, "Bad PDU type received: 0x%.2x\n", pdu->command);
04628 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04629 return -1;
04630 }
04631
04632
04633
04634
04635 DEBUGDUMPSECTION("recv", "VarBindList");
04636 data = asn_parse_sequence(data, length, &type,
04637 (ASN_SEQUENCE | ASN_CONSTRUCTOR),
04638 "varbinds");
04639 if (data == NULL)
04640 return -1;
04641
04642
04643
04644
04645 while ((int) *length > 0) {
04646 netsnmp_variable_list *vptemp;
04647 vptemp = (netsnmp_variable_list *) malloc(sizeof(*vptemp));
04648 if (NULL == vptemp) {
04649 return -1;
04650 }
04651 if (NULL == vp) {
04652 pdu->variables = vptemp;
04653 } else {
04654 vp->next_variable = vptemp;
04655 }
04656 vp = vptemp;
04657
04658 vp->next_variable = NULL;
04659 vp->val.string = NULL;
04660 vp->name_length = MAX_OID_LEN;
04661 vp->name = NULL;
04662 vp->index = 0;
04663 vp->data = NULL;
04664 vp->dataFreeHook = NULL;
04665 DEBUGDUMPSECTION("recv", "VarBind");
04666 data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type,
04667 &vp->val_len, &var_val, length);
04668 if (data == NULL)
04669 return -1;
04670 if (snmp_set_var_objid(vp, objid, vp->name_length))
04671 return -1;
04672
04673 len = MAX_PACKET_LENGTH;
04674 DEBUGDUMPHEADER("recv", "Value");
04675 switch ((short) vp->type) {
04676 case ASN_INTEGER:
04677 vp->val.integer = (long *) vp->buf;
04678 vp->val_len = sizeof(long);
04679 asn_parse_int(var_val, &len, &vp->type,
04680 (long *) vp->val.integer,
04681 sizeof(*vp->val.integer));
04682 break;
04683 case ASN_COUNTER:
04684 case ASN_GAUGE:
04685 case ASN_TIMETICKS:
04686 case ASN_UINTEGER:
04687 vp->val.integer = (long *) vp->buf;
04688 vp->val_len = sizeof(u_long);
04689 asn_parse_unsigned_int(var_val, &len, &vp->type,
04690 (u_long *) vp->val.integer,
04691 vp->val_len);
04692 break;
04693 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
04694 case ASN_OPAQUE_COUNTER64:
04695 case ASN_OPAQUE_U64:
04696 #endif
04697 case ASN_COUNTER64:
04698 vp->val.counter64 = (struct counter64 *) vp->buf;
04699 vp->val_len = sizeof(struct counter64);
04700 asn_parse_unsigned_int64(var_val, &len, &vp->type,
04701 (struct counter64 *) vp->val.
04702 counter64, vp->val_len);
04703 break;
04704 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
04705 case ASN_OPAQUE_FLOAT:
04706 vp->val.floatVal = (float *) vp->buf;
04707 vp->val_len = sizeof(float);
04708 asn_parse_float(var_val, &len, &vp->type,
04709 vp->val.floatVal, vp->val_len);
04710 break;
04711 case ASN_OPAQUE_DOUBLE:
04712 vp->val.doubleVal = (double *) vp->buf;
04713 vp->val_len = sizeof(double);
04714 asn_parse_double(var_val, &len, &vp->type,
04715 vp->val.doubleVal, vp->val_len);
04716 break;
04717 case ASN_OPAQUE_I64:
04718 vp->val.counter64 = (struct counter64 *) vp->buf;
04719 vp->val_len = sizeof(struct counter64);
04720 asn_parse_signed_int64(var_val, &len, &vp->type,
04721 (struct counter64 *) vp->val.counter64,
04722 sizeof(*vp->val.counter64));
04723
04724 break;
04725 #endif
04726 case ASN_OCTET_STR:
04727 case ASN_IPADDRESS:
04728 case ASN_OPAQUE:
04729 case ASN_NSAP:
04730 if (vp->val_len < sizeof(vp->buf)) {
04731 vp->val.string = (u_char *) vp->buf;
04732 } else {
04733 vp->val.string = (u_char *) malloc(vp->val_len);
04734 }
04735 if (vp->val.string == NULL) {
04736 return -1;
04737 }
04738 asn_parse_string(var_val, &len, &vp->type, vp->val.string,
04739 &vp->val_len);
04740 break;
04741 case ASN_OBJECT_ID:
04742 vp->val_len = MAX_OID_LEN;
04743 asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len);
04744 vp->val_len *= sizeof(oid);
04745 vp->val.objid = (oid *) malloc(vp->val_len);
04746 if (vp->val.objid == NULL) {
04747 return -1;
04748 }
04749 memmove(vp->val.objid, objid, vp->val_len);
04750 break;
04751 case SNMP_NOSUCHOBJECT:
04752 case SNMP_NOSUCHINSTANCE:
04753 case SNMP_ENDOFMIBVIEW:
04754 case ASN_NULL:
04755 break;
04756 case ASN_BIT_STR:
04757 vp->val.bitstring = (u_char *) malloc(vp->val_len);
04758 if (vp->val.bitstring == NULL) {
04759 return -1;
04760 }
04761 asn_parse_bitstring(var_val, &len, &vp->type,
04762 vp->val.bitstring, &vp->val_len);
04763 break;
04764 default:
04765 snmp_log(LOG_ERR, "bad type returned (%x)\n", vp->type);
04766 badtype = -1;
04767 break;
04768 }
04769 DEBUGINDENTADD(-4);
04770 }
04771 return badtype;
04772 }
04773
04774
04775
04776
04777
04778
04779
04780
04781 u_char *
04782 snmpv3_scopedPDU_parse(netsnmp_pdu *pdu, u_char * cp, size_t * length)
04783 {
04784 u_char tmp_buf[SNMP_MAX_MSG_SIZE];
04785 size_t tmp_buf_len;
04786 u_char type;
04787 size_t asn_len;
04788 u_char *data;
04789
04790 pdu->command = 0;
04791 asn_len = *length;
04792 data = asn_parse_sequence(cp, &asn_len, &type,
04793 (ASN_SEQUENCE | ASN_CONSTRUCTOR),
04794 "plaintext scopedPDU");
04795 if (data == NULL) {
04796 return NULL;
04797 }
04798 *length -= data - cp;
04799
04800
04801
04802
04803 DEBUGDUMPHEADER("recv", "contextEngineID");
04804 data = asn_parse_string(data, length, &type, pdu->contextEngineID,
04805 &pdu->contextEngineIDLen);
04806 DEBUGINDENTLESS();
04807 if (data == NULL) {
04808 ERROR_MSG("error parsing contextEngineID from scopedPdu");
04809 return NULL;
04810 }
04811
04812
04813
04814
04815
04816 if (pdu->securityEngineIDLen != pdu->contextEngineIDLen ||
04817 memcmp(pdu->securityEngineID, pdu->contextEngineID,
04818 pdu->securityEngineIDLen) != 0) {
04819 DEBUGMSGTL(("scopedPDU_parse",
04820 "inconsistent engineID information in message\n"));
04821 }
04822
04823
04824
04825
04826 tmp_buf_len = SNMP_MAX_CONTEXT_SIZE;
04827 DEBUGDUMPHEADER("recv", "contextName");
04828 data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len);
04829 DEBUGINDENTLESS();
04830 if (data == NULL) {
04831 ERROR_MSG("error parsing contextName from scopedPdu");
04832 return NULL;
04833 }
04834
04835 if (tmp_buf_len) {
04836 pdu->contextName = (char *) malloc(tmp_buf_len);
04837 memmove(pdu->contextName, tmp_buf, tmp_buf_len);
04838 pdu->contextNameLen = tmp_buf_len;
04839 } else {
04840 pdu->contextName = strdup("");
04841 pdu->contextNameLen = 0;
04842 }
04843 if (pdu->contextName == NULL) {
04844 ERROR_MSG("error copying contextName from scopedPdu");
04845 return NULL;
04846 }
04847
04848
04849
04850
04851 asn_len = *length;
04852 cp = asn_parse_header(data, &asn_len, &type);
04853 if (cp == NULL)
04854 return NULL;
04855
04856 pdu->command = type;
04857
04858 return data;
04859 }
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883 int
04884 snmp_send(netsnmp_session * session, netsnmp_pdu *pdu)
04885 {
04886 return snmp_async_send(session, pdu, NULL, NULL);
04887 }
04888
04889 int
04890 snmp_sess_send(void *sessp, netsnmp_pdu *pdu)
04891 {
04892 return snmp_sess_async_send(sessp, pdu, NULL, NULL);
04893 }
04894
04895 int
04896 snmp_async_send(netsnmp_session * session,
04897 netsnmp_pdu *pdu, snmp_callback callback, void *cb_data)
04898 {
04899 void *sessp = snmp_sess_pointer(session);
04900 return snmp_sess_async_send(sessp, pdu, callback, cb_data);
04901 }
04902
04903 static int
04904 _sess_async_send(void *sessp,
04905 netsnmp_pdu *pdu, snmp_callback callback, void *cb_data)
04906 {
04907 struct session_list *slp = (struct session_list *) sessp;
04908 netsnmp_session *session;
04909 struct snmp_internal_session *isp;
04910 netsnmp_transport *transport = NULL;
04911 u_char *pktbuf = NULL, *packet = NULL;
04912 size_t pktbuf_len = 0, offset = 0, length = 0;
04913 int result;
04914 long reqid;
04915
04916 if (slp == NULL) {
04917 return 0;
04918 } else {
04919 session = slp->session;
04920 isp = slp->internal;
04921 transport = slp->transport;
04922 if (!session || !isp || !transport) {
04923 DEBUGMSGTL(("sess_async_send", "send fail: closing...\n"));
04924 return 0;
04925 }
04926 }
04927
04928 if (pdu == NULL) {
04929 session->s_snmp_errno = SNMPERR_NULL_PDU;
04930 return 0;
04931 }
04932
04933 session->s_snmp_errno = 0;
04934 session->s_errno = 0;
04935
04936
04937
04938
04939 if (pdu->version == SNMP_DEFAULT_VERSION) {
04940 if (session->version == SNMP_DEFAULT_VERSION) {
04941 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04942 return 0;
04943 }
04944 pdu->version = session->version;
04945 } else if (session->version == SNMP_DEFAULT_VERSION) {
04946
04947
04948
04949 } else if (pdu->version != session->version) {
04950
04951
04952
04953 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04954 return 0;
04955 }
04956
04957
04958
04959
04960 switch (pdu->command) {
04961
04962 case SNMP_MSG_RESPONSE:
04963 case SNMP_MSG_TRAP:
04964 case SNMP_MSG_TRAP2:
04965 case SNMP_MSG_REPORT:
04966 case AGENTX_MSG_CLEANUPSET:
04967 case AGENTX_MSG_RESPONSE:
04968 pdu->flags &= ~UCD_MSG_FLAG_EXPECT_RESPONSE;
04969 break;
04970
04971 default:
04972 pdu->flags |= UCD_MSG_FLAG_EXPECT_RESPONSE;
04973 break;
04974 }
04975
04976
04977
04978
04979 if ((pdu->version == SNMP_VERSION_3) &&
04980 (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE) &&
04981 (session->securityEngineIDLen == 0) &&
04982 (0 == (session->flags & SNMP_FLAGS_DONT_PROBE))) {
04983 int rc;
04984 DEBUGMSGTL(("snmpv3_build", "delayed probe for engineID\n"));
04985 rc = snmpv3_engineID_probe(slp, session);
04986 if (rc == 0)
04987 return 0;
04988 }
04989
04990
04991
04992
04993 if (create_user_from_session(session) != SNMPERR_SUCCESS) {
04994 session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
04995 DEBUGMSGTL(("snmp_api",
04996 "snmp_send(): failed(2) to create a new user from session\n"));
04997 return 0;
04998 }
04999
05000 if ((pktbuf = (u_char *)malloc(2048)) == NULL) {
05001 DEBUGMSGTL(("sess_async_send",
05002 "couldn't malloc initial packet buffer\n"));
05003 session->s_snmp_errno = SNMPERR_MALLOC;
05004 return 0;
05005 } else {
05006 pktbuf_len = 2048;
05007 }
05008
05009 #if TEMPORARILY_DISABLED
05010
05011
05012
05013
05014
05015
05016
05017
05018 if (pdu->variables == NULL) {
05019 switch (pdu->command) {
05020 case SNMP_MSG_GET:
05021 case SNMP_MSG_SET:
05022 case SNMP_MSG_GETNEXT:
05023 case SNMP_MSG_GETBULK:
05024 case SNMP_MSG_RESPONSE:
05025 case SNMP_MSG_TRAP2:
05026 case SNMP_MSG_REPORT:
05027 case SNMP_MSG_INFORM:
05028 session->s_snmp_errno = snmp_errno = SNMPERR_NO_VARS;
05029 return 0;
05030 case SNMP_MSG_TRAP:
05031 break;
05032 }
05033 }
05034 #endif
05035
05036
05037
05038
05039
05040 if (isp->hook_realloc_build) {
05041 result = isp->hook_realloc_build(session, pdu,
05042 &pktbuf, &pktbuf_len, &offset);
05043 packet = pktbuf;
05044 length = offset;
05045 } else if (isp->hook_build) {
05046 packet = pktbuf;
05047 length = pktbuf_len;
05048 result = isp->hook_build(session, pdu, pktbuf, &length);
05049 } else {
05050 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
05051 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
05052 result =
05053 snmp_build(&pktbuf, &pktbuf_len, &offset, session, pdu);
05054 packet = pktbuf + pktbuf_len - offset;
05055 length = offset;
05056 } else {
05057 #endif
05058 packet = pktbuf;
05059 length = pktbuf_len;
05060 result = snmp_build(&pktbuf, &length, &offset, session, pdu);
05061 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
05062 }
05063 #endif
05064 }
05065
05066 if (result < 0) {
05067 DEBUGMSGTL(("sess_async_send", "encoding failure\n"));
05068 SNMP_FREE(pktbuf);
05069 return 0;
05070 }
05071
05072
05073
05074
05075
05076
05077 if (session->sndMsgMaxSize != 0 && length > session->sndMsgMaxSize) {
05078 DEBUGMSGTL(("sess_async_send",
05079 "length of packet (%lu) exceeds session maximum (%lu)\n",
05080 (unsigned long)length, (unsigned long)session->sndMsgMaxSize));
05081 session->s_snmp_errno = SNMPERR_TOO_LONG;
05082 SNMP_FREE(pktbuf);
05083 return 0;
05084 }
05085
05086
05087
05088
05089
05090
05091 if (transport->msgMaxSize != 0 && length > transport->msgMaxSize) {
05092 DEBUGMSGTL(("sess_async_send",
05093 "length of packet (%lu) exceeds transport maximum (%lu)\n",
05094 (unsigned long)length, (unsigned long)transport->msgMaxSize));
05095 session->s_snmp_errno = SNMPERR_TOO_LONG;
05096 SNMP_FREE(pktbuf);
05097 return 0;
05098 }
05099
05100 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET)) {
05101 if (transport->f_fmtaddr != NULL) {
05102 char *dest_txt =
05103 transport->f_fmtaddr(transport, pdu->transport_data,
05104 pdu->transport_data_length);
05105 if (dest_txt != NULL) {
05106 snmp_log(LOG_DEBUG, "\nSending %lu bytes to %s\n", (unsigned long)length,
05107 dest_txt);
05108 SNMP_FREE(dest_txt);
05109 } else {
05110 snmp_log(LOG_DEBUG, "\nSending %lu bytes to <UNKNOWN>\n",
05111 (unsigned long)length);
05112 }
05113 }
05114 xdump(packet, length, "");
05115 }
05116
05117
05118
05119
05120
05121 DEBUGMSGTL(("sess_process_packet", "sending message id#%ld reqid#%ld\n",
05122 pdu->msgid, pdu->reqid));
05123 result = transport->f_send(transport, packet, length,
05124 &(pdu->transport_data),
05125 &(pdu->transport_data_length));
05126
05127 SNMP_FREE(pktbuf);
05128
05129 if (result < 0) {
05130 session->s_snmp_errno = SNMPERR_BAD_SENDTO;
05131 session->s_errno = errno;
05132 return 0;
05133 }
05134
05135 reqid = pdu->reqid;
05136
05137
05138
05139
05140 if (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE) {
05141 netsnmp_request_list *rp;
05142 struct timeval tv;
05143
05144 rp = (netsnmp_request_list *) calloc(1,
05145 sizeof(netsnmp_request_list));
05146 if (rp == NULL) {
05147 session->s_snmp_errno = SNMPERR_GENERR;
05148 return 0;
05149 }
05150
05151 gettimeofday(&tv, (struct timezone *) 0);
05152 rp->pdu = pdu;
05153 rp->request_id = pdu->reqid;
05154 rp->message_id = pdu->msgid;
05155 rp->callback = callback;
05156 rp->cb_data = cb_data;
05157 rp->retries = 0;
05158 if (pdu->flags & UCD_MSG_FLAG_PDU_TIMEOUT) {
05159 rp->timeout = pdu->time * 1000000L;
05160 } else {
05161 rp->timeout = session->timeout;
05162 }
05163 rp->time = tv;
05164 tv.tv_usec += rp->timeout;
05165 tv.tv_sec += tv.tv_usec / 1000000L;
05166 tv.tv_usec %= 1000000L;
05167 rp->expire = tv;
05168
05169
05170
05171
05172 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
05173 if (isp->requestsEnd) {
05174 rp->next_request = isp->requestsEnd->next_request;
05175 isp->requestsEnd->next_request = rp;
05176 isp->requestsEnd = rp;
05177 } else {
05178 rp->next_request = isp->requests;
05179 isp->requests = rp;
05180 isp->requestsEnd = rp;
05181 }
05182 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
05183 } else {
05184
05185
05186
05187 if (reqid) {
05188
05189
05190
05191 snmp_free_pdu(pdu);
05192 }
05193 }
05194
05195 return reqid;
05196 }
05197
05198 int
05199 snmp_sess_async_send(void *sessp,
05200 netsnmp_pdu *pdu,
05201 snmp_callback callback, void *cb_data)
05202 {
05203 int rc;
05204
05205 if (sessp == NULL) {
05206 snmp_errno = SNMPERR_BAD_SESSION;
05207 return (0);
05208 }
05209
05210
05211
05212 rc = _sess_async_send(sessp, pdu, callback, cb_data);
05213 if (rc == 0) {
05214 struct session_list *psl;
05215 netsnmp_session *pss;
05216 psl = (struct session_list *) sessp;
05217 pss = psl->session;
05218 SET_SNMP_ERROR(pss->s_snmp_errno);
05219 }
05220 return rc;
05221 }
05222
05223
05224
05225
05226
05227 void
05228 snmp_free_var_internals(netsnmp_variable_list * var)
05229 {
05230 if (!var)
05231 return;
05232
05233 if (var->name != var->name_loc)
05234 SNMP_FREE(var->name);
05235 if (var->val.string != var->buf)
05236 SNMP_FREE(var->val.string);
05237 if (var->data) {
05238 if (var->dataFreeHook) {
05239 var->dataFreeHook(var->data);
05240 var->data = NULL;
05241 } else {
05242 SNMP_FREE(var->data);
05243 }
05244 }
05245 }
05246
05247 void
05248 snmp_free_var(netsnmp_variable_list * var)
05249 {
05250 snmp_free_var_internals(var);
05251 free((char *) var);
05252 }
05253
05254 void
05255 snmp_free_varbind(netsnmp_variable_list * var)
05256 {
05257 netsnmp_variable_list *ptr;
05258 while (var) {
05259 ptr = var->next_variable;
05260 snmp_free_var(var);
05261 var = ptr;
05262 }
05263 }
05264
05265
05266
05267
05268 void
05269 snmp_free_pdu(netsnmp_pdu *pdu)
05270 {
05271 struct snmp_secmod_def *sptr;
05272
05273 if (!pdu)
05274 return;
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296 if ((sptr = find_sec_mod(pdu->securityModel)) != NULL &&
05297 sptr->pdu_free != NULL) {
05298 (*sptr->pdu_free) (pdu);
05299 }
05300 snmp_free_varbind(pdu->variables);
05301 SNMP_FREE(pdu->enterprise);
05302 SNMP_FREE(pdu->community);
05303 SNMP_FREE(pdu->contextEngineID);
05304 SNMP_FREE(pdu->securityEngineID);
05305 SNMP_FREE(pdu->contextName);
05306 SNMP_FREE(pdu->securityName);
05307 SNMP_FREE(pdu->transport_data);
05308 memset(pdu, 0, sizeof(netsnmp_pdu));
05309 free((char *) pdu);
05310 }
05311
05312 netsnmp_pdu *
05313 snmp_create_sess_pdu(netsnmp_transport *transport, void *opaque,
05314 size_t olength)
05315 {
05316 netsnmp_pdu *pdu = (netsnmp_pdu *)calloc(1, sizeof(netsnmp_pdu));
05317 if (pdu == NULL) {
05318 DEBUGMSGTL(("sess_process_packet", "can't malloc space for PDU\n"));
05319 return NULL;
05320 }
05321
05322
05323
05324
05325
05326
05327 pdu->transport_data = opaque;
05328 pdu->transport_data_length = olength;
05329 pdu->tDomain = transport->domain;
05330 pdu->tDomainLen = transport->domain_length;
05331 return pdu;
05332 }
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342 static int
05343 _sess_process_packet(void *sessp, netsnmp_session * sp,
05344 struct snmp_internal_session *isp,
05345 netsnmp_transport *transport,
05346 void *opaque, int olength,
05347 u_char * packetptr, int length)
05348 {
05349 struct session_list *slp = (struct session_list *) sessp;
05350 netsnmp_pdu *pdu;
05351 netsnmp_request_list *rp, *orp = NULL;
05352 struct snmp_secmod_def *sptr;
05353 int ret = 0, handled = 0;
05354
05355 DEBUGMSGTL(("sess_process_packet",
05356 "session %p fd %d pkt %p length %d\n", sessp,
05357 transport->sock, packetptr, length));
05358
05359 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
05360 NETSNMP_DS_LIB_DUMP_PACKET)) {
05361 if (transport->f_fmtaddr != NULL) {
05362 char *addrtxt = transport->f_fmtaddr(transport, opaque, olength);
05363 if (addrtxt != NULL) {
05364 snmp_log(LOG_DEBUG, "\nReceived %d bytes from %s\n",
05365 length, addrtxt);
05366 SNMP_FREE(addrtxt);
05367 } else {
05368 snmp_log(LOG_DEBUG, "\nReceived %d bytes from <UNKNOWN>\n",
05369 length);
05370 }
05371 }
05372 xdump(packetptr, length, "");
05373 }
05374
05375
05376
05377
05378
05379 if (isp->hook_pre) {
05380 if (isp->hook_pre(sp, transport, opaque, olength) == 0) {
05381 DEBUGMSGTL(("sess_process_packet", "pre-parse fail\n"));
05382 if (opaque != NULL) {
05383 SNMP_FREE(opaque);
05384 }
05385 return -1;
05386 }
05387 }
05388
05389 if (isp->hook_create_pdu) {
05390 pdu = isp->hook_create_pdu(transport, opaque, olength);
05391 } else {
05392 pdu = snmp_create_sess_pdu(transport, opaque, olength);
05393 }
05394
05395
05396
05397 if (transport->flags & NETSNMP_TRANSPORT_FLAG_TUNNELED) {
05398 pdu->flags |= UCD_MSG_FLAG_TUNNELED;
05399 }
05400
05401 if (pdu == NULL) {
05402 snmp_log(LOG_ERR, "pdu failed to be created\n");
05403 if (opaque != NULL) {
05404 SNMP_FREE(opaque);
05405 }
05406 return -1;
05407 }
05408
05409 if (isp->hook_parse) {
05410 ret = isp->hook_parse(sp, pdu, packetptr, length);
05411 } else {
05412 ret = snmp_parse(sessp, sp, pdu, packetptr, length);
05413 }
05414
05415 DEBUGMSGTL(("sess_process_packet", "received message id#%ld reqid#%ld\n",
05416 pdu->msgid, pdu->reqid));
05417
05418 if (ret != SNMP_ERR_NOERROR) {
05419 DEBUGMSGTL(("sess_process_packet", "parse fail\n"));
05420 }
05421
05422 if (isp->hook_post) {
05423 if (isp->hook_post(sp, pdu, ret) == 0) {
05424 DEBUGMSGTL(("sess_process_packet", "post-parse fail\n"));
05425 ret = SNMPERR_ASN_PARSE_ERR;
05426 }
05427 }
05428
05429 if (ret != SNMP_ERR_NOERROR) {
05430
05431
05432
05433 if (pdu->securityStateRef != NULL) {
05434 sptr = find_sec_mod(pdu->securityModel);
05435 if (sptr != NULL) {
05436 if (sptr->pdu_free_state_ref != NULL) {
05437 (*sptr->pdu_free_state_ref) (pdu->securityStateRef);
05438 } else {
05439 snmp_log(LOG_ERR,
05440 "Security Model %d can't free state references\n",
05441 pdu->securityModel);
05442 }
05443 } else {
05444 snmp_log(LOG_ERR,
05445 "Can't find security model to free ptr: %d\n",
05446 pdu->securityModel);
05447 }
05448 pdu->securityStateRef = NULL;
05449 }
05450 snmp_free_pdu(pdu);
05451 return -1;
05452 }
05453
05454 if (pdu->flags & UCD_MSG_FLAG_RESPONSE_PDU) {
05455
05456
05457
05458 if (pdu->securityStateRef) {
05459 sptr = find_sec_mod(pdu->securityModel);
05460 if (sptr) {
05461 if (sptr->pdu_free_state_ref) {
05462 (*sptr->pdu_free_state_ref) (pdu->securityStateRef);
05463 } else {
05464 snmp_log(LOG_ERR,
05465 "Security Model %d can't free state references\n",
05466 pdu->securityModel);
05467 }
05468 } else {
05469 snmp_log(LOG_ERR,
05470 "Can't find security model to free ptr: %d\n",
05471 pdu->securityModel);
05472 }
05473 pdu->securityStateRef = NULL;
05474 }
05475
05476 for (rp = isp->requests; rp; orp = rp, rp = rp->next_request) {
05477 snmp_callback callback;
05478 void *magic;
05479
05480 if (pdu->version == SNMP_VERSION_3) {
05481
05482
05483
05484 if (rp->message_id != pdu->msgid) {
05485 DEBUGMSGTL(("sess_process_packet", "unmatched msg id: %ld != %ld\n",
05486 rp->message_id, pdu->msgid));
05487 continue;
05488 }
05489
05490
05491
05492
05493
05494 if (!snmpv3_verify_msg(rp, pdu)) {
05495 break;
05496 }
05497 } else {
05498 if (rp->request_id != pdu->reqid) {
05499 continue;
05500 }
05501 }
05502
05503 if (rp->callback) {
05504 callback = rp->callback;
05505 magic = rp->cb_data;
05506 } else {
05507 callback = sp->callback;
05508 magic = sp->callback_magic;
05509 }
05510 handled = 1;
05511
05512
05513
05514
05515
05516
05517 if (callback == NULL
05518 || callback(NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE, sp,
05519 pdu->reqid, pdu, magic) == 1) {
05520 if (pdu->command == SNMP_MSG_REPORT) {
05521 if (sp->s_snmp_errno == SNMPERR_NOT_IN_TIME_WINDOW ||
05522 snmpv3_get_report_type(pdu) ==
05523 SNMPERR_NOT_IN_TIME_WINDOW) {
05524
05525
05526
05527
05528
05529 if (rp->retries <= sp->retries) {
05530 snmp_resend_request(slp, rp, TRUE);
05531 break;
05532 }
05533 } else {
05534 if (SNMPV3_IGNORE_UNAUTH_REPORTS) {
05535 break;
05536 }
05537 }
05538
05539
05540
05541
05542 if (!sp->securityEngineIDLen && pdu->securityEngineIDLen) {
05543 sp->securityEngineID =
05544 (u_char *) malloc(pdu->securityEngineIDLen);
05545 if (sp->securityEngineID == NULL) {
05546
05547
05548
05549
05550 }
05551 memcpy(sp->securityEngineID, pdu->securityEngineID,
05552 pdu->securityEngineIDLen);
05553 sp->securityEngineIDLen = pdu->securityEngineIDLen;
05554 if (!sp->contextEngineIDLen) {
05555 sp->contextEngineID =
05556 (u_char *) malloc(pdu->
05557 securityEngineIDLen);
05558 if (sp->contextEngineID == NULL) {
05559
05560
05561
05562
05563 }
05564 memcpy(sp->contextEngineID,
05565 pdu->securityEngineID,
05566 pdu->securityEngineIDLen);
05567 sp->contextEngineIDLen =
05568 pdu->securityEngineIDLen;
05569 }
05570 }
05571 }
05572
05573
05574
05575
05576 if (isp->requests == rp) {
05577 isp->requests = rp->next_request;
05578 if (isp->requestsEnd == rp) {
05579 isp->requestsEnd = NULL;
05580 }
05581 } else {
05582 orp->next_request = rp->next_request;
05583 if (isp->requestsEnd == rp) {
05584 isp->requestsEnd = orp;
05585 }
05586 }
05587 snmp_free_pdu(rp->pdu);
05588 free((char *) rp);
05589
05590
05591
05592 break;
05593 }
05594
05595
05596
05597 }
05598 } else {
05599 if (sp->callback) {
05600
05601
05602
05603 handled = 1;
05604 sp->callback(NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE,
05605 sp, pdu->reqid, pdu, sp->callback_magic);
05606
05607
05608
05609 }
05610 }
05611
05612
05613
05614
05615 if (pdu != NULL && pdu->securityStateRef &&
05616 pdu->command == SNMP_MSG_TRAP2) {
05617 sptr = find_sec_mod(pdu->securityModel);
05618 if (sptr) {
05619 if (sptr->pdu_free_state_ref) {
05620 (*sptr->pdu_free_state_ref) (pdu->securityStateRef);
05621 } else {
05622 snmp_log(LOG_ERR,
05623 "Security Model %d can't free state references\n",
05624 pdu->securityModel);
05625 }
05626 } else {
05627 snmp_log(LOG_ERR,
05628 "Can't find security model to free ptr: %d\n",
05629 pdu->securityModel);
05630 }
05631 pdu->securityStateRef = NULL;
05632 }
05633
05634 if (!handled) {
05635 snmp_increment_statistic(STAT_SNMPUNKNOWNPDUHANDLERS);
05636 DEBUGMSGTL(("sess_process_packet", "unhandled PDU\n"));
05637 }
05638
05639 snmp_free_pdu(pdu);
05640 return 0;
05641 }
05642
05643
05644
05645
05646
05647
05648
05649
05650 void
05651 snmp_read(fd_set * fdset)
05652 {
05653 netsnmp_large_fd_set lfdset;
05654
05655 netsnmp_large_fd_set_init(&lfdset, FD_SETSIZE);
05656 netsnmp_copy_fd_set_to_large_fd_set(&lfdset, fdset);
05657 snmp_read2(&lfdset);
05658 netsnmp_large_fd_set_cleanup(&lfdset);
05659 }
05660
05661 void
05662 snmp_read2(netsnmp_large_fd_set * fdset)
05663 {
05664 struct session_list *slp;
05665 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
05666 for (slp = Sessions; slp; slp = slp->next) {
05667 snmp_sess_read2((void *) slp, fdset);
05668 }
05669 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
05670 }
05671
05672
05673
05674
05675
05676
05677
05678 int
05679 _sess_read(void *sessp, netsnmp_large_fd_set * fdset)
05680 {
05681 struct session_list *slp = (struct session_list *) sessp;
05682 netsnmp_session *sp = slp ? slp->session : NULL;
05683 struct snmp_internal_session *isp = slp ? slp->internal : NULL;
05684 netsnmp_transport *transport = slp ? slp->transport : NULL;
05685 size_t pdulen = 0, rxbuf_len = 65536;
05686 u_char *rxbuf = NULL;
05687 int length = 0, olength = 0, rc = 0;
05688 void *opaque = NULL;
05689
05690 if (!sp || !isp || !transport) {
05691 DEBUGMSGTL(("sess_read", "read fail: closing...\n"));
05692 return 0;
05693 }
05694
05695
05696 if (transport->sock < 0) {
05697 snmp_log (LOG_INFO, "transport->sock got negative fd value %d\n", transport->sock);
05698 return 0;
05699 }
05700
05701 if (!fdset || !(NETSNMP_LARGE_FD_ISSET(transport->sock, fdset))) {
05702 DEBUGMSGTL(("sess_read", "not reading %d (fdset %p set %d)\n",
05703 transport->sock, fdset,
05704 fdset ? NETSNMP_LARGE_FD_ISSET(transport->sock, fdset)
05705 : -9));
05706 return 0;
05707 }
05708
05709 sp->s_snmp_errno = 0;
05710 sp->s_errno = 0;
05711
05712 if (transport->flags & NETSNMP_TRANSPORT_FLAG_LISTEN) {
05713 int data_sock = transport->f_accept(transport);
05714
05715 if (data_sock >= 0) {
05716
05717
05718
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742 netsnmp_transport *new_transport=netsnmp_transport_copy(transport);
05743 if (new_transport != NULL) {
05744 struct session_list *nslp = NULL;
05745
05746 new_transport->sock = data_sock;
05747 new_transport->flags &= ~NETSNMP_TRANSPORT_FLAG_LISTEN;
05748
05749 nslp = (struct session_list *)snmp_sess_add_ex(sp,
05750 new_transport, isp->hook_pre, isp->hook_parse,
05751 isp->hook_post, isp->hook_build,
05752 isp->hook_realloc_build, isp->check_packet,
05753 isp->hook_create_pdu);
05754
05755 if (nslp != NULL) {
05756 nslp->next = Sessions;
05757 Sessions = nslp;
05758
05759
05760
05761 DEBUGMSGTL(("sess_read",
05762 "perform callback with op=CONNECT\n"));
05763 (void)nslp->session->callback(NETSNMP_CALLBACK_OP_CONNECT,
05764 nslp->session, 0, NULL,
05765 sp->callback_magic);
05766 }
05767 return 0;
05768 } else {
05769 sp->s_snmp_errno = SNMPERR_MALLOC;
05770 sp->s_errno = errno;
05771 snmp_set_detail(strerror(errno));
05772 return -1;
05773 }
05774 } else {
05775 sp->s_snmp_errno = SNMPERR_BAD_RECVFROM;
05776 sp->s_errno = errno;
05777 snmp_set_detail(strerror(errno));
05778 return -1;
05779 }
05780 }
05781
05782
05783
05784
05785
05786 if (transport->flags & NETSNMP_TRANSPORT_FLAG_STREAM) {
05787 if (isp->packet == NULL) {
05788
05789
05790
05791 if ((isp->packet = (u_char *) malloc(rxbuf_len)) == NULL) {
05792 DEBUGMSGTL(("sess_read", "can't malloc %lu bytes for rxbuf\n",
05793 (unsigned long)rxbuf_len));
05794 return 0;
05795 } else {
05796 rxbuf = isp->packet;
05797 isp->packet_size = rxbuf_len;
05798 isp->packet_len = 0;
05799 }
05800 } else {
05801
05802
05803
05804
05805 u_char *newbuf;
05806
05807 if (isp->packet_size < isp->packet_len + rxbuf_len) {
05808 newbuf =
05809 (u_char *) realloc(isp->packet,
05810 isp->packet_len + rxbuf_len);
05811 if (newbuf == NULL) {
05812 DEBUGMSGTL(("sess_read",
05813 "can't malloc %lu more for rxbuf (%lu tot)\n",
05814 (unsigned long)rxbuf_len, (unsigned long)(isp->packet_len + rxbuf_len)));
05815 return 0;
05816 } else {
05817 isp->packet = newbuf;
05818 isp->packet_size = isp->packet_len + rxbuf_len;
05819 rxbuf = isp->packet + isp->packet_len;
05820 }
05821 } else {
05822 rxbuf = isp->packet + isp->packet_len;
05823 rxbuf_len = isp->packet_size - isp->packet_len;
05824 }
05825 }
05826 } else {
05827 if ((rxbuf = (u_char *) malloc(rxbuf_len)) == NULL) {
05828 DEBUGMSGTL(("sess_read", "can't malloc %lu bytes for rxbuf\n",
05829 (unsigned long)rxbuf_len));
05830 return 0;
05831 }
05832 }
05833
05834 length = transport->f_recv(transport, rxbuf, rxbuf_len, &opaque, &olength);
05835
05836 if (length == -1 && !(transport->flags & NETSNMP_TRANSPORT_FLAG_STREAM)) {
05837 sp->s_snmp_errno = SNMPERR_BAD_RECVFROM;
05838 sp->s_errno = errno;
05839 snmp_set_detail(strerror(errno));
05840 SNMP_FREE(rxbuf);
05841 if (opaque != NULL) {
05842 SNMP_FREE(opaque);
05843 }
05844 return -1;
05845 }
05846
05847 if (0 == length && transport->flags & NETSNMP_TRANSPORT_FLAG_EMPTY_PKT) {
05848
05849
05850
05851
05852
05853 transport->flags &= (~NETSNMP_TRANSPORT_FLAG_EMPTY_PKT);
05854
05855 return 0;
05856 }
05857
05858
05859
05860
05861
05862 if (length <= 0 && transport->flags & NETSNMP_TRANSPORT_FLAG_STREAM) {
05863
05864
05865
05866 if (sp->callback != NULL) {
05867 DEBUGMSGTL(("sess_read", "perform callback with op=DISCONNECT\n"));
05868 (void) sp->callback(NETSNMP_CALLBACK_OP_DISCONNECT, sp, 0,
05869 NULL, sp->callback_magic);
05870 }
05871
05872
05873
05874 DEBUGMSGTL(("sess_read", "fd %d closed\n", transport->sock));
05875 transport->f_close(transport);
05876 SNMP_FREE(isp->packet);
05877 if (opaque != NULL) {
05878 SNMP_FREE(opaque);
05879 }
05880 return -1;
05881 }
05882
05883 if (transport->flags & NETSNMP_TRANSPORT_FLAG_STREAM) {
05884 u_char *pptr = isp->packet;
05885 void *ocopy = NULL;
05886
05887 isp->packet_len += length;
05888
05889 while (isp->packet_len > 0) {
05890
05891
05892
05893
05894
05895 if (isp->check_packet) {
05896 pdulen = isp->check_packet(pptr, isp->packet_len);
05897 } else {
05898 pdulen = asn_check_packet(pptr, isp->packet_len);
05899 }
05900
05901 DEBUGMSGTL(("sess_read", " loop packet_len %lu, PDU length %lu\n",
05902 (unsigned long)isp->packet_len, (unsigned long)pdulen));
05903
05904 if ((pdulen > MAX_PACKET_LENGTH) || (pdulen < 0)) {
05905
05906
05907
05908 snmp_log(LOG_ERR,
05909 "Received broken packet. Closing session.\n");
05910 if (sp->callback != NULL) {
05911 DEBUGMSGTL(("sess_read",
05912 "perform callback with op=DISCONNECT\n"));
05913 (void)sp->callback(NETSNMP_CALLBACK_OP_DISCONNECT,
05914 sp, 0, NULL, sp->callback_magic);
05915 }
05916 DEBUGMSGTL(("sess_read", "fd %d closed\n", transport->sock));
05917 transport->f_close(transport);
05918 if (opaque != NULL) {
05919 SNMP_FREE(opaque);
05920 }
05922 return -1;
05923 }
05924
05925 if (pdulen > isp->packet_len || pdulen == 0) {
05926
05927
05928
05929
05930
05931
05932 DEBUGMSGTL(("sess_read",
05933 "pkt not complete (need %lu got %lu so far)\n",
05934 (unsigned long)pdulen, (unsigned long)isp->packet_len));
05935
05936 if (pptr != isp->packet)
05937 break;
05938
05939 if (opaque != NULL) {
05940 SNMP_FREE(opaque);
05941 }
05942 return 0;
05943 }
05944
05945
05946
05947
05948
05949 if (pdulen < isp->packet_len) {
05950 if (olength > 0 && opaque != NULL) {
05951 ocopy = malloc(olength);
05952 if (ocopy != NULL) {
05953 memcpy(ocopy, opaque, olength);
05954 }
05955 }
05956 } else if (pdulen == isp->packet_len) {
05957
05958
05959 ocopy = opaque;
05960 opaque = NULL;
05961 }
05962
05963 if ((rc = _sess_process_packet(sessp, sp, isp, transport,
05964 ocopy, ocopy?olength:0, pptr,
05965 pdulen))) {
05966
05967
05968
05969
05970 if (sp->s_snmp_errno != 0) {
05971 SET_SNMP_ERROR(sp->s_snmp_errno);
05972 }
05973 }
05974
05975
05976
05977
05978 ocopy = NULL;
05979
05980
05981
05982 pptr += pdulen;
05983 isp->packet_len -= pdulen;
05984 }
05985
05986
05987
05988
05989
05990 if (opaque != NULL) {
05991 SNMP_FREE(opaque);
05992 }
05993
05994 if (isp->packet_len >= MAXIMUM_PACKET_SIZE) {
05995
05996
05997
05998 snmp_log(LOG_ERR,
05999 "too large packet_len = %lu, dropping connection %d\n",
06000 (unsigned long)(isp->packet_len), transport->sock);
06001 transport->f_close(transport);
06003 return -1;
06004 } else if (isp->packet_len == 0) {
06005
06006
06007
06008
06009
06010
06011 SNMP_FREE(isp->packet);
06012 isp->packet = NULL;
06013 isp->packet_size = 0;
06014 isp->packet_len = 0;
06015 return rc;
06016 }
06017
06018
06019
06020
06021
06022
06023
06024
06025 memmove(isp->packet, pptr, isp->packet_len);
06026 DEBUGMSGTL(("sess_read", "end: memmove(%p, %p, %lu); realloc(%p, %lu)\n",
06027 isp->packet, pptr, (unsigned long)isp->packet_len,
06028 isp->packet, (unsigned long)isp->packet_len));
06029
06030 if ((rxbuf = (u_char *)realloc(isp->packet, isp->packet_len)) == NULL) {
06031
06032
06033
06034 DEBUGMSGTL(("sess_read", "realloc() failed\n"));
06035 } else {
06036 DEBUGMSGTL(("sess_read", "realloc() okay, old buffer %p, new %p\n",
06037 isp->packet, rxbuf));
06038 isp->packet = rxbuf;
06039 isp->packet_size = isp->packet_len;
06040 }
06041 return rc;
06042 } else {
06043 rc = _sess_process_packet(sessp, sp, isp, transport, opaque,
06044 olength, rxbuf, length);
06045 SNMP_FREE(rxbuf);
06046 return rc;
06047 }
06048 }
06049
06050
06051
06052
06053
06054
06055 int
06056 snmp_sess_read(void *sessp, fd_set * fdset)
06057 {
06058 int rc;
06059 netsnmp_large_fd_set lfdset;
06060
06061 netsnmp_large_fd_set_init(&lfdset, FD_SETSIZE);
06062 netsnmp_copy_fd_set_to_large_fd_set(&lfdset, fdset);
06063 rc = snmp_sess_read2(sessp, &lfdset);
06064 netsnmp_large_fd_set_cleanup(&lfdset);
06065 return rc;
06066 }
06067
06068 int
06069 snmp_sess_read2(void *sessp, netsnmp_large_fd_set * fdset)
06070 {
06071 struct session_list *psl;
06072 netsnmp_session *pss;
06073 int rc;
06074
06075 rc = _sess_read(sessp, fdset);
06076 psl = (struct session_list *) sessp;
06077 pss = psl->session;
06078 if (rc && pss->s_snmp_errno) {
06079 SET_SNMP_ERROR(pss->s_snmp_errno);
06080 }
06081 return rc;
06082 }
06083
06084
06085
06086
06087
06088
06089
06090
06091
06092
06093
06094
06095
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105
06106
06107
06108 int
06109 snmp_select_info(int *numfds,
06110 fd_set * fdset, struct timeval *timeout, int *block)
06111
06112
06113
06114
06115
06116
06117 {
06118 return snmp_sess_select_info((void *) 0, numfds, fdset, timeout,
06119 block);
06120 }
06121
06122 int
06123 snmp_select_info2(int *numfds,
06124 netsnmp_large_fd_set * fdset,
06125 struct timeval *timeout, int *block)
06126
06127
06128
06129
06130
06131
06132 {
06133 return snmp_sess_select_info2((void *) 0, numfds, fdset, timeout,
06134 block);
06135 }
06136
06137
06138
06139
06140 int
06141 snmp_sess_select_info(void *sessp,
06142 int *numfds,
06143 fd_set * fdset, struct timeval *timeout, int *block)
06144 {
06145 int rc;
06146 netsnmp_large_fd_set lfdset;
06147
06148 netsnmp_large_fd_set_init(&lfdset, FD_SETSIZE);
06149 netsnmp_copy_fd_set_to_large_fd_set(&lfdset, fdset);
06150 rc = snmp_sess_select_info2(sessp, numfds, &lfdset, timeout, block);
06151 if (netsnmp_copy_large_fd_set_to_fd_set(fdset, &lfdset) < 0) {
06152 snmp_log(LOG_ERR,
06153 "Use snmp_sess_select_info2() for processing"
06154 " large file descriptors");
06155 }
06156 netsnmp_large_fd_set_cleanup(&lfdset);
06157 return rc;
06158 }
06159
06160 int
06161 snmp_sess_select_info2(void *sessp,
06162 int *numfds,
06163 netsnmp_large_fd_set * fdset,
06164 struct timeval *timeout, int *block)
06165 {
06166 struct session_list *slptest = (struct session_list *) sessp;
06167 struct session_list *slp, *next = NULL;
06168 netsnmp_request_list *rp;
06169 struct timeval now, earliest, delta;
06170 int active = 0, requests = 0;
06171 int next_alarm = 0;
06172
06173 timerclear(&earliest);
06174
06175
06176
06177
06178
06179
06180
06181 if (sessp) {
06182 slp = slptest;
06183 } else {
06184 slp = Sessions;
06185 }
06186
06187 DEBUGMSGTL(("sess_select", "for %s session%s: ",
06188 sessp ? "single" : "all", sessp ? "" : "s"));
06189
06190 for (; slp; slp = next) {
06191 next = slp->next;
06192
06193 if (slp->transport == NULL) {
06194
06195
06196
06197 DEBUGMSG(("sess_select", "skip "));
06198 continue;
06199 }
06200
06201 if (slp->transport->sock == -1) {
06202
06203
06204
06205 DEBUGMSG(("sess_select", "delete\n"));
06206 if (sessp == NULL) {
06207 snmp_close(slp->session);
06208 } else {
06209 snmp_sess_close(slp);
06210 }
06211 DEBUGMSGTL(("sess_select", "for %s session%s: ",
06212 sessp ? "single" : "all", sessp ? "" : "s"));
06213 continue;
06214 }
06215
06216 DEBUGMSG(("sess_select", "%d ", slp->transport->sock));
06217 if ((slp->transport->sock + 1) > *numfds) {
06218 *numfds = (slp->transport->sock + 1);
06219 }
06220
06221 NETSNMP_LARGE_FD_SET(slp->transport->sock, fdset);
06222 if (slp->internal != NULL && slp->internal->requests) {
06223
06224
06225
06226 requests++;
06227 for (rp = slp->internal->requests; rp; rp = rp->next_request) {
06228 if ((!timerisset(&earliest)
06229 || (timercmp(&rp->expire, &earliest, <)))) {
06230 earliest = rp->expire;
06231 DEBUGMSG(("verbose:sess_select","(to in %d.%06d sec) ",
06232 (int)earliest.tv_sec, (int)earliest.tv_usec));
06233 }
06234 }
06235 }
06236
06237 active++;
06238 if (sessp) {
06239
06240
06241
06242 break;
06243 }
06244 }
06245 DEBUGMSG(("sess_select", "\n"));
06246
06247 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ALARM_DONT_USE_SIG)) {
06248 next_alarm = get_next_alarm_delay_time(&delta);
06249 DEBUGMSGT(("sess_select","next alarm %d.%06d sec\n",
06250 (int)delta.tv_sec, (int)delta.tv_usec));
06251 }
06252 if (next_alarm == 0 && requests == 0) {
06253
06254
06255
06256 DEBUGMSGT(("sess_select","blocking:no session requests or alarms.\n"));
06257 *block = 1;
06258 return active;
06259 }
06260
06261
06262
06263
06264
06265
06266 gettimeofday(&now, (struct timezone *) 0);
06267
06268
06269
06270
06271 if (next_alarm) {
06272 delta.tv_sec += now.tv_sec;
06273 delta.tv_usec += now.tv_usec;
06274 while (delta.tv_usec >= 1000000) {
06275 delta.tv_usec -= 1000000;
06276 delta.tv_sec += 1;
06277 }
06278 if (!timerisset(&earliest) ||
06279 ((earliest.tv_sec > delta.tv_sec) ||
06280 ((earliest.tv_sec == delta.tv_sec) &&
06281 (earliest.tv_usec > delta.tv_usec)))) {
06282 earliest.tv_sec = delta.tv_sec;
06283 earliest.tv_usec = delta.tv_usec;
06284 }
06285 }
06286
06287 if (earliest.tv_sec < now.tv_sec) {
06288 DEBUGMSGT(("verbose:sess_select","timer overdue\n"));
06289 earliest.tv_sec = 0;
06290 earliest.tv_usec = 0;
06291 } else if (earliest.tv_sec == now.tv_sec) {
06292 earliest.tv_sec = 0;
06293 earliest.tv_usec = (earliest.tv_usec - now.tv_usec);
06294 if (earliest.tv_usec < 0) {
06295 earliest.tv_usec = 100;
06296 }
06297 DEBUGMSGT(("verbose:sess_select","timer due *real* soon. %d usec\n",
06298 (int)earliest.tv_usec));
06299 } else {
06300 earliest.tv_sec = (earliest.tv_sec - now.tv_sec);
06301 earliest.tv_usec = (earliest.tv_usec - now.tv_usec);
06302 if (earliest.tv_usec < 0) {
06303 earliest.tv_sec--;
06304 earliest.tv_usec = (1000000L + earliest.tv_usec);
06305 }
06306 DEBUGMSGT(("verbose:sess_select","timer due in %d.%06d sec\n",
06307 (int)earliest.tv_sec, (int)earliest.tv_usec));
06308 }
06309
06310
06311
06312
06313 if ((*block || (timercmp(&earliest, timeout, <)))) {
06314 DEBUGMSGT(("verbose:sess_select",
06315 "setting timer to %d.%06d sec, clear block (was %d)\n",
06316 (int)earliest.tv_sec, (int)earliest.tv_usec, *block));
06317 *timeout = earliest;
06318 *block = 0;
06319 }
06320 return active;
06321 }
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332 void
06333 snmp_timeout(void)
06334 {
06335 struct session_list *slp;
06336 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
06337 for (slp = Sessions; slp; slp = slp->next) {
06338 snmp_sess_timeout((void *) slp);
06339 }
06340 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
06341 }
06342
06343 static int
06344 snmp_resend_request(struct session_list *slp, netsnmp_request_list *rp,
06345 int incr_retries)
06346 {
06347 struct snmp_internal_session *isp;
06348 netsnmp_session *sp;
06349 netsnmp_transport *transport;
06350 u_char *pktbuf = NULL, *packet = NULL;
06351 size_t pktbuf_len = 0, offset = 0, length = 0;
06352 struct timeval tv, now;
06353 int result = 0;
06354
06355 sp = slp->session;
06356 isp = slp->internal;
06357 transport = slp->transport;
06358 if (!sp || !isp || !transport) {
06359 DEBUGMSGTL(("sess_read", "resend fail: closing...\n"));
06360 return 0;
06361 }
06362
06363 if ((pktbuf = (u_char *)malloc(2048)) == NULL) {
06364 DEBUGMSGTL(("sess_resend",
06365 "couldn't malloc initial packet buffer\n"));
06366 return 0;
06367 } else {
06368 pktbuf_len = 2048;
06369 }
06370
06371 if (incr_retries) {
06372 rp->retries++;
06373 }
06374
06375
06376
06377
06378 rp->pdu->msgid = rp->message_id = snmp_get_next_msgid();
06379
06380 if (isp->hook_realloc_build) {
06381 result = isp->hook_realloc_build(sp, rp->pdu,
06382 &pktbuf, &pktbuf_len, &offset);
06383
06384 packet = pktbuf;
06385 length = offset;
06386 } else if (isp->hook_build) {
06387 packet = pktbuf;
06388 length = pktbuf_len;
06389 result = isp->hook_build(sp, rp->pdu, pktbuf, &length);
06390 } else {
06391 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
06392 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
06393 result =
06394 snmp_build(&pktbuf, &pktbuf_len, &offset, sp, rp->pdu);
06395 packet = pktbuf + pktbuf_len - offset;
06396 length = offset;
06397 } else {
06398 #endif
06399 packet = pktbuf;
06400 length = pktbuf_len;
06401 result = snmp_build(&pktbuf, &length, &offset, sp, rp->pdu);
06402 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
06403 }
06404 #endif
06405 }
06406
06407 if (result < 0) {
06408
06409
06410
06411 DEBUGMSGTL(("sess_resend", "encoding failure\n"));
06412 if (pktbuf != NULL) {
06413 SNMP_FREE(pktbuf);
06414 }
06415 return -1;
06416 }
06417
06418 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET)) {
06419 if (transport->f_fmtaddr != NULL) {
06420 char *str = NULL;
06421 str = transport->f_fmtaddr(transport, rp->pdu->transport_data,
06422 rp->pdu->transport_data_length);
06423 if (str != NULL) {
06424 snmp_log(LOG_DEBUG, "\nResending %lu bytes to %s\n",
06425 (unsigned long)length, str);
06426 SNMP_FREE(str);
06427 } else {
06428 snmp_log(LOG_DEBUG, "\nResending %lu bytes to <UNKNOWN>\n",
06429 (unsigned long)length);
06430 }
06431 }
06432 xdump(packet, length, "");
06433 }
06434
06435 DEBUGMSGTL(("sess_process_packet", "resending message id#%ld reqid#%ld rp_reqid#%ld rp_msgid#%ld\n",
06436 rp->pdu->msgid, rp->pdu->reqid, rp->request_id, rp->message_id));
06437 result = transport->f_send(transport, packet, length,
06438 &(rp->pdu->transport_data),
06439 &(rp->pdu->transport_data_length));
06440
06441
06442
06443
06444
06445
06446 if (pktbuf != NULL) {
06447 SNMP_FREE(pktbuf);
06448 pktbuf = packet = NULL;
06449 }
06450
06451 if (result < 0) {
06452 sp->s_snmp_errno = SNMPERR_BAD_SENDTO;
06453 sp->s_errno = errno;
06454 snmp_set_detail(strerror(errno));
06455 return -1;
06456 } else {
06457 gettimeofday(&now, (struct timezone *) 0);
06458 tv = now;
06459 rp->time = tv;
06460 tv.tv_usec += rp->timeout;
06461 tv.tv_sec += tv.tv_usec / 1000000L;
06462 tv.tv_usec %= 1000000L;
06463 rp->expire = tv;
06464 }
06465 return 0;
06466 }
06467
06468
06469
06470 void
06471 snmp_sess_timeout(void *sessp)
06472 {
06473 struct session_list *slp = (struct session_list *) sessp;
06474 netsnmp_session *sp;
06475 struct snmp_internal_session *isp;
06476 netsnmp_request_list *rp, *orp = NULL, *freeme = NULL;
06477 struct timeval now;
06478 snmp_callback callback;
06479 void *magic;
06480 struct snmp_secmod_def *sptr;
06481
06482 sp = slp->session;
06483 isp = slp->internal;
06484 if (!sp || !isp) {
06485 DEBUGMSGTL(("sess_read", "timeout fail: closing...\n"));
06486 return;
06487 }
06488
06489 gettimeofday(&now, (struct timezone *) 0);
06490
06491
06492
06493
06494 for (rp = isp->requests; rp; rp = rp->next_request) {
06495 if (freeme != NULL) {
06496
06497
06498
06499 free((char *) freeme);
06500 freeme = NULL;
06501 }
06502
06503 if ((timercmp(&rp->expire, &now, <))) {
06504 if ((sptr = find_sec_mod(rp->pdu->securityModel)) != NULL &&
06505 sptr->pdu_timeout != NULL) {
06506
06507
06508
06509 (*sptr->pdu_timeout) (rp->pdu);
06510 }
06511
06512
06513
06514
06515 if (rp->retries >= sp->retries) {
06516 if (rp->callback) {
06517 callback = rp->callback;
06518 magic = rp->cb_data;
06519 } else {
06520 callback = sp->callback;
06521 magic = sp->callback_magic;
06522 }
06523
06524
06525
06526
06527 if (callback) {
06528 callback(NETSNMP_CALLBACK_OP_TIMED_OUT, sp,
06529 rp->pdu->reqid, rp->pdu, magic);
06530 }
06531 if (isp->requests == rp) {
06532 isp->requests = rp->next_request;
06533 if (isp->requestsEnd == rp) {
06534 isp->requestsEnd = NULL;
06535 }
06536 } else {
06537 orp->next_request = rp->next_request;
06538 if (isp->requestsEnd == rp) {
06539 isp->requestsEnd = orp;
06540 }
06541 }
06542 snmp_free_pdu(rp->pdu);
06543 freeme = rp;
06544 continue;
06545 } else {
06546 if (snmp_resend_request(slp, rp, TRUE)) {
06547 break;
06548 }
06549 }
06550 }
06551 orp = rp;
06552 }
06553
06554 if (freeme != NULL) {
06555 free((char *) freeme);
06556 freeme = NULL;
06557 }
06558 }
06559
06560
06561
06562
06563
06564
06565
06566
06567
06568
06569 int
06570 snmp_oid_ncompare(const oid * in_name1,
06571 size_t len1,
06572 const oid * in_name2, size_t len2, size_t max_len)
06573 {
06574 register int len;
06575 register const oid *name1 = in_name1;
06576 register const oid *name2 = in_name2;
06577 size_t min_len;
06578
06579
06580
06581
06582 if (len1 < len2)
06583 min_len = len1;
06584 else
06585 min_len = len2;
06586
06587 if (min_len > max_len)
06588 min_len = max_len;
06589
06590 len = min_len;
06591
06592
06593
06594
06595 while (len-- > 0) {
06596
06597
06598
06599
06600
06601 if (*(name1) != *(name2)) {
06602 if (*(name1) < *(name2))
06603 return -1;
06604 return 1;
06605 }
06606 name1++;
06607 name2++;
06608 }
06609
06610 if (min_len != max_len) {
06611
06612
06613
06614 if (len1 < len2)
06615 return -1;
06616 if (len2 < len1)
06617 return 1;
06618 }
06619
06620 return 0;
06621 }
06622
06630 int
06631 snmp_oid_compare(const oid * in_name1,
06632 size_t len1, const oid * in_name2, size_t len2)
06633 {
06634 register int len;
06635 register const oid *name1 = in_name1;
06636 register const oid *name2 = in_name2;
06637
06638
06639
06640
06641 if (len1 < len2)
06642 len = len1;
06643 else
06644 len = len2;
06645
06646
06647
06648 while (len-- > 0) {
06649
06650
06651
06652
06653
06654 if (*(name1) != *(name2)) {
06655 if (*(name1) < *(name2))
06656 return -1;
06657 return 1;
06658 }
06659 name1++;
06660 name2++;
06661 }
06662
06663
06664
06665 if (len1 < len2)
06666 return -1;
06667 if (len2 < len1)
06668 return 1;
06669 return 0;
06670 }
06671
06679 int
06680 netsnmp_oid_compare_ll(const oid * in_name1,
06681 size_t len1, const oid * in_name2, size_t len2,
06682 size_t *offpt)
06683 {
06684 register int len;
06685 register const oid *name1 = in_name1;
06686 register const oid *name2 = in_name2;
06687 int initlen;
06688
06689
06690
06691
06692 if (len1 < len2)
06693 initlen = len = len1;
06694 else
06695 initlen = len = len2;
06696
06697
06698
06699 while (len-- > 0) {
06700
06701
06702
06703
06704
06705 if (*(name1) != *(name2)) {
06706 *offpt = initlen - len;
06707 if (*(name1) < *(name2))
06708 return -1;
06709 return 1;
06710 }
06711 name1++;
06712 name2++;
06713 }
06714
06715
06716
06717 *offpt = initlen - len;
06718 if (len1 < len2)
06719 return -1;
06720 if (len2 < len1)
06721 return 1;
06722 return 0;
06723 }
06724
06732 int
06733 snmp_oidtree_compare(const oid * in_name1,
06734 size_t len1, const oid * in_name2, size_t len2)
06735 {
06736 int len = ((len1 < len2) ? len1 : len2);
06737
06738 return (snmp_oid_compare(in_name1, len, in_name2, len));
06739 }
06740
06741 int
06742 snmp_oidsubtree_compare(const oid * in_name1,
06743 size_t len1, const oid * in_name2, size_t len2)
06744 {
06745 int len = ((len1 < len2) ? len1 : len2);
06746
06747 return (snmp_oid_compare(in_name1, len1, in_name2, len));
06748 }
06749
06760 int
06761 netsnmp_oid_equals(const oid * in_name1,
06762 size_t len1, const oid * in_name2, size_t len2)
06763 {
06764 register const oid *name1 = in_name1;
06765 register const oid *name2 = in_name2;
06766 register int len = len1;
06767
06768
06769
06770
06771 if (len1 != len2)
06772 return 1;
06773
06774
06775
06776 while (len-- > 0) {
06777
06778
06779
06780
06781
06782 if (*(name1++) != *(name2++))
06783 return 1;
06784 }
06785 return 0;
06786 }
06787
06796 int
06797 netsnmp_oid_is_subtree(const oid * in_name1,
06798 size_t len1, const oid * in_name2, size_t len2)
06799 {
06800 if (len1 > len2)
06801 return 1;
06802
06803 if (memcmp(in_name1, in_name2, len1 * sizeof(oid)))
06804 return 1;
06805
06806 return 0;
06807 }
06808
06816 int
06817 netsnmp_oid_find_prefix(const oid * in_name1, size_t len1,
06818 const oid * in_name2, size_t len2)
06819 {
06820 int i;
06821 size_t min_size;
06822
06823 if (!in_name1 || !in_name2 || !len1 || !len2)
06824 return -1;
06825
06826 if (in_name1[0] != in_name2[0])
06827 return 0;
06828 min_size = SNMP_MIN(len1, len2);
06829 for(i = 0; i < (int)min_size; i++) {
06830 if (in_name1[i] != in_name2[i])
06831 return i + 1;
06832 }
06833 return min_size;
06834 }
06835
06836 static int _check_range(struct tree *tp, long ltmp, int *resptr,
06837 const char *errmsg)
06838 {
06839 char *cp = NULL;
06840 char *temp = NULL;
06841 int temp_len = 0;
06842 int check = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
06843 NETSNMP_DS_LIB_DONT_CHECK_RANGE);
06844
06845 if (check && tp && tp->ranges) {
06846 struct range_list *rp = tp->ranges;
06847 while (rp) {
06848 if (rp->low <= ltmp && ltmp <= rp->high) break;
06849
06850 temp_len += ((rp->low != rp->high) ? 14 : 8 );
06851 rp = rp->next;
06852 }
06853 if (!rp) {
06854 *resptr = SNMPERR_RANGE;
06855 temp = (char *)malloc( temp_len+strlen(errmsg)+7);
06856 if ( temp ) {
06857
06858 sprintf( temp, "%s :: {", errmsg );
06859 cp = temp+(strlen(temp));
06860 for ( rp = tp->ranges; rp; rp=rp->next ) {
06861 if ( rp->low != rp->high )
06862 sprintf( cp, "(%d..%d), ", rp->low, rp->high );
06863 else
06864 sprintf( cp, "(%d), ", rp->low );
06865 cp += strlen(cp);
06866 }
06867 *(cp-2) = '}';
06868 *(cp-1) = 0;
06869 snmp_set_detail(temp);
06870 free(temp);
06871 }
06872 return 0;
06873 }
06874 }
06875 free(temp);
06876 return 1;
06877 }
06878
06879
06880
06881
06882
06883
06884 netsnmp_variable_list *
06885 snmp_pdu_add_variable(netsnmp_pdu *pdu,
06886 const oid * name,
06887 size_t name_length,
06888 u_char type, const void * value, size_t len)
06889 {
06890 return snmp_varlist_add_variable(&pdu->variables, name, name_length,
06891 type, value, len);
06892 }
06893
06894
06895
06896
06897
06898 netsnmp_variable_list *
06899 snmp_varlist_add_variable(netsnmp_variable_list ** varlist,
06900 const oid * name,
06901 size_t name_length,
06902 u_char type, const void * value, size_t len)
06903 {
06904 netsnmp_variable_list *vars, *vtmp;
06905 int rc;
06906
06907 if (varlist == NULL)
06908 return NULL;
06909
06910 vars = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
06911 if (vars == NULL)
06912 return NULL;
06913
06914 vars->type = type;
06915
06916 rc = snmp_set_var_value( vars, value, len );
06917 if (( 0 != rc ) ||
06918 (name != NULL && snmp_set_var_objid(vars, name, name_length))) {
06919 snmp_free_var(vars);
06920 return NULL;
06921 }
06922
06923
06924
06925
06926 if (*varlist == NULL) {
06927 *varlist = vars;
06928 } else {
06929 for (vtmp = *varlist; vtmp->next_variable;
06930 vtmp = vtmp->next_variable);
06931
06932 vtmp->next_variable = vars;
06933 }
06934
06935 return vars;
06936 }
06937
06938
06939
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952 int
06953 snmp_add_var(netsnmp_pdu *pdu,
06954 const oid * name, size_t name_length, char type, const char *value)
06955 {
06956 char *st;
06957 const char *cp;
06958 char *ecp, *vp;
06959 int result = SNMPERR_SUCCESS;
06960 #ifndef NETSNMP_DISABLE_MIB_LOADING
06961 int check = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
06962 NETSNMP_DS_LIB_DONT_CHECK_RANGE);
06963 int do_hint = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
06964 NETSNMP_DS_LIB_NO_DISPLAY_HINT);
06965 u_char *hintptr;
06966 struct tree *tp;
06967 #endif
06968 u_char *buf = NULL;
06969 const u_char *buf_ptr = NULL;
06970 size_t buf_len = 0, value_len = 0, tint;
06971 in_addr_t atmp;
06972 long ltmp;
06973 int itmp;
06974 struct enum_list *ep;
06975 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
06976 double dtmp;
06977 float ftmp;
06978 #endif
06979 struct counter64 c64tmp;
06980
06981 #ifndef NETSNMP_DISABLE_MIB_LOADING
06982 tp = get_tree(name, name_length, get_tree_head());
06983 if (!tp || !tp->type || tp->type > TYPE_SIMPLE_LAST) {
06984 check = 0;
06985 }
06986 if (!(tp && tp->hint))
06987 do_hint = 0;
06988
06989 if (tp && type == '=') {
06990
06991
06992
06993 switch (tp->type) {
06994 case TYPE_INTEGER:
06995 case TYPE_INTEGER32:
06996 type = 'i';
06997 break;
06998 case TYPE_GAUGE:
06999 case TYPE_UNSIGNED32:
07000 type = 'u';
07001 break;
07002 case TYPE_UINTEGER:
07003 type = '3';
07004 break;
07005 case TYPE_COUNTER:
07006 type = 'c';
07007 break;
07008 case TYPE_COUNTER64:
07009 type = 'C';
07010 break;
07011 case TYPE_TIMETICKS:
07012 type = 't';
07013 break;
07014 case TYPE_OCTETSTR:
07015 type = 's';
07016 break;
07017 case TYPE_BITSTRING:
07018 type = 'b';
07019 break;
07020 case TYPE_IPADDR:
07021 type = 'a';
07022 break;
07023 case TYPE_OBJID:
07024 type = 'o';
07025 break;
07026 }
07027 }
07028 #endif
07029
07030 switch (type) {
07031 case 'i':
07032 #ifndef NETSNMP_DISABLE_MIB_LOADING
07033 if (check && tp->type != TYPE_INTEGER
07034 && tp->type != TYPE_INTEGER32) {
07035 value = "INTEGER";
07036 result = SNMPERR_VALUE;
07037 goto type_error;
07038 }
07039 #endif
07040 if (!*value)
07041 goto fail;
07042 ltmp = strtol(value, &ecp, 10);
07043 if (*ecp) {
07044 #ifndef NETSNMP_DISABLE_MIB_LOADING
07045 ep = tp ? tp->enums : NULL;
07046 while (ep) {
07047 if (strcmp(value, ep->label) == 0) {
07048 ltmp = ep->value;
07049 break;
07050 }
07051 ep = ep->next;
07052 }
07053 if (!ep) {
07054 #endif
07055 result = SNMPERR_RANGE;
07056 snmp_set_detail(value);
07057 break;
07058 #ifndef NETSNMP_DISABLE_MIB_LOADING
07059 }
07060 #endif
07061 }
07062
07063 #ifndef NETSNMP_DISABLE_MIB_LOADING
07064 if (!_check_range(tp, ltmp, &result, value))
07065 break;
07066 #endif
07067 snmp_pdu_add_variable(pdu, name, name_length, ASN_INTEGER,
07068 <mp, sizeof(ltmp));
07069 break;
07070
07071 case 'u':
07072 #ifndef NETSNMP_DISABLE_MIB_LOADING
07073 if (check && tp->type != TYPE_GAUGE && tp->type != TYPE_UNSIGNED32) {
07074 value = "Unsigned32";
07075 result = SNMPERR_VALUE;
07076 goto type_error;
07077 }
07078 #endif
07079 ltmp = strtoul(value, &ecp, 10);
07080 if (*value && !*ecp)
07081 snmp_pdu_add_variable(pdu, name, name_length, ASN_UNSIGNED,
07082 <mp, sizeof(ltmp));
07083 else
07084 goto fail;
07085 break;
07086
07087 case '3':
07088 #ifndef NETSNMP_DISABLE_MIB_LOADING
07089 if (check && tp->type != TYPE_UINTEGER) {
07090 value = "UInteger32";
07091 result = SNMPERR_VALUE;
07092 goto type_error;
07093 }
07094 #endif
07095 ltmp = strtoul(value, &ecp, 10);
07096 if (*value && !*ecp)
07097 snmp_pdu_add_variable(pdu, name, name_length, ASN_UINTEGER,
07098 <mp, sizeof(ltmp));
07099 else
07100 goto fail;
07101 break;
07102
07103 case 'c':
07104 #ifndef NETSNMP_DISABLE_MIB_LOADING
07105 if (check && tp->type != TYPE_COUNTER) {
07106 value = "Counter32";
07107 result = SNMPERR_VALUE;
07108 goto type_error;
07109 }
07110 #endif
07111 ltmp = strtoul(value, &ecp, 10);
07112 if (*value && !*ecp)
07113 snmp_pdu_add_variable(pdu, name, name_length, ASN_COUNTER,
07114 <mp, sizeof(ltmp));
07115 else
07116 goto fail;
07117 break;
07118
07119 case 'C':
07120 #ifndef NETSNMP_DISABLE_MIB_LOADING
07121 if (check && tp->type != TYPE_COUNTER64) {
07122 value = "Counter64";
07123 result = SNMPERR_VALUE;
07124 goto type_error;
07125 }
07126 #endif
07127 if (read64(&c64tmp, value))
07128 snmp_pdu_add_variable(pdu, name, name_length, ASN_COUNTER64,
07129 &c64tmp, sizeof(c64tmp));
07130 else
07131 goto fail;
07132 break;
07133
07134 case 't':
07135 #ifndef NETSNMP_DISABLE_MIB_LOADING
07136 if (check && tp->type != TYPE_TIMETICKS) {
07137 value = "Timeticks";
07138 result = SNMPERR_VALUE;
07139 goto type_error;
07140 }
07141 #endif
07142 ltmp = strtoul(value, &ecp, 10);
07143 if (*value && !*ecp)
07144 snmp_pdu_add_variable(pdu, name, name_length, ASN_TIMETICKS,
07145 <mp, sizeof(long));
07146 else
07147 goto fail;
07148 break;
07149
07150 case 'a':
07151 #ifndef NETSNMP_DISABLE_MIB_LOADING
07152 if (check && tp->type != TYPE_IPADDR) {
07153 value = "IpAddress";
07154 result = SNMPERR_VALUE;
07155 goto type_error;
07156 }
07157 #endif
07158 atmp = inet_addr(value);
07159 if (atmp != (in_addr_t) -1 || !strcmp(value, "255.255.255.255"))
07160 snmp_pdu_add_variable(pdu, name, name_length, ASN_IPADDRESS,
07161 &atmp, sizeof(atmp));
07162 else
07163 goto fail;
07164 break;
07165
07166 case 'o':
07167 #ifndef NETSNMP_DISABLE_MIB_LOADING
07168 if (check && tp->type != TYPE_OBJID) {
07169 value = "OBJECT IDENTIFIER";
07170 result = SNMPERR_VALUE;
07171 goto type_error;
07172 }
07173 #endif
07174 if ((buf = (u_char *)malloc(sizeof(oid) * MAX_OID_LEN)) == NULL) {
07175 result = SNMPERR_MALLOC;
07176 } else {
07177 tint = MAX_OID_LEN;
07178 if (snmp_parse_oid(value, (oid *) buf, &tint)) {
07179 snmp_pdu_add_variable(pdu, name, name_length, ASN_OBJECT_ID,
07180 buf, sizeof(oid) * tint);
07181 } else {
07182 result = snmp_errno;
07183 }
07184 }
07185 break;
07186
07187 case 's':
07188 case 'x':
07189 case 'd':
07190 #ifndef NETSNMP_DISABLE_MIB_LOADING
07191 if (check && tp->type != TYPE_OCTETSTR && tp->type != TYPE_BITSTRING) {
07192 value = "OCTET STRING";
07193 result = SNMPERR_VALUE;
07194 goto type_error;
07195 }
07196 if ('s' == type && do_hint && !parse_octet_hint(tp->hint, value, &hintptr, &itmp)) {
07197 if (_check_range(tp, itmp, &result, "Value does not match DISPLAY-HINT")) {
07198 snmp_pdu_add_variable(pdu, name, name_length, ASN_OCTET_STR,
07199 hintptr, itmp);
07200 }
07201 SNMP_FREE(hintptr);
07202 hintptr = buf;
07203 break;
07204 }
07205 #endif
07206 if (type == 'd') {
07207 if (!snmp_decimal_to_binary
07208 (&buf, &buf_len, &value_len, 1, value)) {
07209 result = SNMPERR_VALUE;
07210 snmp_set_detail(value);
07211 break;
07212 }
07213 buf_ptr = buf;
07214 } else if (type == 'x') {
07215 if (!snmp_hex_to_binary(&buf, &buf_len, &value_len, 1, value)) {
07216 result = SNMPERR_VALUE;
07217 snmp_set_detail(value);
07218 break;
07219 }
07220
07221 itmp = value_len;
07222 buf_ptr = buf;
07223 } else if (type == 's') {
07224 buf_ptr = (const u_char *)value;
07225 value_len = strlen(value);
07226 }
07227 #ifndef NETSNMP_DISABLE_MIB_LOADING
07228 if (!_check_range(tp, value_len, &result, "Bad string length"))
07229 break;
07230 #endif
07231 snmp_pdu_add_variable(pdu, name, name_length, ASN_OCTET_STR,
07232 buf_ptr, value_len);
07233 break;
07234
07235 case 'n':
07236 snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, NULL, 0);
07237 break;
07238
07239 case 'b':
07240 #ifndef NETSNMP_DISABLE_MIB_LOADING
07241 if (check && (tp->type != TYPE_BITSTRING || !tp->enums)) {
07242 value = "BITS";
07243 result = SNMPERR_VALUE;
07244 goto type_error;
07245 }
07246 #endif
07247 tint = 0;
07248 if ((buf = (u_char *) malloc(256)) == NULL) {
07249 result = SNMPERR_MALLOC;
07250 break;
07251 } else {
07252 buf_len = 256;
07253 memset(buf, 0, buf_len);
07254 }
07255
07256 #ifndef NETSNMP_DISABLE_MIB_LOADING
07257 for (ep = tp ? tp->enums : NULL; ep; ep = ep->next) {
07258 if (ep->value / 8 >= (int) tint) {
07259 tint = ep->value / 8 + 1;
07260 }
07261 }
07262 #endif
07263
07264 vp = strdup(value);
07265 for (cp = strtok_r(vp, " ,\t", &st); cp; cp = strtok_r(NULL, " ,\t", &st)) {
07266 int ix, bit;
07267
07268 ltmp = strtoul(cp, &ecp, 0);
07269 if (*ecp != 0) {
07270 #ifndef NETSNMP_DISABLE_MIB_LOADING
07271 for (ep = tp ? tp->enums : NULL; ep != NULL; ep = ep->next) {
07272 if (strncmp(ep->label, cp, strlen(ep->label)) == 0) {
07273 break;
07274 }
07275 }
07276 if (ep != NULL) {
07277 ltmp = ep->value;
07278 } else {
07279 #endif
07280 result = SNMPERR_RANGE;
07281 snmp_set_detail(cp);
07282 SNMP_FREE(buf);
07283 SNMP_FREE(vp);
07284 goto out;
07285 #ifndef NETSNMP_DISABLE_MIB_LOADING
07286 }
07287 #endif
07288 }
07289
07290 ix = ltmp / 8;
07291 if (ix >= (int) tint) {
07292 tint = ix + 1;
07293 }
07294 if (ix >= (int)buf_len && !snmp_realloc(&buf, &buf_len)) {
07295 result = SNMPERR_MALLOC;
07296 break;
07297 }
07298 bit = 0x80 >> ltmp % 8;
07299 buf[ix] |= bit;
07300
07301 }
07302 SNMP_FREE(vp);
07303 snmp_pdu_add_variable(pdu, name, name_length, ASN_OCTET_STR,
07304 buf, tint);
07305 break;
07306
07307 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
07308 case 'U':
07309 if (read64(&c64tmp, value))
07310 snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_U64,
07311 &c64tmp, sizeof(c64tmp));
07312 else
07313 goto fail;
07314 break;
07315
07316 case 'I':
07317 if (read64(&c64tmp, value))
07318 snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_I64,
07319 &c64tmp, sizeof(c64tmp));
07320 else
07321 goto fail;
07322 break;
07323
07324 case 'F':
07325 if (sscanf(value, "%f", &ftmp) == 1)
07326 snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_FLOAT,
07327 &ftmp, sizeof(ftmp));
07328 else
07329 goto fail;
07330 break;
07331
07332 case 'D':
07333 if (sscanf(value, "%lf", &dtmp) == 1)
07334 snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_DOUBLE,
07335 &dtmp, sizeof(dtmp));
07336 else
07337 goto fail;
07338 break;
07339 #endif
07340
07341 default:
07342 result = SNMPERR_VAR_TYPE;
07343 buf = (u_char *)calloc(1, 4);
07344 if (buf != NULL) {
07345 sprintf((char *)buf, "\"%c\"", type);
07346 snmp_set_detail((char *)buf);
07347 }
07348 break;
07349 }
07350
07351 SNMP_FREE(buf);
07352 SET_SNMP_ERROR(result);
07353 return result;
07354
07355 #ifndef NETSNMP_DISABLE_MIB_LOADING
07356 type_error:
07357 {
07358 char error_msg[256];
07359 char undef_msg[32];
07360 const char *var_type;
07361 switch (tp->type) {
07362 case TYPE_OBJID:
07363 var_type = "OBJECT IDENTIFIER";
07364 break;
07365 case TYPE_OCTETSTR:
07366 var_type = "OCTET STRING";
07367 break;
07368 case TYPE_INTEGER:
07369 var_type = "INTEGER";
07370 break;
07371 case TYPE_NETADDR:
07372 var_type = "NetworkAddress";
07373 break;
07374 case TYPE_IPADDR:
07375 var_type = "IpAddress";
07376 break;
07377 case TYPE_COUNTER:
07378 var_type = "Counter32";
07379 break;
07380 case TYPE_GAUGE:
07381 var_type = "Gauge32";
07382 break;
07383 case TYPE_TIMETICKS:
07384 var_type = "Timeticks";
07385 break;
07386 case TYPE_OPAQUE:
07387 var_type = "Opaque";
07388 break;
07389 case TYPE_NULL:
07390 var_type = "Null";
07391 break;
07392 case TYPE_COUNTER64:
07393 var_type = "Counter64";
07394 break;
07395 case TYPE_BITSTRING:
07396 var_type = "BITS";
07397 break;
07398 case TYPE_NSAPADDRESS:
07399 var_type = "NsapAddress";
07400 break;
07401 case TYPE_UINTEGER:
07402 var_type = "UInteger";
07403 break;
07404 case TYPE_UNSIGNED32:
07405 var_type = "Unsigned32";
07406 break;
07407 case TYPE_INTEGER32:
07408 var_type = "Integer32";
07409 break;
07410 default:
07411 sprintf(undef_msg, "TYPE_%d", tp->type);
07412 var_type = undef_msg;
07413 }
07414 snprintf(error_msg, sizeof(error_msg),
07415 "Type of attribute is %s, not %s", var_type, value);
07416 error_msg[ sizeof(error_msg)-1 ] = 0;
07417 result = SNMPERR_VAR_TYPE;
07418 snmp_set_detail(error_msg);
07419 goto out;
07420 }
07421 #endif
07422 fail:
07423 result = SNMPERR_VALUE;
07424 snmp_set_detail(value);
07425 out:
07426 SET_SNMP_ERROR(result);
07427 return result;
07428 }
07429
07430
07431
07432
07433
07434
07435 void *
07436 snmp_sess_pointer(netsnmp_session * session)
07437 {
07438 struct session_list *slp;
07439
07440 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
07441 for (slp = Sessions; slp; slp = slp->next) {
07442 if (slp->session == session) {
07443 break;
07444 }
07445 }
07446 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
07447
07448 if (slp == NULL) {
07449 snmp_errno = SNMPERR_BAD_SESSION;
07450 return (NULL);
07451 }
07452 return ((void *) slp);
07453 }
07454
07455
07456
07457
07458
07459 netsnmp_session *
07460 snmp_sess_session(void *sessp)
07461 {
07462 struct session_list *slp = (struct session_list *) sessp;
07463 if (slp == NULL)
07464 return (NULL);
07465 return (slp->session);
07466 }
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477 netsnmp_transport *
07478 snmp_sess_transport(void *sessp)
07479 {
07480 struct session_list *slp = (struct session_list *) sessp;
07481 if (slp == NULL) {
07482 return NULL;
07483 } else {
07484 return slp->transport;
07485 }
07486 }
07487
07488
07489
07490
07491
07492
07493
07494
07495 void
07496 snmp_sess_transport_set(void *sp, netsnmp_transport *t)
07497 {
07498 struct session_list *slp = (struct session_list *) sp;
07499 if (slp != NULL) {
07500 slp->transport = t;
07501 }
07502 }
07503
07504
07505
07506
07507
07508
07509 oid *
07510 snmp_duplicate_objid(const oid * objToCopy, size_t objToCopyLen)
07511 {
07512 oid *returnOid;
07513 if (objToCopy != NULL && objToCopyLen != 0) {
07514 returnOid = (oid *) malloc(objToCopyLen * sizeof(oid));
07515 if (returnOid) {
07516 memcpy(returnOid, objToCopy, objToCopyLen * sizeof(oid));
07517 }
07518 } else
07519 returnOid = NULL;
07520 return returnOid;
07521 }
07522
07523
07524
07525
07526 static u_int statistics[MAX_STATS];
07527
07528 u_int
07529 snmp_increment_statistic(int which)
07530 {
07531 if (which >= 0 && which < MAX_STATS) {
07532 statistics[which]++;
07533 return statistics[which];
07534 }
07535 return 0;
07536 }
07537
07538 u_int
07539 snmp_increment_statistic_by(int which, int count)
07540 {
07541 if (which >= 0 && which < MAX_STATS) {
07542 statistics[which] += count;
07543 return statistics[which];
07544 }
07545 return 0;
07546 }
07547
07548 u_int
07549 snmp_get_statistic(int which)
07550 {
07551 if (which >= 0 && which < MAX_STATS)
07552 return statistics[which];
07553 return 0;
07554 }
07555
07556 void
07557 snmp_init_statistics(void)
07558 {
07559 memset(statistics, 0, sizeof(statistics));
07560 }