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