00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <stdio.h> 00004 #include <sys/types.h> 00005 #include <ctype.h> 00006 #include <errno.h> 00007 00008 #if HAVE_STRING_H 00009 #include <string.h> 00010 #else 00011 #include <strings.h> 00012 #endif 00013 #if HAVE_STDLIB_H 00014 #include <stdlib.h> 00015 #endif 00016 #if HAVE_UNISTD_H 00017 #include <unistd.h> 00018 #endif 00019 #if HAVE_SYS_SOCKET_H 00020 #include <sys/socket.h> 00021 #endif 00022 #if HAVE_SYS_UN_H 00023 #include <sys/un.h> 00024 #endif 00025 00026 #if HAVE_DMALLOC_H 00027 #include <dmalloc.h> 00028 #endif 00029 00030 #include <net-snmp/types.h> 00031 #include <net-snmp/output_api.h> 00032 #include <net-snmp/config_api.h> 00033 00034 #include <net-snmp/library/snmp_transport.h> 00035 #include <net-snmp/library/snmpUDPDomain.h> 00036 #include <net-snmp/library/snmpUnixDomain.h> 00037 #include <net-snmp/library/system.h> /* mkdirhier */ 00038 00039 00040 #ifndef NETSNMP_STREAM_QUEUE_LEN 00041 #define NETSNMP_STREAM_QUEUE_LEN 5 00042 #endif 00043 00044 #ifndef SUN_LEN 00045 /* 00046 * Evaluate to actual length of the `sockaddr_un' structure. 00047 */ 00048 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ 00049 + strlen ((ptr)->sun_path)) 00050 #endif 00051 00052 oid netsnmp_UnixDomain[] = { TRANSPORT_DOMAIN_LOCAL }; 00053 static netsnmp_tdomain unixDomain; 00054 00055 00056 /* 00057 * This is the structure we use to hold transport-specific data. 00058 */ 00059 00060 typedef struct _sockaddr_un_pair { 00061 int local; 00062 struct sockaddr_un server; 00063 struct sockaddr_un client; 00064 } sockaddr_un_pair; 00065 00066 00067 /* 00068 * Return a string representing the address in data, or else the "far end" 00069 * address if data is NULL. 00070 */ 00071 00072 static char * 00073 netsnmp_unix_fmtaddr(netsnmp_transport *t, void *data, int len) 00074 { 00075 struct sockaddr_un *to = NULL; 00076 00077 if (data != NULL) { 00078 to = (struct sockaddr_un *) data; 00079 } else if (t != NULL && t->data != NULL) { 00080 to = &(((sockaddr_un_pair *) t->data)->server); 00081 len = SUN_LEN(to); 00082 } 00083 if (to == NULL) { 00084 /* 00085 * "Local IPC" is the Posix.1g term for Unix domain protocols, 00086 * according to W. R. Stevens, ``Unix Network Programming Volume I 00087 * Second Edition'', p. 374. 00088 */ 00089 return strdup("Local IPC: unknown"); 00090 } else if (to->sun_path[0] == 0) { 00091 /* 00092 * This is an abstract name. We could render it as hex or something 00093 * but let's not worry about that for now. 00094 */ 00095 return strdup("Local IPC: abstract"); 00096 } else { 00097 char *tmp = (char *) malloc(16 + len); 00098 if (tmp != NULL) { 00099 sprintf(tmp, "Local IPC: %s", to->sun_path); 00100 } 00101 return tmp; 00102 } 00103 } 00104 00105 00106 00107 /* 00108 * You can write something into opaque that will subsequently get passed back 00109 * to your send function if you like. For instance, you might want to 00110 * remember where a PDU came from, so that you can send a reply there... 00111 */ 00112 00113 static int 00114 netsnmp_unix_recv(netsnmp_transport *t, void *buf, int size, 00115 void **opaque, int *olength) 00116 { 00117 int rc = -1; 00118 socklen_t tolen = sizeof(struct sockaddr_un); 00119 struct sockaddr *to; 00120 00121 00122 if (t != NULL && t->sock >= 0) { 00123 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_un)); 00124 if (to == NULL) { 00125 *opaque = NULL; 00126 *olength = 0; 00127 return -1; 00128 } else { 00129 memset(to, 0, tolen); 00130 } 00131 if(getsockname(t->sock, to, &tolen) != 0){ 00132 free(to); 00133 *opaque = NULL; 00134 *olength = 0; 00135 return -1; 00136 }; 00137 while (rc < 0) { 00138 rc = recvfrom(t->sock, buf, size, 0, NULL, NULL); 00139 if (rc < 0 && errno != EINTR) { 00140 DEBUGMSGTL(("netsnmp_unix", "recv fd %d err %d (\"%s\")\n", 00141 t->sock, errno, strerror(errno))); 00142 return rc; 00143 } 00144 *opaque = (void*)to; 00145 *olength = sizeof(struct sockaddr_un); 00146 } 00147 DEBUGMSGTL(("netsnmp_unix", "recv fd %d got %d bytes\n", t->sock, rc)); 00148 } 00149 return rc; 00150 } 00151 00152 00153 00154 static int 00155 netsnmp_unix_send(netsnmp_transport *t, void *buf, int size, 00156 void **opaque, int *olength) 00157 { 00158 int rc = -1; 00159 00160 if (t != NULL && t->sock >= 0) { 00161 DEBUGMSGTL(("netsnmp_unix", "send %d bytes to %p on fd %d\n", 00162 size, buf, t->sock)); 00163 while (rc < 0) { 00164 rc = sendto(t->sock, buf, size, 0, NULL, 0); 00165 if (rc < 0 && errno != EINTR) { 00166 break; 00167 } 00168 } 00169 } 00170 return rc; 00171 } 00172 00173 00174 00175 static int 00176 netsnmp_unix_close(netsnmp_transport *t) 00177 { 00178 int rc = 0; 00179 sockaddr_un_pair *sup = (sockaddr_un_pair *) t->data; 00180 00181 if (t->sock >= 0) { 00182 #ifndef HAVE_CLOSESOCKET 00183 rc = close(t->sock); 00184 #else 00185 rc = closesocket(t->sock); 00186 #endif 00187 t->sock = -1; 00188 if (sup != NULL) { 00189 if (sup->local) { 00190 if (sup->server.sun_path[0] != 0) { 00191 DEBUGMSGTL(("netsnmp_unix", "close: server unlink(\"%s\")\n", 00192 sup->server.sun_path)); 00193 unlink(sup->server.sun_path); 00194 } 00195 } else { 00196 if (sup->client.sun_path[0] != 0) { 00197 DEBUGMSGTL(("netsnmp_unix", "close: client unlink(\"%s\")\n", 00198 sup->client.sun_path)); 00199 unlink(sup->client.sun_path); 00200 } 00201 } 00202 } 00203 return rc; 00204 } else { 00205 return -1; 00206 } 00207 } 00208 00209 00210 00211 static int 00212 netsnmp_unix_accept(netsnmp_transport *t) 00213 { 00214 struct sockaddr *farend = NULL; 00215 int newsock = -1; 00216 socklen_t farendlen = sizeof(struct sockaddr_un); 00217 00218 farend = (struct sockaddr *) malloc(farendlen); 00219 00220 if (farend == NULL) { 00221 /* 00222 * Indicate that the acceptance of this socket failed. 00223 */ 00224 DEBUGMSGTL(("netsnmp_unix", "accept: malloc failed\n")); 00225 return -1; 00226 } 00227 memset(farend, 0, farendlen); 00228 00229 if (t != NULL && t->sock >= 0) { 00230 newsock = accept(t->sock, farend, &farendlen); 00231 00232 if (newsock < 0) { 00233 DEBUGMSGTL(("netsnmp_unix","accept failed rc %d errno %d \"%s\"\n", 00234 newsock, errno, strerror(errno))); 00235 free(farend); 00236 return newsock; 00237 } 00238 00239 if (t->data != NULL) { 00240 free(t->data); 00241 } 00242 00243 DEBUGMSGTL(("netsnmp_unix", "accept succeeded (farend %p len %d)\n", 00244 farend, farendlen)); 00245 t->data = farend; 00246 t->data_length = sizeof(struct sockaddr_un); 00247 netsnmp_sock_buffer_set(newsock, SO_SNDBUF, 1, 0); 00248 netsnmp_sock_buffer_set(newsock, SO_RCVBUF, 1, 0); 00249 return newsock; 00250 } else { 00251 free(farend); 00252 return -1; 00253 } 00254 } 00255 00256 static int create_path = 0; 00257 static mode_t create_mode; 00258 00262 void netsnmp_unix_create_path_with_mode(int mode) 00263 { 00264 create_path = 1; 00265 create_mode = mode; 00266 } 00267 00271 void netsnmp_unix_dont_create_path(void) 00272 { 00273 create_path = 0; 00274 } 00275 00276 /* 00277 * Open a Unix-domain transport for SNMP. Local is TRUE if addr is the local 00278 * address to bind to (i.e. this is a server-type session); otherwise addr is 00279 * the remote address to send things to (and we make up a temporary name for 00280 * the local end of the connection). 00281 */ 00282 00283 netsnmp_transport * 00284 netsnmp_unix_transport(struct sockaddr_un *addr, int local) 00285 { 00286 netsnmp_transport *t = NULL; 00287 sockaddr_un_pair *sup = NULL; 00288 int rc = 0; 00289 char *string = NULL; 00290 00291 if (addr == NULL || addr->sun_family != AF_UNIX) { 00292 return NULL; 00293 } 00294 00295 t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport)); 00296 if (t == NULL) { 00297 return NULL; 00298 } 00299 00300 string = netsnmp_unix_fmtaddr(NULL, (void *)addr, 00301 sizeof(struct sockaddr_un)); 00302 DEBUGMSGTL(("netsnmp_unix", "open %s %s\n", local ? "local" : "remote", 00303 string)); 00304 free(string); 00305 00306 memset(t, 0, sizeof(netsnmp_transport)); 00307 00308 t->domain = netsnmp_UnixDomain; 00309 t->domain_length = 00310 sizeof(netsnmp_UnixDomain) / sizeof(netsnmp_UnixDomain[0]); 00311 00312 t->data = malloc(sizeof(sockaddr_un_pair)); 00313 if (t->data == NULL) { 00314 netsnmp_transport_free(t); 00315 return NULL; 00316 } 00317 memset(t->data, 0, sizeof(sockaddr_un_pair)); 00318 t->data_length = sizeof(sockaddr_un_pair); 00319 sup = (sockaddr_un_pair *) t->data; 00320 00321 t->sock = socket(PF_UNIX, SOCK_STREAM, 0); 00322 if (t->sock < 0) { 00323 netsnmp_transport_free(t); 00324 return NULL; 00325 } 00326 00327 t->flags = NETSNMP_TRANSPORT_FLAG_STREAM; 00328 00329 if (local) { 00330 t->local = (u_char *)malloc(strlen(addr->sun_path)); 00331 if (t->local == NULL) { 00332 netsnmp_transport_free(t); 00333 return NULL; 00334 } 00335 memcpy(t->local, addr->sun_path, strlen(addr->sun_path)); 00336 t->local_length = strlen(addr->sun_path); 00337 00338 /* 00339 * This session is inteneded as a server, so we must bind to the given 00340 * path (unlinking it first, to avoid errors). 00341 */ 00342 00343 t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN; 00344 00345 unlink(addr->sun_path); 00346 rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); 00347 00348 if (rc != 0 && errno == ENOENT && create_path) { 00349 rc = mkdirhier(addr->sun_path, create_mode, 1); 00350 if (rc != 0) { 00351 netsnmp_unix_close(t); 00352 netsnmp_transport_free(t); 00353 return NULL; 00354 } 00355 rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); 00356 } 00357 if (rc != 0) { 00358 DEBUGMSGTL(("netsnmp_unix_transport", 00359 "couldn't bind \"%s\", errno %d (%s)\n", 00360 addr->sun_path, errno, strerror(errno))); 00361 netsnmp_unix_close(t); 00362 netsnmp_transport_free(t); 00363 return NULL; 00364 } 00365 00366 /* 00367 * Save the address in the transport-specific data pointer for later 00368 * use by netsnmp_unix_close. 00369 */ 00370 00371 sup->server.sun_family = AF_UNIX; 00372 strcpy(sup->server.sun_path, addr->sun_path); 00373 sup->local = 1; 00374 00375 /* 00376 * Now sit here and listen for connections to arrive. 00377 */ 00378 00379 rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); 00380 if (rc != 0) { 00381 DEBUGMSGTL(("netsnmp_unix_transport", 00382 "couldn't listen to \"%s\", errno %d (%s)\n", 00383 addr->sun_path, errno, strerror(errno))); 00384 netsnmp_unix_close(t); 00385 netsnmp_transport_free(t); 00386 return NULL; 00387 } 00388 00389 } else { 00390 t->remote = (u_char *)malloc(strlen(addr->sun_path)); 00391 if (t->remote == NULL) { 00392 netsnmp_transport_free(t); 00393 return NULL; 00394 } 00395 memcpy(t->remote, addr->sun_path, strlen(addr->sun_path)); 00396 t->remote_length = strlen(addr->sun_path); 00397 00398 rc = connect(t->sock, (struct sockaddr *) addr, 00399 sizeof(struct sockaddr_un)); 00400 if (rc != 0) { 00401 DEBUGMSGTL(("netsnmp_unix_transport", 00402 "couldn't connect to \"%s\", errno %d (%s)\n", 00403 addr->sun_path, errno, strerror(errno))); 00404 netsnmp_unix_close(t); 00405 netsnmp_transport_free(t); 00406 return NULL; 00407 } 00408 00409 /* 00410 * Save the remote address in the transport-specific data pointer for 00411 * later use by netsnmp_unix_send. 00412 */ 00413 00414 sup->server.sun_family = AF_UNIX; 00415 strcpy(sup->server.sun_path, addr->sun_path); 00416 sup->local = 0; 00417 netsnmp_sock_buffer_set(t->sock, SO_SNDBUF, local, 0); 00418 netsnmp_sock_buffer_set(t->sock, SO_RCVBUF, local, 0); 00419 } 00420 00421 /* 00422 * Message size is not limited by this transport (hence msgMaxSize 00423 * is equal to the maximum legal size of an SNMP message). 00424 */ 00425 00426 t->msgMaxSize = 0x7fffffff; 00427 t->f_recv = netsnmp_unix_recv; 00428 t->f_send = netsnmp_unix_send; 00429 t->f_close = netsnmp_unix_close; 00430 t->f_accept = netsnmp_unix_accept; 00431 t->f_fmtaddr = netsnmp_unix_fmtaddr; 00432 00433 return t; 00434 } 00435 00436 netsnmp_transport * 00437 netsnmp_unix_create_tstring(const char *string, int local, 00438 const char *default_target) 00439 { 00440 struct sockaddr_un addr; 00441 00442 if (string && *string != '\0') { 00443 } else if (default_target && *default_target != '\0') { 00444 string = default_target; 00445 } 00446 00447 if ((string != NULL && *string != '\0') && 00448 (strlen(string) < sizeof(addr.sun_path))) { 00449 addr.sun_family = AF_UNIX; 00450 memset(addr.sun_path, 0, sizeof(addr.sun_path)); 00451 strncpy(addr.sun_path, string, sizeof(addr.sun_path) - 1); 00452 return netsnmp_unix_transport(&addr, local); 00453 } else { 00454 if (string != NULL && *string != '\0') { 00455 snmp_log(LOG_ERR, "Path too long for Unix domain transport\n"); 00456 } 00457 return NULL; 00458 } 00459 } 00460 00461 00462 00463 netsnmp_transport * 00464 netsnmp_unix_create_ostring(const u_char * o, size_t o_len, int local) 00465 { 00466 struct sockaddr_un addr; 00467 00468 if (o_len > 0 && o_len < (sizeof(addr.sun_path) - 1)) { 00469 addr.sun_family = AF_UNIX; 00470 memset(addr.sun_path, 0, sizeof(addr.sun_path)); 00471 strncpy(addr.sun_path, (const char *)o, o_len); 00472 return netsnmp_unix_transport(&addr, local); 00473 } else { 00474 if (o_len > 0) { 00475 snmp_log(LOG_ERR, "Path too long for Unix domain transport\n"); 00476 } 00477 } 00478 return NULL; 00479 } 00480 00481 00482 00483 void 00484 netsnmp_unix_ctor(void) 00485 { 00486 unixDomain.name = netsnmp_UnixDomain; 00487 unixDomain.name_length = sizeof(netsnmp_UnixDomain) / sizeof(oid); 00488 unixDomain.prefix = (const char**)calloc(2, sizeof(char *)); 00489 unixDomain.prefix[0] = "unix"; 00490 00491 unixDomain.f_create_from_tstring_new = netsnmp_unix_create_tstring; 00492 unixDomain.f_create_from_ostring = netsnmp_unix_create_ostring; 00493 00494 netsnmp_tdomain_register(&unixDomain); 00495 } 00496 00497 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) 00498 /* support for SNMPv1 and SNMPv2c on unix domain*/ 00499 00500 #define EXAMPLE_COMMUNITY "COMMUNITY" 00501 typedef struct _com2SecUnixEntry { 00502 char community[COMMUNITY_MAX_LEN]; 00503 char sockpath[sizeof(struct sockaddr_un)]; 00504 unsigned long pathlen; 00505 char secName[VACMSTRINGLEN]; 00506 char contextName[VACMSTRINGLEN]; 00507 struct _com2SecUnixEntry *next; 00508 } com2SecUnixEntry; 00509 00510 com2SecUnixEntry *com2SecUnixList = NULL, *com2SecUnixListLast = NULL; 00511 00512 00513 int 00514 netsnmp_unix_getSecName(void *opaque, int olength, 00515 const char *community, 00516 size_t community_len, 00517 char **secName, char **contextName) 00518 { 00519 com2SecUnixEntry *c; 00520 struct sockaddr_un *to = (struct sockaddr_un *) opaque; 00521 char *ztcommunity = NULL; 00522 00523 if (secName != NULL) { 00524 *secName = NULL; /* Haven't found anything yet */ 00525 } 00526 00527 /* 00528 * Special case if there are NO entries (as opposed to no MATCHING 00529 * entries). 00530 */ 00531 00532 if (com2SecUnixList == NULL) { 00533 DEBUGMSGTL(("netsnmp_unix_getSecName", "no com2sec entries\n")); 00534 return 0; 00535 } 00536 00537 /* 00538 * If there is no unix socket path, then there can be no valid security 00539 * name. 00540 */ 00541 00542 if (opaque == NULL || olength != sizeof(struct sockaddr_un) || 00543 to->sun_family != AF_UNIX) { 00544 DEBUGMSGTL(("netsnmp_unix_getSecName", 00545 "no unix destine address in PDU?\n")); 00546 return 1; 00547 } 00548 00549 DEBUGIF("netsnmp_unix_getSecName") { 00550 ztcommunity = (char *)malloc(community_len + 1); 00551 if (ztcommunity != NULL) { 00552 memcpy(ztcommunity, community, community_len); 00553 ztcommunity[community_len] = '\0'; 00554 } 00555 00556 DEBUGMSGTL(("netsnmp_unix_getSecName", "resolve <\"%s\">\n", 00557 ztcommunity ? ztcommunity : "<malloc error>")); 00558 } 00559 00560 for (c = com2SecUnixList; c != NULL; c = c->next) { 00561 DEBUGMSGTL(("netsnmp_unix_getSecName","compare <\"%s\",to socket %s>", 00562 c->community, c->sockpath )); 00563 if ((community_len == strlen(c->community)) && 00564 (memcmp(community, c->community, community_len) == 0) && 00565 /* compare sockpath, if pathlen == 0, always match */ 00566 (strlen(to->sun_path) == c->pathlen || c->pathlen == 0) && 00567 (memcmp(to->sun_path, c->sockpath, c->pathlen) == 0) 00568 ) { 00569 DEBUGMSG(("netsnmp_unix_getSecName", "... SUCCESS\n")); 00570 if (secName != NULL) { 00571 *secName = c->secName; 00572 *contextName = c->contextName; 00573 } 00574 break; 00575 } 00576 DEBUGMSG(("netsnmp_unix_getSecName", "... nope\n")); 00577 } 00578 if (ztcommunity != NULL) { 00579 free(ztcommunity); 00580 } 00581 return 1; 00582 } 00583 00584 void 00585 netsnmp_unix_parse_security(const char *token, char *param) 00586 { 00587 char secName[VACMSTRINGLEN + 1], community[COMMUNITY_MAX_LEN + 1]; 00588 char contextName[VACMSTRINGLEN + 1]; 00589 char sockpath[sizeof(struct sockaddr_un) + 1]; 00590 com2SecUnixEntry *e = NULL; 00591 00592 00593 param = copy_nword(param, secName, VACMSTRINGLEN); 00594 if (strcmp(secName, "-Cn") == 0) { 00595 if (!secName) { 00596 config_perror("missing CONTEXT_NAME parameter"); 00597 return; 00598 } 00599 param = copy_nword( param, contextName, sizeof(contextName)); 00600 param = copy_nword( param, secName, sizeof(secName)); 00601 } else { 00602 contextName[0] = '\0'; 00603 } 00604 if (secName[0] == '\0') { 00605 config_perror("missing NAME parameter"); 00606 return; 00607 } else if (strlen(secName) > (VACMSTRINGLEN - 1)) { 00608 config_perror("security name too long"); 00609 return; 00610 } 00611 00612 param = copy_nword(param, sockpath, sizeof(struct sockaddr_un) - 1); 00613 if (sockpath[0] == '\0') { 00614 config_perror("missing SOCKPATH parameter"); 00615 return; 00616 } else if (strlen(sockpath) > (sizeof(struct sockaddr_un) - 1)) { 00617 config_perror("sockpath too long"); 00618 return; 00619 } 00620 /* if sockpath == "default", set pathlen=0*/ 00621 if(strcmp(sockpath, "default") == 0){ 00622 sockpath[0] = 0; 00623 } 00624 00625 param = copy_nword(param, community, COMMUNITY_MAX_LEN); 00626 if (community[0] == '\0') { 00627 config_perror("missing COMMUNITY parameter\n"); 00628 return; 00629 } else if (strncmp 00630 (community, EXAMPLE_COMMUNITY, strlen(EXAMPLE_COMMUNITY)) 00631 == 0) { 00632 config_perror("example config COMMUNITY not properly configured"); 00633 return; 00634 } else if (strlen(community) > (COMMUNITY_MAX_LEN - 1)) { 00635 config_perror("community name too long"); 00636 return; 00637 } 00638 00639 e = (com2SecUnixEntry *) malloc(sizeof(com2SecUnixEntry)); 00640 if (e == NULL) { 00641 config_perror("memory error"); 00642 return; 00643 } 00644 00645 DEBUGMSGTL(("netsnmp_unix_parse_security", 00646 "<\"%s\"> => \"%s\"\n", community, secName)); 00647 00648 strcpy(e->secName, secName); 00649 strcpy(e->contextName, contextName); 00650 strcpy(e->community, community); 00651 strcpy(e->sockpath, sockpath); 00652 e->pathlen = strlen(sockpath); 00653 e->next = NULL; 00654 00655 if (com2SecUnixListLast != NULL) { 00656 com2SecUnixListLast->next = e; 00657 com2SecUnixListLast = e; 00658 } else { 00659 com2SecUnixListLast = com2SecUnixList = e; 00660 } 00661 } 00662 00663 void 00664 netsnmp_unix_com2SecList_free(void) 00665 { 00666 com2SecUnixEntry *e = com2SecUnixList; 00667 while (e != NULL) { 00668 com2SecUnixEntry *tmp = e; 00669 e = e->next; 00670 free(tmp); 00671 } 00672 com2SecUnixList = com2SecUnixListLast = NULL; 00673 } 00674 #endif /* support for community based SNMP */ 00675 00676 void 00677 netsnmp_unix_agent_config_tokens_register(void) 00678 { 00679 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) 00680 register_app_config_handler("com2secunix", netsnmp_unix_parse_security, 00681 netsnmp_unix_com2SecList_free, 00682 "[-Cn CONTEXT] secName sockpath community"); 00683 #endif /* support for community based SNMP */ 00684 }
1.5.7.1
Last modified: Tuesday, 23-Dec-2025 17:22:04 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.