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