net-snmp  5.4.1
snmp_transport.c
00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #include <stdio.h>
00004 #if HAVE_STRING_H
00005 #include <string.h>
00006 #else
00007 #include <strings.h>
00008 #endif
00009 #include <sys/types.h>
00010 
00011 #if HAVE_STDLIB_H
00012 #include <stdlib.h>
00013 #endif
00014 
00015 #if HAVE_DMALLOC_H
00016 #include <dmalloc.h>
00017 #endif
00018 
00019 #include <net-snmp/output_api.h>
00020 #include <net-snmp/utilities.h>
00021 
00022 #include <net-snmp/library/snmp_transport.h>
00023 #include <net-snmp/library/snmpUDPDomain.h>
00024 #ifdef NETSNMP_TRANSPORT_TLS_DOMAIN
00025 #include <net-snmp/library/snmpTLSDomain.h>
00026 #endif
00027 #ifdef NETSNMP_TRANSPORT_STD_DOMAIN
00028 #include <net-snmp/library/snmpSTDDomain.h>
00029 #endif
00030 #ifdef NETSNMP_TRANSPORT_TCP_DOMAIN
00031 #include <net-snmp/library/snmpTCPDomain.h>
00032 #endif
00033 #ifdef NETSNMP_TRANSPORT_IPX_DOMAIN
00034 #include <net-snmp/library/snmpIPXDomain.h>
00035 #endif
00036 #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
00037 #include <net-snmp/library/snmpUnixDomain.h>
00038 #endif
00039 #ifdef NETSNMP_TRANSPORT_AAL5PVC_DOMAIN
00040 #include <net-snmp/library/snmpAAL5PVCDomain.h>
00041 #endif
00042 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
00043 #include <net-snmp/library/snmpUDPIPv6Domain.h>
00044 #endif
00045 #ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
00046 #include <net-snmp/library/snmpTCPIPv6Domain.h>
00047 #endif
00048 #include <net-snmp/library/snmp_api.h>
00049 #include <net-snmp/library/snmp_service.h>
00050 
00051 
00052 /*
00053  * Our list of supported transport domains.  
00054  */
00055 
00056 static netsnmp_tdomain *domain_list = NULL;
00057 
00058 
00059 
00060 /*
00061  * The standard SNMP domains.  
00062  */
00063 
00064 oid             netsnmpUDPDomain[] = { 1, 3, 6, 1, 6, 1, 1 };
00065 size_t          netsnmpUDPDomain_len = OID_LENGTH(netsnmpUDPDomain);
00066 oid             netsnmpCLNSDomain[] = { 1, 3, 6, 1, 6, 1, 2 };
00067 size_t          netsnmpCLNSDomain_len = OID_LENGTH(netsnmpCLNSDomain);
00068 oid             netsnmpCONSDomain[] = { 1, 3, 6, 1, 6, 1, 3 };
00069 size_t          netsnmpCONSDomain_len = OID_LENGTH(netsnmpCONSDomain);
00070 oid             netsnmpDDPDomain[] = { 1, 3, 6, 1, 6, 1, 4 };
00071 size_t          netsnmpDDPDomain_len = OID_LENGTH(netsnmpDDPDomain);
00072 oid             netsnmpIPXDomain[] = { 1, 3, 6, 1, 6, 1, 5 };
00073 size_t          netsnmpIPXDomain_len = OID_LENGTH(netsnmpIPXDomain);
00074 
00075 
00076 
00077 static void     netsnmp_tdomain_dump(void);
00078 
00079 
00080 /*
00081  * Make a deep copy of an netsnmp_transport.  
00082  */
00083 
00084 netsnmp_transport *
00085 netsnmp_transport_copy(netsnmp_transport *t)
00086 {
00087     netsnmp_transport *n = NULL;
00088 
00089     n = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
00090     if (n == NULL) {
00091         return NULL;
00092     }
00093     memset(n, 0, sizeof(netsnmp_transport));
00094 
00095     if (t->domain != NULL) {
00096         n->domain = t->domain;
00097         n->domain_length = t->domain_length;
00098     } else {
00099         n->domain = NULL;
00100         n->domain_length = 0;
00101     }
00102 
00103     if (t->local != NULL) {
00104         n->local = (u_char *) malloc(t->local_length);
00105         if (n->local == NULL) {
00106             netsnmp_transport_free(n);
00107             return NULL;
00108         }
00109         n->local_length = t->local_length;
00110         memcpy(n->local, t->local, t->local_length);
00111     } else {
00112         n->local = NULL;
00113         n->local_length = 0;
00114     }
00115 
00116     if (t->remote != NULL) {
00117         n->remote = (u_char *) malloc(t->remote_length);
00118         if (n->remote == NULL) {
00119             netsnmp_transport_free(n);
00120             return NULL;
00121         }
00122         n->remote_length = t->remote_length;
00123         memcpy(n->remote, t->remote, t->remote_length);
00124     } else {
00125         n->remote = NULL;
00126         n->remote_length = 0;
00127     }
00128 
00129     if (t->data != NULL && t->data_length > 0) {
00130         n->data = malloc(t->data_length);
00131         if (n->data == NULL) {
00132             netsnmp_transport_free(n);
00133             return NULL;
00134         }
00135         n->data_length = t->data_length;
00136         memcpy(n->data, t->data, t->data_length);
00137     } else {
00138         n->data = NULL;
00139         n->data_length = 0;
00140     }
00141 
00142     n->msgMaxSize = t->msgMaxSize;
00143     n->f_accept = t->f_accept;
00144     n->f_recv = t->f_recv;
00145     n->f_send = t->f_send;
00146     n->f_close = t->f_close;
00147     n->f_fmtaddr = t->f_fmtaddr;
00148     n->sock = t->sock;
00149     n->flags = t->flags;
00150 
00151     return n;
00152 }
00153 
00154 
00155 
00156 void
00157 netsnmp_transport_free(netsnmp_transport *t)
00158 {
00159     if (NULL == t)
00160         return;
00161 
00162     if (t->local != NULL) {
00163         SNMP_FREE(t->local);
00164     }
00165     if (t->remote != NULL) {
00166         SNMP_FREE(t->remote);
00167     }
00168     if (t->data != NULL) {
00169         SNMP_FREE(t->data);
00170     }
00171     SNMP_FREE(t);
00172 }
00173 
00174 
00175 
00176 int
00177 netsnmp_tdomain_support(const oid * in_oid,
00178                         size_t in_len,
00179                         const oid ** out_oid, size_t * out_len)
00180 {
00181     netsnmp_tdomain *d = NULL;
00182 
00183     for (d = domain_list; d != NULL; d = d->next) {
00184         if (netsnmp_oid_equals(in_oid, in_len, d->name, d->name_length) == 0) {
00185             if (out_oid != NULL && out_len != NULL) {
00186                 *out_oid = d->name;
00187                 *out_len = d->name_length;
00188             }
00189             return 1;
00190         }
00191     }
00192     return 0;
00193 }
00194 
00195 
00196 
00197 void
00198 netsnmp_tdomain_init(void)
00199 {
00200     DEBUGMSGTL(("tdomain", "netsnmp_tdomain_init() called\n"));
00201     netsnmp_udp_ctor();
00202 #ifdef NETSNMP_TRANSPORT_STD_DOMAIN
00203     netsnmp_std_ctor();
00204 #endif
00205 #ifdef NETSNMP_TRANSPORT_TCP_DOMAIN
00206     netsnmp_tcp_ctor();
00207 #endif
00208 #ifdef NETSNMP_TRANSPORT_IPX_DOMAIN
00209     netsnmp_ipx_ctor();
00210 #endif
00211 #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
00212     netsnmp_unix_ctor();
00213 #endif
00214 #ifdef NETSNMP_TRANSPORT_AAL5PVC_DOMAIN
00215     netsnmp_aal5pvc_ctor();
00216 #endif
00217 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
00218     netsnmp_udp6_ctor();
00219 #endif
00220 #ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
00221     netsnmp_tcp6_ctor();
00222 #endif
00223     netsnmp_tdomain_dump();
00224 }
00225 
00226 void
00227 netsnmp_clear_tdomain_list(void)
00228 {
00229     netsnmp_tdomain *list = domain_list, *next = NULL;
00230     DEBUGMSGTL(("tdomain", "clear_tdomain_list() called\n"));
00231 
00232     while (list != NULL) {
00233         next = list->next;
00234         SNMP_FREE(list->prefix);
00235         /* attention!! list itself is not in the heap, so we must not free it! */
00236         list = next;
00237     }
00238     domain_list = NULL;
00239 }
00240 
00241 
00242 static void
00243 netsnmp_tdomain_dump(void)
00244 {
00245     netsnmp_tdomain *d;
00246     int i = 0;
00247 
00248     DEBUGMSGTL(("tdomain", "domain_list -> "));
00249     for (d = domain_list; d != NULL; d = d->next) {
00250         DEBUGMSG(("tdomain", "{ "));
00251         DEBUGMSGOID(("tdomain", d->name, d->name_length));
00252         DEBUGMSG(("tdomain", ", \""));
00253         for (i = 0; d->prefix[i] != NULL; i++) {
00254             DEBUGMSG(("tdomain", "%s%s", d->prefix[i],
00255                       (d->prefix[i + 1]) ? "/" : ""));
00256         }
00257         DEBUGMSG(("tdomain", "\" } -> "));
00258     }
00259     DEBUGMSG(("tdomain", "[NIL]\n"));
00260 }
00261 
00262 
00263 
00264 int
00265 netsnmp_tdomain_register(netsnmp_tdomain *n)
00266 {
00267     netsnmp_tdomain **prevNext = &domain_list, *d;
00268 
00269     if (n != NULL) {
00270         for (d = domain_list; d != NULL; d = d->next) {
00271             if (netsnmp_oid_equals(n->name, n->name_length,
00272                                 d->name, d->name_length) == 0) {
00273                 /*
00274                  * Already registered.  
00275                  */
00276                 return 0;
00277             }
00278             prevNext = &(d->next);
00279         }
00280         n->next = NULL;
00281         *prevNext = n;
00282         return 1;
00283     } else {
00284         return 0;
00285     }
00286 }
00287 
00288 
00289 
00290 int
00291 netsnmp_tdomain_unregister(netsnmp_tdomain *n)
00292 {
00293     netsnmp_tdomain **prevNext = &domain_list, *d;
00294 
00295     if (n != NULL) {
00296         for (d = domain_list; d != NULL; d = d->next) {
00297             if (netsnmp_oid_equals(n->name, n->name_length,
00298                                 d->name, d->name_length) == 0) {
00299                 *prevNext = n->next;
00300                 SNMP_FREE(n->prefix);
00301                 return 1;
00302             }
00303             prevNext = &(d->next);
00304         }
00305         return 0;
00306     } else {
00307         return 0;
00308     }
00309 }
00310 
00311 
00312 /*
00313  * Locate the appropriate transport domain and call the create function for
00314  * it.
00315  */
00316 netsnmp_transport *
00317 netsnmp_tdomain_transport_full(const char *application,
00318                                const char *str, int local,
00319                                const char *default_domain,
00320                                const char *default_target)
00321 {
00322     netsnmp_tdomain *d, *match = NULL;
00323     netsnmp_transport *t = NULL;
00324     const char     *spec, *addr = NULL, *addr2;
00325     char           *cp, *mystring = NULL;
00326     int             i;
00327 
00328     DEBUGMSGTL(("tdomain",
00329                 "tdomain_transport_full(\"%s\", \"%s\", %d, \"%s\", \"%s\")\n",
00330                 application, str ? str : "[NIL]", local,
00331                 default_domain ? default_domain : "[NIL]",
00332                 default_target ? default_target : "[NIL]"));
00333 
00334     /* First try - assume that there is a domain in str (domain:target) */
00335 
00336     if (str != NULL) {
00337         if ((mystring = strdup(str)) == NULL) {
00338             DEBUGMSGTL(("tdomain", "can't strdup(\"%s\")\n", str));
00339             return NULL;
00340         }
00341 
00342         if ((cp = strchr(mystring, ':')) != NULL) {
00343             *cp = '\0';
00344             spec = mystring;
00345             addr = cp + 1;
00346 
00347             for (d = domain_list; d != NULL && match == NULL; d = d->next)
00348                 for (i = 0; d->prefix[i] != NULL && match == NULL; i++)
00349                     if (strcasecmp(d->prefix[i], spec) == 0)
00350                         match = d;
00351             if (match != NULL)
00352                 DEBUGMSGTL(("tdomain",
00353                             "Found domain \"%s\" from specifier \"%s\"\n",
00354                             match->prefix[0], spec));
00355             else
00356                 DEBUGMSGTL(("tdomain",
00357                             "Found no domain from specifier \"%s\"\n", spec));
00358         }
00359     }
00360 
00361     /*
00362      * Second try, if there is no domain in str (target), then try the
00363      * default domain
00364      */
00365 
00366     if (match == NULL) {
00367         addr = str;
00368         if (addr && *addr == '/') {
00369             spec = "unix";
00370             DEBUGMSGTL(("tdomain",
00371                         "Address starts with '/', so assume \"unix\" "
00372                         "domain\n"));
00373         } else if (default_domain) {
00374             spec = default_domain;
00375             DEBUGMSGTL(("tdomain",
00376                         "Use user specified default domain \"%s\"\n", spec));
00377         } else {
00378             spec = netsnmp_lookup_default_domain(application);
00379             if (spec == NULL) {
00380                 spec = "udp";
00381                 DEBUGMSGTL(("tdomain",
00382                             "No default domain found, assume \"udp\"\n"));
00383             } else {
00384                 DEBUGMSGTL(("tdomain",
00385                             "Use application default domain \"%s\"\n", spec));
00386             }
00387         }
00388         for (d = domain_list; d != NULL && match == NULL; d = d->next)
00389             for (i = 0; d->prefix[i] != NULL && match == NULL; i++)
00390                 if (strcasecmp(d->prefix[i], spec) == 0)
00391                     match = d;
00392         if (match != NULL)
00393             DEBUGMSGTL(("tdomain",
00394                         "Found domain \"%s\" from specifier \"%s\"\n",
00395                         match->prefix[0], spec));
00396         else {
00397             DEBUGMSGTL(("tdomain",
00398                         "Found no domain from specifier \"%s\"\n", spec));
00399             SNMP_FREE(mystring);
00400             snmp_log(LOG_ERR,
00401                      "No support for any checked transport domain\n");
00402             return NULL;
00403         }
00404     }
00405 
00406     /*
00407      * Ok, we know what domain to use, lets see what default data that should
00408      * be used
00409      */
00410 
00411     if (default_target != NULL)
00412         addr2 = default_target;
00413     else
00414         addr2 = netsnmp_lookup_default_target(application, match->prefix[0]);
00415 
00416     DEBUGMSGTL(("tdomain",
00417                 "domain \"%s\" address \"%s\" default address \"%s\"\n",
00418                 match->prefix[0], addr ? addr : "[NIL]",
00419                 addr2 ? addr2 : "[NIL]"));
00420 
00421     if (match->f_create_from_tstring)
00422       t = match->f_create_from_tstring(addr, local);
00423     else
00424       t = match->f_create_from_tstring_new(addr, local, addr2);
00425     SNMP_FREE(mystring);
00426     return t;
00427 }
00428 
00429 
00430 netsnmp_transport *
00431 netsnmp_tdomain_transport(const char *str, int local,
00432                           const char *default_domain)
00433 {
00434     return netsnmp_tdomain_transport_full("snmp", str, local, default_domain,
00435                                           NULL);
00436 }
00437 
00438 
00439 netsnmp_transport *
00440 netsnmp_tdomain_transport_oid(const oid * dom,
00441                               size_t dom_len,
00442                               const u_char * o, size_t o_len, int local)
00443 {
00444     netsnmp_tdomain *d;
00445     int             i;
00446 
00447     DEBUGMSGTL(("tdomain", "domain \""));
00448     DEBUGMSGOID(("tdomain", dom, dom_len));
00449     DEBUGMSG(("tdomain", "\"\n"));
00450 
00451     for (d = domain_list; d != NULL; d = d->next) {
00452         for (i = 0; d->prefix[i] != NULL; i++) {
00453             if (netsnmp_oid_equals(dom, dom_len, d->name, d->name_length) ==
00454                 0) {
00455                 return d->f_create_from_ostring(o, o_len, local);
00456             }
00457         }
00458     }
00459 
00460     snmp_log(LOG_ERR, "No support for requested transport domain\n");
00461     return NULL;
00462 }
00463 
00464 netsnmp_transport*
00465 netsnmp_transport_open(const char* application, const char* str, int local)
00466 {
00467     return netsnmp_tdomain_transport_full(application, str, local, NULL, NULL);
00468 }
00469 
00470 netsnmp_transport*
00471 netsnmp_transport_open_server(const char* application, const char* str)
00472 {
00473     return netsnmp_tdomain_transport_full(application, str, 1, NULL, NULL);
00474 }
00475 
00476 netsnmp_transport*
00477 netsnmp_transport_open_client(const char* application, const char* str)
00478 {
00479     return netsnmp_tdomain_transport_full(application, str, 0, NULL, NULL);
00480 }
00481 
00484 int
00485 netsnmp_transport_add_to_list(netsnmp_transport_list **transport_list,
00486                               netsnmp_transport *transport)
00487 {
00488     netsnmp_transport_list *newptr =
00489         SNMP_MALLOC_TYPEDEF(netsnmp_transport_list);
00490 
00491     if (!newptr)
00492         return 1;
00493 
00494     newptr->next = *transport_list;
00495     newptr->transport = transport;
00496 
00497     *transport_list = newptr;
00498 
00499     return 0;
00500 }
00501 
00502 
00505 int
00506 netsnmp_transport_remove_from_list(netsnmp_transport_list **transport_list,
00507                                    netsnmp_transport *transport)
00508 {
00509     netsnmp_transport_list *ptr = *transport_list, *lastptr = NULL;
00510 
00511     while (ptr && ptr->transport != transport) {
00512         lastptr = ptr;
00513         ptr = ptr->next;
00514     }
00515 
00516     if (!ptr)
00517         return 1;
00518 
00519     if (lastptr)
00520         lastptr->next = ptr->next;
00521     else
00522         *transport_list = ptr->next;
00523 
00524     SNMP_FREE(ptr);
00525 
00526     return 0;
00527 }