net-snmp 5.7
snmp_transport.c
00001 #include <net-snmp/net-snmp-config.h>
00002 #include <net-snmp/net-snmp-features.h>
00003 
00004 #include <net-snmp/types.h>
00005 #include <net-snmp/library/snmp_transport.h>
00006 
00007 #include <stdio.h>
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013 #include <sys/types.h>
00014 
00015 #if HAVE_STDLIB_H
00016 #include <stdlib.h>
00017 #endif
00018 
00019 #include <ctype.h>
00020 
00021 #if HAVE_UNISTD_H
00022 #include <unistd.h>
00023 #endif
00024 #if HAVE_DMALLOC_H
00025 #include <dmalloc.h>
00026 #endif
00027 
00028 #include <net-snmp/output_api.h>
00029 #include <net-snmp/utilities.h>
00030 
00031 #include <net-snmp/library/default_store.h>
00032 
00033 #include <net-snmp/library/snmpUDPDomain.h>
00034 #ifdef NETSNMP_TRANSPORT_TLSBASE_DOMAIN
00035 #include <net-snmp/library/snmpTLSBaseDomain.h>
00036 #endif
00037 #ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
00038 #include <net-snmp/library/snmpTLSTCPDomain.h>
00039 #endif
00040 #ifdef NETSNMP_TRANSPORT_STD_DOMAIN
00041 #include <net-snmp/library/snmpSTDDomain.h>
00042 #endif
00043 #ifdef NETSNMP_TRANSPORT_TCP_DOMAIN
00044 #include <net-snmp/library/snmpTCPDomain.h>
00045 #endif
00046 #ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
00047 #include <net-snmp/library/snmpDTLSUDPDomain.h>
00048 #endif
00049 #ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
00050 #include <net-snmp/library/snmpSSHDomain.h>
00051 #endif
00052 #ifdef NETSNMP_TRANSPORT_ALIAS_DOMAIN
00053 #include <net-snmp/library/snmpAliasDomain.h>
00054 #endif
00055 #ifdef NETSNMP_TRANSPORT_IPX_DOMAIN
00056 #include <net-snmp/library/snmpIPXDomain.h>
00057 #endif
00058 #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
00059 #include <net-snmp/library/snmpUnixDomain.h>
00060 #endif
00061 #ifdef NETSNMP_TRANSPORT_AAL5PVC_DOMAIN
00062 #include <net-snmp/library/snmpAAL5PVCDomain.h>
00063 #endif
00064 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
00065 #include <net-snmp/library/snmpUDPIPv6Domain.h>
00066 #endif
00067 #ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
00068 #include <net-snmp/library/snmpTCPIPv6Domain.h>
00069 #endif
00070 #include <net-snmp/library/snmp_api.h>
00071 #include <net-snmp/library/snmp_service.h>
00072 #include <net-snmp/library/read_config.h>
00073 
00074 netsnmp_feature_child_of(transport_all, libnetsnmp)
00075 
00076 netsnmp_feature_child_of(tdomain_support, transport_all)
00077 netsnmp_feature_child_of(tdomain_transport_oid, transport_all)
00078 netsnmp_feature_child_of(sockaddr_size, transport_all)
00079 
00080 /*
00081  * Our list of supported transport domains.  
00082  */
00083 
00084 static netsnmp_tdomain *domain_list = NULL;
00085 
00086 
00087 
00088 /*
00089  * The standard SNMP domains.  
00090  */
00091 
00092 oid             netsnmpUDPDomain[] = { 1, 3, 6, 1, 6, 1, 1 };
00093 size_t          netsnmpUDPDomain_len = OID_LENGTH(netsnmpUDPDomain);
00094 oid             netsnmpCLNSDomain[] = { 1, 3, 6, 1, 6, 1, 2 };
00095 size_t          netsnmpCLNSDomain_len = OID_LENGTH(netsnmpCLNSDomain);
00096 oid             netsnmpCONSDomain[] = { 1, 3, 6, 1, 6, 1, 3 };
00097 size_t          netsnmpCONSDomain_len = OID_LENGTH(netsnmpCONSDomain);
00098 oid             netsnmpDDPDomain[] = { 1, 3, 6, 1, 6, 1, 4 };
00099 size_t          netsnmpDDPDomain_len = OID_LENGTH(netsnmpDDPDomain);
00100 oid             netsnmpIPXDomain[] = { 1, 3, 6, 1, 6, 1, 5 };
00101 size_t          netsnmpIPXDomain_len = OID_LENGTH(netsnmpIPXDomain);
00102 
00103 
00104 
00105 static void     netsnmp_tdomain_dump(void);
00106 
00107 
00108 
00109 void
00110 init_snmp_transport(void)
00111 {
00112     netsnmp_ds_register_config(ASN_BOOLEAN,
00113                                "snmp", "dontLoadHostConfig",
00114                                NETSNMP_DS_LIBRARY_ID,
00115                                NETSNMP_DS_LIB_DONT_LOAD_HOST_FILES);
00116 }
00117 
00118 /*
00119  * Make a deep copy of an netsnmp_transport.  
00120  */
00121 netsnmp_transport *
00122 netsnmp_transport_copy(netsnmp_transport *t)
00123 {
00124     netsnmp_transport *n = NULL;
00125 
00126     if (t == NULL) {
00127         return NULL;
00128     }
00129 
00130     n = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
00131     if (n == NULL) {
00132         return NULL;
00133     }
00134     memset(n, 0, sizeof(netsnmp_transport));
00135 
00136     if (t->domain != NULL) {
00137         n->domain = t->domain;
00138         n->domain_length = t->domain_length;
00139     } else {
00140         n->domain = NULL;
00141         n->domain_length = 0;
00142     }
00143 
00144     if (t->local != NULL) {
00145         n->local = (u_char *) malloc(t->local_length);
00146         if (n->local == NULL) {
00147             netsnmp_transport_free(n);
00148             return NULL;
00149         }
00150         n->local_length = t->local_length;
00151         memcpy(n->local, t->local, t->local_length);
00152     } else {
00153         n->local = NULL;
00154         n->local_length = 0;
00155     }
00156 
00157     if (t->remote != NULL) {
00158         n->remote = (u_char *) malloc(t->remote_length);
00159         if (n->remote == NULL) {
00160             netsnmp_transport_free(n);
00161             return NULL;
00162         }
00163         n->remote_length = t->remote_length;
00164         memcpy(n->remote, t->remote, t->remote_length);
00165     } else {
00166         n->remote = NULL;
00167         n->remote_length = 0;
00168     }
00169 
00170     if (t->data != NULL && t->data_length > 0) {
00171         n->data = malloc(t->data_length);
00172         if (n->data == NULL) {
00173             netsnmp_transport_free(n);
00174             return NULL;
00175         }
00176         n->data_length = t->data_length;
00177         memcpy(n->data, t->data, t->data_length);
00178     } else {
00179         n->data = NULL;
00180         n->data_length = 0;
00181     }
00182 
00183     n->msgMaxSize = t->msgMaxSize;
00184     n->f_accept = t->f_accept;
00185     n->f_recv = t->f_recv;
00186     n->f_send = t->f_send;
00187     n->f_close = t->f_close;
00188     n->f_copy = t->f_copy;
00189     n->f_config = t->f_config;
00190     n->f_fmtaddr = t->f_fmtaddr;
00191     n->sock = t->sock;
00192     n->flags = t->flags;
00193     n->base_transport = netsnmp_transport_copy(t->base_transport);
00194 
00195     /* give the transport a chance to do "special things" */
00196     if (t->f_copy)
00197         t->f_copy(t, n);
00198                 
00199     return n;
00200 }
00201 
00202 
00203 
00204 void
00205 netsnmp_transport_free(netsnmp_transport *t)
00206 {
00207     if (NULL == t)
00208         return;
00209 
00210     SNMP_FREE(t->local);
00211     SNMP_FREE(t->remote);
00212     SNMP_FREE(t->data);
00213     netsnmp_transport_free(t->base_transport);
00214 
00215     SNMP_FREE(t);
00216 }
00217 
00218 /*
00219  * netsnmp_transport_peer_string
00220  *
00221  * returns string representation of peer address.
00222  *
00223  * caller is responsible for freeing the allocated string.
00224  */
00225 char *
00226 netsnmp_transport_peer_string(netsnmp_transport *t, void *data, int len)
00227 {
00228     char           *str;
00229 
00230     if (NULL == t)
00231         return NULL;
00232 
00233     if (t->f_fmtaddr != NULL)
00234         str = t->f_fmtaddr(t, data, len);
00235     else
00236         str = strdup("<UNKNOWN>");
00237 
00238     return str;
00239 }
00240 
00241 #ifndef NETSNMP_FEATURE_REMOVE_SOCKADDR_SIZE
00242 int
00243 netsnmp_sockaddr_size(struct sockaddr *sa)
00244 {
00245     if (NULL == sa)
00246         return 0;
00247 
00248     switch (sa->sa_family) {
00249         case AF_INET:
00250             return sizeof(struct sockaddr_in);
00251         break;
00252 #ifdef NETSNMP_ENABLE_IPV6
00253         case AF_INET6:
00254             return sizeof(struct sockaddr_in6);
00255             break;
00256 #endif
00257     }
00258 
00259     return 0;
00260 }
00261 #endif /* NETSNMP_FEATURE_REMOVE_SOCKADDR_SIZE */
00262     
00263 int
00264 netsnmp_transport_send(netsnmp_transport *t, void *packet, int length,
00265                        void **opaque, int *olength)
00266 {
00267     int dumpPacket, debugLength;
00268 
00269     if ((NULL == t) || (NULL == t->f_send)) {
00270         DEBUGMSGTL(("transport:pkt:send", "NULL transport or send function\n"));
00271         return SNMPERR_GENERR;
00272     }
00273 
00274     dumpPacket = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00275                                         NETSNMP_DS_LIB_DUMP_PACKET);
00276     debugLength = (SNMPERR_SUCCESS ==
00277                    debug_is_token_registered("transport:send"));
00278 
00279     if (dumpPacket | debugLength) {
00280         char *str = netsnmp_transport_peer_string(t,
00281                                                   opaque ? *opaque : NULL,
00282                                                   olength ? *olength : 0);
00283         if (debugLength)
00284             DEBUGMSGT_NC(("transport:send","%lu bytes to %s\n",
00285                           (unsigned long)length, str));
00286         if (dumpPacket)
00287             snmp_log(LOG_DEBUG, "\nSending %lu bytes to %s\n", 
00288                      (unsigned long)length, str);
00289         SNMP_FREE(str);
00290     }
00291     if (dumpPacket)
00292         xdump(packet, length, "");
00293 
00294     return t->f_send(t, packet, length, opaque, olength);
00295 }
00296 
00297 int
00298 netsnmp_transport_recv(netsnmp_transport *t, void *packet, int length,
00299                        void **opaque, int *olength)
00300 {
00301     int debugLength;
00302 
00303     if ((NULL == t) || (NULL == t->f_recv)) {
00304         DEBUGMSGTL(("transport:recv", "NULL transport or recv function\n"));
00305         return SNMPERR_GENERR;
00306     }
00307 
00308     length = t->f_recv(t, packet, length, opaque, olength);
00309 
00310     if (length <=0)
00311         return length; /* don't log timeouts/socket closed */
00312 
00313     debugLength = (SNMPERR_SUCCESS ==
00314                    debug_is_token_registered("transport:recv"));
00315 
00316     if (debugLength) {
00317         char *str = netsnmp_transport_peer_string(t,
00318                                                   opaque ? *opaque : NULL,
00319                                                   olength ? *olength : 0);
00320         if (debugLength)
00321             DEBUGMSGT_NC(("transport:recv","%d bytes from %s\n",
00322                           length, str));
00323         SNMP_FREE(str);
00324     }
00325 
00326     return length;
00327 }
00328 
00329 
00330 
00331 #ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_SUPPORT
00332 int
00333 netsnmp_tdomain_support(const oid * in_oid,
00334                         size_t in_len,
00335                         const oid ** out_oid, size_t * out_len)
00336 {
00337     netsnmp_tdomain *d = NULL;
00338 
00339     for (d = domain_list; d != NULL; d = d->next) {
00340         if (netsnmp_oid_equals(in_oid, in_len, d->name, d->name_length) == 0) {
00341             if (out_oid != NULL && out_len != NULL) {
00342                 *out_oid = d->name;
00343                 *out_len = d->name_length;
00344             }
00345             return 1;
00346         }
00347     }
00348     return 0;
00349 }
00350 #endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_SUPPORT */
00351 
00352 
00353 void
00354 netsnmp_tdomain_init(void)
00355 {
00356     DEBUGMSGTL(("tdomain", "netsnmp_tdomain_init() called\n"));
00357 
00358 /* include the configure generated list of constructor calls */
00359 #include "transports/snmp_transport_inits.h"
00360 
00361     netsnmp_tdomain_dump();
00362 }
00363 
00364 void
00365 netsnmp_clear_tdomain_list(void)
00366 {
00367     netsnmp_tdomain *list = domain_list, *next = NULL;
00368     DEBUGMSGTL(("tdomain", "clear_tdomain_list() called\n"));
00369 
00370     while (list != NULL) {
00371         next = list->next;
00372         SNMP_FREE(list->prefix);
00373         /* attention!! list itself is not in the heap, so we must not free it! */
00374         list = next;
00375     }
00376     domain_list = NULL;
00377 }
00378 
00379 
00380 static void
00381 netsnmp_tdomain_dump(void)
00382 {
00383     netsnmp_tdomain *d;
00384     int i = 0;
00385 
00386     DEBUGMSGTL(("tdomain", "domain_list -> "));
00387     for (d = domain_list; d != NULL; d = d->next) {
00388         DEBUGMSG(("tdomain", "{ "));
00389         DEBUGMSGOID(("tdomain", d->name, d->name_length));
00390         DEBUGMSG(("tdomain", ", \""));
00391         for (i = 0; d->prefix[i] != NULL; i++) {
00392             DEBUGMSG(("tdomain", "%s%s", d->prefix[i],
00393                       (d->prefix[i + 1]) ? "/" : ""));
00394         }
00395         DEBUGMSG(("tdomain", "\" } -> "));
00396     }
00397     DEBUGMSG(("tdomain", "[NIL]\n"));
00398 }
00399 
00400 
00401 
00402 int
00403 netsnmp_tdomain_register(netsnmp_tdomain *n)
00404 {
00405     netsnmp_tdomain **prevNext = &domain_list, *d;
00406 
00407     if (n != NULL) {
00408         for (d = domain_list; d != NULL; d = d->next) {
00409             if (netsnmp_oid_equals(n->name, n->name_length,
00410                                 d->name, d->name_length) == 0) {
00411                 /*
00412                  * Already registered.  
00413                  */
00414                 return 0;
00415             }
00416             prevNext = &(d->next);
00417         }
00418         n->next = NULL;
00419         *prevNext = n;
00420         return 1;
00421     } else {
00422         return 0;
00423     }
00424 }
00425 
00426 
00427 
00428 netsnmp_feature_child_of(tdomain_unregister, netsnmp_unused)
00429 #ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_UNREGISTER
00430 int
00431 netsnmp_tdomain_unregister(netsnmp_tdomain *n)
00432 {
00433     netsnmp_tdomain **prevNext = &domain_list, *d;
00434 
00435     if (n != NULL) {
00436         for (d = domain_list; d != NULL; d = d->next) {
00437             if (netsnmp_oid_equals(n->name, n->name_length,
00438                                 d->name, d->name_length) == 0) {
00439                 *prevNext = n->next;
00440                 SNMP_FREE(n->prefix);
00441                 return 1;
00442             }
00443             prevNext = &(d->next);
00444         }
00445         return 0;
00446     } else {
00447         return 0;
00448     }
00449 }
00450 #endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_UNREGISTER */
00451 
00452 
00453 static netsnmp_tdomain *
00454 find_tdomain(const char* spec)
00455 {
00456     netsnmp_tdomain *d;
00457     for (d = domain_list; d != NULL; d = d->next) {
00458         int i;
00459         for (i = 0; d->prefix[i] != NULL; i++)
00460             if (strcasecmp(d->prefix[i], spec) == 0) {
00461                 DEBUGMSGTL(("tdomain",
00462                             "Found domain \"%s\" from specifier \"%s\"\n",
00463                             d->prefix[0], spec));
00464                 return d;
00465             }
00466     }
00467     DEBUGMSGTL(("tdomain", "Found no domain from specifier \"%s\"\n", spec));
00468     return NULL;
00469 }
00470 
00471 static int
00472 netsnmp_is_fqdn(const char *thename)
00473 {
00474     if (!thename)
00475         return 0;
00476     while(*thename) {
00477         if (*thename != '.' && !isupper((unsigned char)*thename) &&
00478             !islower((unsigned char)*thename) &&
00479             !isdigit((unsigned char)*thename) && *thename != '-') {
00480             return 0;
00481         }
00482         thename++;
00483     }
00484     return 1;
00485 }
00486 
00487 /*
00488  * Locate the appropriate transport domain and call the create function for
00489  * it.
00490  */
00491 netsnmp_transport *
00492 netsnmp_tdomain_transport_full(const char *application,
00493                                const char *str, int local,
00494                                const char *default_domain,
00495                                const char *default_target)
00496 {
00497     netsnmp_tdomain    *match = NULL;
00498     const char         *addr = NULL;
00499     const char * const *spec = NULL;
00500     int                 any_found = 0;
00501     char buf[SNMP_MAXPATH];
00502     extern const char *curfilename;             /* from read_config.c */
00503     const char        *prev_curfilename;
00504 
00505     prev_curfilename = curfilename;
00506 
00507     DEBUGMSGTL(("tdomain",
00508                 "tdomain_transport_full(\"%s\", \"%s\", %d, \"%s\", \"%s\")\n",
00509                 application, str ? str : "[NIL]", local,
00510                 default_domain ? default_domain : "[NIL]",
00511                 default_target ? default_target : "[NIL]"));
00512 
00513     /* see if we can load a host-name specific set of conf files */
00514     if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00515                                 NETSNMP_DS_LIB_DONT_LOAD_HOST_FILES) &&
00516         netsnmp_is_fqdn(str)) {
00517         static int have_added_handler = 0;
00518         char *newhost;
00519         struct config_line *config_handlers;
00520         struct config_files file_names;
00521         char *prev_hostname;
00522 
00523         /* register a "transport" specifier */
00524         if (!have_added_handler) {
00525             have_added_handler = 1;
00526             netsnmp_ds_register_config(ASN_OCTET_STR,
00527                                        "snmp", "transport",
00528                                        NETSNMP_DS_LIBRARY_ID,
00529                                        NETSNMP_DS_LIB_HOSTNAME);
00530         }
00531 
00532         /* we save on specific setting that we don't allow to change
00533            from one transport creation to the next; ie, we don't want
00534            the "transport" specifier to be a default.  It should be a
00535            single invocation use only */
00536         prev_hostname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00537                                               NETSNMP_DS_LIB_HOSTNAME);
00538         if (prev_hostname)
00539             prev_hostname = strdup(prev_hostname);
00540 
00541         /* read in the hosts/STRING.conf files */
00542         config_handlers = read_config_get_handlers("snmp");
00543         snprintf(buf, sizeof(buf)-1, "hosts/%s", str);
00544         file_names.fileHeader = buf;
00545         file_names.start = config_handlers;
00546         file_names.next = NULL;
00547         DEBUGMSGTL(("tdomain", "checking for host specific config %s\n",
00548                     buf));
00549         read_config_files_of_type(EITHER_CONFIG, &file_names);
00550 
00551         if (NULL !=
00552             (newhost = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00553                                              NETSNMP_DS_LIB_HOSTNAME))) {
00554             strncpy(buf, newhost, sizeof(buf)-1);
00555             str = buf;
00556         }
00557 
00558         netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
00559                               NETSNMP_DS_LIB_HOSTNAME,
00560                               prev_hostname);
00561         SNMP_FREE(prev_hostname);
00562     }
00563 
00564     /* First try - assume that there is a domain in str (domain:target) */
00565 
00566     if (str != NULL) {
00567         const char *cp;
00568         if ((cp = strchr(str, ':')) != NULL) {
00569             char* mystring = (char*)malloc(cp + 1 - str);
00570             memcpy(mystring, str, cp - str);
00571             mystring[cp - str] = '\0';
00572             addr = cp + 1;
00573 
00574             match = find_tdomain(mystring);
00575             free(mystring);
00576         }
00577     }
00578 
00579     /*
00580      * Second try, if there is no domain in str (target), then try the
00581      * default domain
00582      */
00583 
00584     if (match == NULL) {
00585         addr = str;
00586         if (addr && *addr == '/') {
00587             DEBUGMSGTL(("tdomain",
00588                         "Address starts with '/', so assume \"unix\" "
00589                         "domain\n"));
00590             match = find_tdomain("unix");
00591         } else if (default_domain) {
00592             DEBUGMSGTL(("tdomain",
00593                         "Use user specified default domain \"%s\"\n",
00594                         default_domain));
00595             match = find_tdomain(default_domain);
00596         } else {
00597             spec = netsnmp_lookup_default_domains(application);
00598             if (spec == NULL) {
00599                 DEBUGMSGTL(("tdomain",
00600                             "No default domain found, assume \"udp\"\n"));
00601                 match = find_tdomain("udp");
00602             } else {
00603                 const char * const * r = spec;
00604                 DEBUGMSGTL(("tdomain",
00605                             "Use application default domains"));
00606                 while(*r) {
00607                     DEBUGMSG(("tdomain", " \"%s\"", *r));
00608                     ++r;
00609                 }
00610                 DEBUGMSG(("tdomain", "\n"));
00611             }
00612         }
00613     }
00614 
00615     for(;;) {
00616         if (match) {
00617             netsnmp_transport *t = NULL;
00618             const char* addr2;
00619 
00620             any_found = 1;
00621             /*
00622              * Ok, we know what domain to try, lets see what default data
00623              * should be used with it
00624              */
00625             if (default_target != NULL)
00626                 addr2 = default_target;
00627             else
00628                 addr2 = netsnmp_lookup_default_target(application,
00629                                                       match->prefix[0]);
00630             DEBUGMSGTL(("tdomain",
00631                         "trying domain \"%s\" address \"%s\" "
00632                         "default address \"%s\"\n",
00633                         match->prefix[0], addr ? addr : "[NIL]",
00634                         addr2 ? addr2 : "[NIL]"));
00635             if (match->f_create_from_tstring) {
00636                 NETSNMP_LOGONCE((LOG_WARNING,
00637                                  "transport domain %s uses deprecated f_create_from_tstring\n",
00638                                  match->prefix[0]));
00639                 t = match->f_create_from_tstring(addr, local);
00640             }
00641             else
00642                 t = match->f_create_from_tstring_new(addr, local, addr2);
00643             if (t) {
00644                 curfilename = prev_curfilename;
00645                 return t;
00646             }
00647         }
00648         addr = str;
00649         if (spec && *spec)
00650             match = find_tdomain(*spec++);
00651         else
00652             break;
00653     }
00654     if (!any_found)
00655         snmp_log(LOG_ERR, "No support for any checked transport domain\n");
00656     curfilename = prev_curfilename;
00657     return NULL;
00658 }
00659 
00660 
00661 netsnmp_transport *
00662 netsnmp_tdomain_transport(const char *str, int local,
00663                           const char *default_domain)
00664 {
00665     return netsnmp_tdomain_transport_full("snmp", str, local, default_domain,
00666                                           NULL);
00667 }
00668 
00669 
00670 #ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_TRANSPORT_OID
00671 netsnmp_transport *
00672 netsnmp_tdomain_transport_oid(const oid * dom,
00673                               size_t dom_len,
00674                               const u_char * o, size_t o_len, int local)
00675 {
00676     netsnmp_tdomain *d;
00677     int             i;
00678 
00679     DEBUGMSGTL(("tdomain", "domain \""));
00680     DEBUGMSGOID(("tdomain", dom, dom_len));
00681     DEBUGMSG(("tdomain", "\"\n"));
00682 
00683     for (d = domain_list; d != NULL; d = d->next) {
00684         for (i = 0; d->prefix[i] != NULL; i++) {
00685             if (netsnmp_oid_equals(dom, dom_len, d->name, d->name_length) ==
00686                 0) {
00687                 return d->f_create_from_ostring(o, o_len, local);
00688             }
00689         }
00690     }
00691 
00692     snmp_log(LOG_ERR, "No support for requested transport domain\n");
00693     return NULL;
00694 }
00695 #endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_TRANSPORT_OID */
00696 
00697 netsnmp_transport*
00698 netsnmp_transport_open(const char* application, const char* str, int local)
00699 {
00700     return netsnmp_tdomain_transport_full(application, str, local, NULL, NULL);
00701 }
00702 
00703 netsnmp_transport*
00704 netsnmp_transport_open_server(const char* application, const char* str)
00705 {
00706     return netsnmp_tdomain_transport_full(application, str, 1, NULL, NULL);
00707 }
00708 
00709 netsnmp_transport*
00710 netsnmp_transport_open_client(const char* application, const char* str)
00711 {
00712     return netsnmp_tdomain_transport_full(application, str, 0, NULL, NULL);
00713 }
00714 
00717 int
00718 netsnmp_transport_add_to_list(netsnmp_transport_list **transport_list,
00719                               netsnmp_transport *transport)
00720 {
00721     netsnmp_transport_list *newptr =
00722         SNMP_MALLOC_TYPEDEF(netsnmp_transport_list);
00723 
00724     if (!newptr)
00725         return 1;
00726 
00727     newptr->next = *transport_list;
00728     newptr->transport = transport;
00729 
00730     *transport_list = newptr;
00731 
00732     return 0;
00733 }
00734 
00735 
00738 int
00739 netsnmp_transport_remove_from_list(netsnmp_transport_list **transport_list,
00740                                    netsnmp_transport *transport)
00741 {
00742     netsnmp_transport_list *ptr = *transport_list, *lastptr = NULL;
00743 
00744     while (ptr && ptr->transport != transport) {
00745         lastptr = ptr;
00746         ptr = ptr->next;
00747     }
00748 
00749     if (!ptr)
00750         return 1;
00751 
00752     if (lastptr)
00753         lastptr->next = ptr->next;
00754     else
00755         *transport_list = ptr->next;
00756 
00757     SNMP_FREE(ptr);
00758 
00759     return 0;
00760 }
00761 
00762 int
00763 netsnmp_transport_config_compare(netsnmp_transport_config *left,
00764                                  netsnmp_transport_config *right) {
00765     return strcmp(left->key, right->key);
00766 }
00767 
00768 netsnmp_transport_config *
00769 netsnmp_transport_create_config(char *key, char *value) {
00770     netsnmp_transport_config *entry =
00771         SNMP_MALLOC_TYPEDEF(netsnmp_transport_config);
00772     entry->key = strdup(key);
00773     entry->value = strdup(value);
00774     return entry;
00775 }