snmpUDPIPv6Domain.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:40k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #ifdef SNMP_TRANSPORT_UDPIPV6_DOMAIN
  3. /*
  4.  * hack-o-matic for Cygwin to use winsock2
  5. */
  6. #if defined(cygwin)
  7. #undef HAVE_UNISTD_H
  8. #undef HAVE_NETINET_IN_H
  9. #undef HAVE_ARPA_INET_H
  10. #undef HAVE_NET_IF_H
  11. #undef HAVE_NETDB_H
  12. #undef HAVE_SYS_PARAM_H
  13. #undef HAVE_SYS_SELECT_H
  14. #undef HAVE_SYS_SOCKET_H
  15. #undef HAVE_IN_ADDR_T
  16. #endif
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <ctype.h>
  20. #include <errno.h>
  21. #if HAVE_STRING_H
  22. #include <string.h>
  23. #else
  24. #include <strings.h>
  25. #endif
  26. #if HAVE_STDLIB_H
  27. #include <stdlib.h>
  28. #endif
  29. #if HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #if HAVE_SYS_SOCKET_H
  33. #include <sys/socket.h>
  34. #endif
  35. #if defined(HAVE_WINSOCK_H) || defined(cygwin)
  36.     /*
  37.      *  Windows IPv6 support is part of WinSock2 only
  38.      */
  39. #include <winsock2.h>
  40. #include <ws2tcpip.h>
  41. #undef  HAVE_IF_NAMETOINDEX
  42. extern int         inet_pton(int, const char*, void*);
  43. extern const char *inet_ntop(int, const void*, char*, size_t);
  44. const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
  45. #endif
  46. #if HAVE_NETINET_IN_H
  47. #include <netinet/in.h>
  48. #endif
  49. #if HAVE_ARPA_INET_H
  50. #include <arpa/inet.h>
  51. #endif
  52. #if HAVE_NETDB_H
  53. #include <netdb.h>
  54. #endif
  55. #if HAVE_NET_IF_H
  56. #include <net/if.h>
  57. #endif
  58. #if HAVE_DMALLOC_H
  59. #include <dmalloc.h>
  60. #endif
  61. #include <net-snmp/types.h>
  62. #include <net-snmp/output_api.h>
  63. #include <net-snmp/config_api.h>
  64. #include <net-snmp/library/snmp_transport.h>
  65. #include <net-snmp/library/snmpUDPIPv6Domain.h>
  66. oid netsnmp_UDPIPv6Domain[] = { TRANSPORT_DOMAIN_UDP_IPV6 };
  67. static netsnmp_tdomain udp6Domain;
  68. /*
  69.  * from snmpUDPDomain. not static, but not public, either.
  70.  * (ie don't put it in a public header.)
  71.  */
  72. extern void _netsnmp_udp_sockopt_set(int fd, int server);
  73. /*
  74.  * Return a string representing the address in data, or else the "far end"
  75.  * address if data is NULL.  
  76.  */
  77. static char *
  78. netsnmp_udp6_fmtaddr(netsnmp_transport *t, void *data, int len)
  79. {
  80.     struct sockaddr_in6 *to = NULL;
  81.     DEBUGMSGTL(("netsnmp_udp6", "fmtaddr: t = %p, data = %p, len = %dn", t,
  82.                 data, len));
  83.     if (data != NULL && len == sizeof(struct sockaddr_in6)) {
  84.         to = (struct sockaddr_in6 *) data;
  85.     } else if (t != NULL && t->data != NULL) {
  86.         to = (struct sockaddr_in6 *) t->data;
  87.     }
  88.     if (to == NULL) {
  89.         return strdup("UDP/IPv6: unknown");
  90.     } else {
  91.         char addr[INET6_ADDRSTRLEN];
  92.         char tmp[INET6_ADDRSTRLEN + 8];
  93.         sprintf(tmp, "UDP/IPv6: [%s]:%hd",
  94.                 inet_ntop(AF_INET6, (void *) &(to->sin6_addr), addr,
  95.                           INET6_ADDRSTRLEN), ntohs(to->sin6_port));
  96.         return strdup(tmp);
  97.     }
  98. }
  99. /*
  100.  * You can write something into opaque that will subsequently get passed back 
  101.  * to your send function if you like.  For instance, you might want to
  102.  * remember where a PDU came from, so that you can send a reply there...  
  103.  */
  104. static int
  105. netsnmp_udp6_recv(netsnmp_transport *t, void *buf, int size,
  106.   void **opaque, int *olength)
  107. {
  108.     int             rc = -1;
  109.     socklen_t       fromlen = sizeof(struct sockaddr_in6);
  110.     struct sockaddr *from;
  111.     if (t != NULL && t->sock >= 0) {
  112.         from = (struct sockaddr *) malloc(sizeof(struct sockaddr_in6));
  113.         if (from == NULL) {
  114.             *opaque = NULL;
  115.             *olength = 0;
  116.             return -1;
  117.         } else {
  118.             memset(from, 0, fromlen);
  119.         }
  120. while (rc < 0) {
  121.   rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
  122.   if (rc < 0 && errno != EINTR) {
  123.     break;
  124.   }
  125. }
  126.         if (rc >= 0) {
  127.     char *str = netsnmp_udp6_fmtaddr(NULL, from, fromlen);
  128.             DEBUGMSGTL(("netsnmp_udp6",
  129. "recvfrom fd %d got %d bytes (from %s)n", t->sock,
  130.                         rc, str));
  131.             free(str);
  132.         } else {
  133.             DEBUGMSGTL(("netsnmp_udp6", "recvfrom fd %d err %d ("%s")n",
  134. t->sock, errno, strerror(errno)));
  135.         }
  136.         *opaque = (void *) from;
  137.         *olength = sizeof(struct sockaddr_in6);
  138.     }
  139.     return rc;
  140. }
  141. static int
  142. netsnmp_udp6_send(netsnmp_transport *t, void *buf, int size,
  143.   void **opaque, int *olength)
  144. {
  145.     int rc = -1;
  146.     struct sockaddr *to = NULL;
  147.     if (opaque != NULL && *opaque != NULL &&
  148.         *olength == sizeof(struct sockaddr_in6)) {
  149.         to = (struct sockaddr *) (*opaque);
  150.     } else if (t != NULL && t->data != NULL &&
  151.                t->data_length == sizeof(struct sockaddr_in6)) {
  152.         to = (struct sockaddr *) (t->data);
  153.     }
  154.     if (to != NULL && t != NULL && t->sock >= 0) {
  155.         char *str = netsnmp_udp6_fmtaddr(NULL, (void *)to,
  156.     sizeof(struct sockaddr_in6));
  157.         DEBUGMSGTL(("netsnmp_udp6", "send %d bytes from %p to %s on fd %dn",
  158.                     size, buf, str, t->sock));
  159.         free(str);
  160. while (rc < 0) {
  161.     rc = sendto(t->sock, buf, size, 0, to,sizeof(struct sockaddr_in6));
  162.     if (rc < 0 && errno != EINTR) {
  163. break;
  164.     }
  165. }
  166.     }
  167.     return rc;
  168. }
  169. static int
  170. netsnmp_udp6_close(netsnmp_transport *t)
  171. {
  172.     int rc = -1;
  173.     if (t != NULL && t->sock >= 0) {
  174.         DEBUGMSGTL(("netsnmp_udp6", "close fd %dn", t->sock));
  175. #ifndef HAVE_CLOSESOCKET
  176.         rc = close(t->sock);
  177. #else
  178.         rc = closesocket(t->sock);
  179. #endif
  180.         t->sock = -1;
  181.     }
  182.     return rc;
  183. }
  184. /*
  185.  * Open a UDP/IPv6-based transport for SNMP.  Local is TRUE if addr is the
  186.  * local address to bind to (i.e. this is a server-type session); otherwise
  187.  * addr is the remote address to send things to.  
  188.  */
  189. netsnmp_transport *
  190. netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
  191. {
  192.     netsnmp_transport *t = NULL;
  193.     int             rc = 0;
  194.     char           *str = NULL;
  195.     if (addr == NULL || addr->sin6_family != AF_INET6) {
  196.         return NULL;
  197.     }
  198.     t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
  199.     if (t == NULL) {
  200.         return NULL;
  201.     }
  202.     str = netsnmp_udp6_fmtaddr(NULL, (void *) addr,
  203.   sizeof(struct sockaddr_in6));
  204.     DEBUGMSGTL(("netsnmp_udp6", "open %s %sn", local ? "local" : "remote",
  205.                 str));
  206.     free(str);
  207.     memset(t, 0, sizeof(netsnmp_transport));
  208.     t->domain = netsnmp_UDPIPv6Domain;
  209.     t->domain_length =
  210.         sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]);
  211.     t->sock = socket(PF_INET6, SOCK_DGRAM, 0);
  212.     if (t->sock < 0) {
  213.         netsnmp_transport_free(t);
  214.         return NULL;
  215.     }
  216.     _netsnmp_udp_sockopt_set(t->sock, local);
  217.     if (local) {
  218.         /*
  219.          * This session is inteneded as a server, so we must bind on to the
  220.          * given IP address, which may include an interface address, or could
  221.          * be INADDR_ANY, but certainly includes a port number.
  222.          */
  223. #ifdef IPV6_V6ONLY
  224.         /* Try to restrict PF_INET6 socket to IPv6 communications only. */
  225.         {
  226.   int one=1;
  227.   if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {
  228.     DEBUGMSGTL(("netsnmp_udp6", "couldn't set IPV6_V6ONLY to %d bytes: %sn", one, strerror(errno)));
  229.   } 
  230. }
  231. #endif
  232.         rc = bind(t->sock, (struct sockaddr *) addr,
  233.   sizeof(struct sockaddr_in6));
  234.         if (rc != 0) {
  235.             netsnmp_udp6_close(t);
  236.             netsnmp_transport_free(t);
  237.             return NULL;
  238.         }
  239.         t->local = malloc(18);
  240.         if (t->local == NULL) {
  241.             netsnmp_udp6_close(t);
  242.             netsnmp_transport_free(t);
  243.             return NULL;
  244.         }
  245.         memcpy(t->local, addr->sin6_addr.s6_addr, 16);
  246.         t->local[16] = (addr->sin6_port & 0xff00) >> 8;
  247.         t->local[17] = (addr->sin6_port & 0x00ff) >> 0;
  248.         t->local_length = 18;
  249.         t->data = NULL;
  250.         t->data_length = 0;
  251.     } else {
  252.         /*
  253.          * This is a client session.  Save the address in the
  254.          * transport-specific data pointer for later use by netsnmp_udp6_send.
  255.          */
  256.         t->data = malloc(sizeof(struct sockaddr_in6));
  257.         if (t->data == NULL) {
  258.             netsnmp_udp6_close(t);
  259.             netsnmp_transport_free(t);
  260.             return NULL;
  261.         }
  262.         memcpy(t->data, addr, sizeof(struct sockaddr_in6));
  263.         t->data_length = sizeof(struct sockaddr_in6);
  264.         t->remote = malloc(18);
  265.         if (t->remote == NULL) {
  266.             netsnmp_udp6_close(t);
  267.             netsnmp_transport_free(t);
  268.             return NULL;
  269.         }
  270.         memcpy(t->remote, addr->sin6_addr.s6_addr, 16);
  271.         t->remote[16] = (addr->sin6_port & 0xff00) >> 8;
  272.         t->remote[17] = (addr->sin6_port & 0x00ff) >> 0;
  273.         t->remote_length = 18;
  274.     }
  275.     /*
  276.      * 16-bit length field, 8 byte UDP header, 40 byte IPv6 header.  
  277.      */
  278.     t->msgMaxSize = 0xffff - 8 - 40;
  279.     t->f_recv     = netsnmp_udp6_recv;
  280.     t->f_send     = netsnmp_udp6_send;
  281.     t->f_close    = netsnmp_udp6_close;
  282.     t->f_accept   = NULL;
  283.     t->f_fmtaddr  = netsnmp_udp6_fmtaddr;
  284.     return t;
  285. }
  286. int
  287. netsnmp_sockaddr_in6(struct sockaddr_in6 *addr,
  288.                      const char *inpeername, int remote_port)
  289. {
  290.     char           *cp = NULL, *peername = NULL;
  291.     char            debug_addr[INET6_ADDRSTRLEN];
  292. #if HAVE_GETADDRINFO
  293.     struct addrinfo *addrs = NULL;
  294.     struct addrinfo hint;
  295.     int             err;
  296. #elif HAVE_GETIPNODEBYNAME
  297.     struct hostent *hp = NULL;
  298.     int             err;
  299. #elif HAVE_GETHOSTBYNAME
  300.     struct hostent *hp = NULL;
  301. #endif
  302.     if (addr == NULL) {
  303.         return 0;
  304.     }
  305.     DEBUGMSGTL(("netsnmp_sockaddr_in6", "addr %p, peername "%s"n",
  306.                 addr, inpeername ? inpeername : "[NIL]"));
  307.     memset(addr, 0, sizeof(struct sockaddr_in6));
  308.     addr->sin6_family = AF_INET6;
  309.     addr->sin6_addr = in6addr_any;
  310.     if (remote_port > 0) {
  311.         addr->sin6_port = htons(remote_port);
  312.     } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
  313.   NETSNMP_DS_LIB_DEFAULT_PORT) > 0) {
  314.         addr->sin6_port = htons(netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
  315.  NETSNMP_DS_LIB_DEFAULT_PORT));
  316.     } else {
  317.         addr->sin6_port = htons(SNMP_PORT);
  318.     }
  319.     if (inpeername != NULL) {
  320.         /*
  321.          * Duplicate the peername because we might want to mank around with
  322.          * it.  
  323.          */
  324.         peername = strdup(inpeername);
  325.         if (peername == NULL) {
  326.             return 0;
  327.         }
  328.         for (cp = peername; *cp && isdigit((int) *cp); cp++);
  329.         if (!*cp && atoi(peername) != 0) {
  330.             /*
  331.              * Okay, it looks like JUST a port number.  
  332.              */
  333.             DEBUGMSGTL(("netsnmp_sockaddr_in6", "totally numeric: %dn",
  334.                         atoi(peername)));
  335.             addr->sin6_port = htons(atoi(peername));
  336.             goto resolved;
  337.         }
  338.         /*
  339.          * See if it is an IPv6 address, which covered with square brankets
  340.          * with an appended :port.  
  341.          */
  342.         if (*peername == '[') {
  343.             cp = strchr(peername, ']');
  344.             if (cp != NULL) {
  345.       /*
  346.        * See if it is an IPv6 link-local address with interface
  347.        * name as <zone_id>, like fe80::1234%eth0.
  348.        * Please refer to the internet draft, IPv6 Scoped Address Architecture
  349.        * http://www.ietf.org/internet-drafts/draft-ietf-ipngwg-scoping-arch-04.txt
  350.        *
  351.        */
  352.         char *scope_id;
  353. #ifdef HAVE_IF_NAMETOINDEX
  354.         unsigned int if_index = 0;
  355. #endif
  356.                 *cp = '';
  357. scope_id = strchr(peername + 1, '%');
  358. if (scope_id != NULL) {
  359.     *scope_id = '';
  360. #ifdef HAVE_IF_NAMETOINDEX
  361.     if_index = if_nametoindex(scope_id + 1);
  362. #endif
  363. }
  364.                 if (*(cp + 1) == ':') {
  365.                     if (atoi(cp + 2) != 0 &&
  366.                         inet_pton(AF_INET6, peername + 1,
  367.                                   (void *) &(addr->sin6_addr))) {
  368.                         DEBUGMSGTL(("netsnmp_sockaddr_in6",
  369.                                     "IPv6 address with port suffix :%dn",
  370.                                     atoi(cp + 2)));
  371.                         addr->sin6_port = htons(atoi(cp + 2));
  372. #ifdef HAVE_IF_NAMETOINDEX
  373.                         addr->sin6_scope_id = if_index;
  374. #endif
  375.                         goto resolved;
  376.                     }
  377.                 } else {
  378.                     if (inet_pton
  379.                         (AF_INET6, peername + 1,
  380.                          (void *) &(addr->sin6_addr))) {
  381.                         DEBUGMSGTL(("netsnmp_sockaddr_in6",
  382.                                     "IPv6 address with square branketsn"));
  383.                         addr->sin6_port = htons(SNMP_PORT);
  384. #ifdef HAVE_IF_NAMETOINDEX
  385.                         addr->sin6_scope_id = if_index;
  386. #endif
  387.                         goto resolved;
  388.                     }
  389.                 }
  390. if (scope_id != NULL) {
  391.   *scope_id = '%';
  392. }
  393. *cp = ']';
  394.             }
  395.         }
  396.         cp = strrchr(peername, ':');
  397.         if (cp != NULL) {
  398.     char *scope_id;
  399. #ifdef HAVE_IF_NAMETOINDEX
  400.     unsigned int if_index = 0;
  401. #endif
  402.     *cp = '';
  403.     scope_id = strchr(peername + 1, '%');
  404.     if (scope_id != NULL) {
  405.         *scope_id = '';
  406. #ifdef HAVE_IF_NAMETOINDEX
  407.         if_index = if_nametoindex(scope_id + 1);
  408. #endif
  409.     }
  410.             if (atoi(cp + 1) != 0 &&
  411.                 inet_pton(AF_INET6, peername,
  412.                           (void *) &(addr->sin6_addr))) {
  413.                 DEBUGMSGTL(("netsnmp_sockaddr_in6",
  414.                             "IPv6 address with port suffix :%dn",
  415.                             atoi(cp + 1)));
  416.                 addr->sin6_port = htons(atoi(cp + 1));
  417. #ifdef HAVE_IF_NAMETOINDEX
  418.                 addr->sin6_scope_id = if_index;
  419. #endif
  420.                 goto resolved;
  421.             }
  422.     if (scope_id != NULL) {
  423.       *scope_id = '%';
  424.     }
  425.             *cp = ':';
  426.         }
  427.         /*
  428.          * See if it is JUST an IPv6 address.  
  429.          */
  430.         if (inet_pton(AF_INET6, peername, (void *) &(addr->sin6_addr))) {
  431.             DEBUGMSGTL(("netsnmp_sockaddr_in6", "just IPv6 addressn"));
  432.             goto resolved;
  433.         }
  434.         /*
  435.          * Well, it must be a hostname then, possibly with an appended :port.
  436.          * Sort that out first.  
  437.          */
  438.         cp = strrchr(peername, ':');
  439.         if (cp != NULL) {
  440.             *cp = '';
  441.             if (atoi(cp + 1) != 0) {
  442.                 DEBUGMSGTL(("netsnmp_sockaddr_in6",
  443.                             "hostname(?) with port suffix :%dn",
  444.                             atoi(cp + 1)));
  445.                 addr->sin6_port = htons(atoi(cp + 1));
  446.             } else {
  447.                 /*
  448.                  * No idea, looks bogus but we might as well pass the full thing to
  449.                  * the name resolver below.  
  450.                  */
  451.                 *cp = ':';
  452.                 DEBUGMSGTL(("netsnmp_sockaddr_in6",
  453.                             "hostname(?) with embedded ':'?n"));
  454.             }
  455.             /*
  456.              * Fall through.  
  457.              */
  458.         }
  459. #if HAVE_GETADDRINFO
  460.         memset(&hint, 0, sizeof hint);
  461.         hint.ai_flags = 0;
  462.         hint.ai_family = PF_INET6;
  463.         hint.ai_socktype = SOCK_DGRAM;
  464.         hint.ai_protocol = 0;
  465.         err = getaddrinfo(peername, NULL, &hint, &addrs);
  466.         if (err != 0) {
  467.             snmp_log(LOG_ERR, "getaddrinfo: %s %sn", peername,
  468.                      gai_strerror(err));
  469.             free(peername);
  470.             return 0;
  471.         }
  472.         if (addrs != NULL) {
  473.         DEBUGMSGTL(("netsnmp_sockaddr_in6", "hostname (resolved okay)n"));
  474.         memcpy(&addr->sin6_addr,
  475.                &((struct sockaddr_in6 *) addrs->ai_addr)->sin6_addr,
  476.                sizeof(struct in6_addr));
  477. freeaddrinfo(addrs);
  478.         }
  479. else {
  480.         DEBUGMSGTL(("netsnmp_sockaddr_in6", "Failed to resolve IPv6 hostnamen"));
  481. }
  482. #elif HAVE_GETIPNODEBYNAME
  483.         hp = getipnodebyname(peername, AF_INET6, 0, &err);
  484.         if (hp == NULL) {
  485.             DEBUGMSGTL(("netsnmp_sockaddr_in6",
  486.                         "hostname (couldn't resolve = %d)n", err));
  487.             free(peername);
  488.             return 0;
  489.         }
  490.         DEBUGMSGTL(("netsnmp_sockaddr_in6", "hostname (resolved okay)n"));
  491.         memcpy(&(addr->sin6_addr), hp->h_addr, hp->h_length);
  492. #elif HAVE_GETHOSTBYNAME
  493.         hp = gethostbyname(peername);
  494.         if (hp == NULL) {
  495.             DEBUGMSGTL(("netsnmp_sockaddr_in6",
  496.                         "hostname (couldn't resolve)n"));
  497.             free(peername);
  498.             return 0;
  499.         } else {
  500.             if (hp->h_addrtype != AF_INET6) {
  501.                 DEBUGMSGTL(("netsnmp_sockaddr_in6",
  502.                             "hostname (not AF_INET6!)n"));
  503.                 free(peername);
  504.                 return 0;
  505.             } else {
  506.                 DEBUGMSGTL(("netsnmp_sockaddr_in6",
  507.                             "hostname (resolved okay)n"));
  508.                 memcpy(&(addr->sin6_addr), hp->h_addr, hp->h_length);
  509.             }
  510.         }
  511. #else                           /*HAVE_GETHOSTBYNAME */
  512.         /*
  513.          * There is no name resolving function available.  
  514.          */
  515.         snmp_log(LOG_ERR,
  516.                  "no getaddrinfo()/getipnodebyname()/gethostbyname()n");
  517.         free(peername);
  518.         return 0;
  519. #endif                          /*HAVE_GETHOSTBYNAME */
  520.     } else {
  521.         DEBUGMSGTL(("netsnmp_sockaddr_in6", "NULL peername"));
  522.         return 0;
  523.     }
  524.   resolved:
  525.     DEBUGMSGTL(("netsnmp_sockaddr_in6", "return { AF_INET6, [%s]:%hu }n",
  526.                 inet_ntop(AF_INET6, &addr->sin6_addr, debug_addr,
  527.                           sizeof(debug_addr)), ntohs(addr->sin6_port)));
  528.     free(peername);
  529.     return 1;
  530. }
  531. /*
  532.  * int
  533.  * inet_make_mask_addr( int pf, void *dst, int masklength )
  534.  *      convert from bit length specified masklength to network format, 
  535.  *      which fills 1 from until specified bit length.
  536.  *      dst is usally the structer of sockaddr_in or sockaddr_in6. 
  537.  *      makelength must be an interger from 0 to 32 if pf is PF_INET,
  538.  *      or from 0 to 128 if pf is PF_INET6.
  539.  * return:
  540.  *      0 if the input data, masklength was valid for 
  541.  *      the specified protocol family.
  542.  *      -1 if the the input data wasn't valid.
  543.  */
  544. int
  545. inet_make_mask_addr(int pf, void *dst, int masklength)
  546. {
  547.     unsigned long   Mask = 0;
  548.     int             maskBit = 0x80000000L;
  549.     unsigned char   mask = 0;
  550.     unsigned char   maskbit = 0x80L;
  551.     int             i, j, jj;
  552.     switch (pf) {
  553.     case PF_INET:
  554.         if (masklength < 0 || masklength > 32)
  555.             return -1;
  556.         ((struct in_addr *) dst)->s_addr = 0;
  557.         while (masklength--) {
  558.             Mask |= maskBit;
  559.             maskBit >>= 1;
  560.         }
  561.         ((struct in_addr *) dst)->s_addr = htonl(Mask);
  562.         break;
  563.     case PF_INET6:
  564.         if (masklength < 0 || masklength > 128)
  565.             return -1;
  566.         for (i = 0; i < 16; i++) {
  567.             (*(u_char *) (&((struct in6_addr *) dst)->s6_addr[i])) = 0x00;
  568.         }
  569.         j = (int) masklength / 8;
  570.         jj = masklength % 8;
  571.         for (i = 0; i < j; i++) {
  572.             (*(u_char *) (&((struct in6_addr *) dst)->s6_addr[i])) = 0xff;
  573.         }
  574.         while (jj--) {
  575.             mask |= maskbit;
  576.             maskbit >>= 1;
  577.         }
  578.         (*(u_char *) (&((struct in6_addr *) dst)->s6_addr[j])) = mask;
  579.         break;
  580.     default:
  581.         return -1;              /* unsupported protocol family */
  582.     }
  583.     return 0;
  584. }
  585. /*
  586.  * int
  587.  * inet_addr_complement( int pf, void *src, void *dst )
  588.  *      convert from src to dst, which all bits 
  589.  *      are bit-compliment of src.
  590.  *      Src, dst are ususally sockaddr_in or sockaddr_in6.  
  591.  * return:
  592.  *      0 if the input data src and dst have the same size
  593.  *      -1 if the the input data wasn't valid.
  594.  */
  595. int
  596. inet_addr_complement(int pf, void *src, void *dst)
  597. {
  598.     int             i;
  599.     if (sizeof(src) != sizeof(dst))
  600.         return -1;
  601.     switch (pf) {
  602.     case PF_INET:
  603.         ((struct in_addr *) dst)->s_addr =
  604.             ~((struct in_addr *) src)->s_addr;
  605.         break;
  606.     case PF_INET6:
  607.         for (i = 0; i < 16; i++) {
  608.             (*(u_char *) (&((struct in6_addr *) dst)->s6_addr[i])) =
  609.                 (~(*(u_char *) (&((struct in6_addr *) src)->s6_addr[i])))
  610.                 & 0xff;
  611.         }
  612.         break;
  613.     default:
  614.         return -1;
  615.     }
  616.     return 0;
  617. }
  618. /*
  619.  * int
  620.  * inet_addr_and( int pf, void *src1, void *src2, void *dst) 
  621.  *      take AND operation on src1 and src2, and output the result to dst.
  622.  *      Src1, src2, and dst are ususally sockaddr_in or sockaddr_in6.  
  623.  * return:
  624.  *      0 if the input data src and dst have the same size
  625.  *      -1 if the the input data are not the same size
  626.  */
  627. int
  628. inet_addr_and(int pf, void *src1, void *src2, void *dst)
  629. {
  630.     int             i;
  631.     if (sizeof(src1) != sizeof(src2) || sizeof(src2) != sizeof(dst))
  632.         return -1;
  633.     switch (pf) {
  634.     case PF_INET:
  635.         ((struct in_addr *) dst)->s_addr =
  636.             ((struct in_addr *) src1)->s_addr & ((struct in_addr *) src2)->
  637.             s_addr;
  638.         break;
  639.     case PF_INET6:
  640.         for (i = 0; i < 16; i++) {
  641.             (*(u_char *) (&((struct in6_addr *) dst)->s6_addr[i])) =
  642.                 (*(u_char *) (&((struct in6_addr *) src1)->s6_addr[i])) &
  643.                 (*(u_char *) (&((struct in6_addr *) src2)->s6_addr[i]));
  644.         }
  645.         break;
  646.     default:
  647.         return -1;
  648.     }
  649.     return 0;
  650. }
  651. /*
  652.  * int
  653.  * inet_addrs_consistence (int pf, void *net, void *mask ) 
  654.  *      This function checks if the network address net is consistent
  655.  *      with the netmask address, mask.
  656.  *      Net and mask are ususally sockaddr_in or sockaddr_in6.  
  657.  * Note:
  658.  *      Must spefiey protocol family in pf.
  659.  * return:
  660.  *      0 if there is no consistence with address "net" and "mask".
  661.  *      -1 if network address is inconsistent with netmask address, for 
  662.  *      instance, network address is 192.168.0.128 in spite of netmask, 
  663.  *      which is 255.255.255.0. 
  664.  *      The case that the size of net and mask are different also returns -1.
  665.  */
  666. int
  667. inet_addrs_consistence(int pf, void *net, void *mask)
  668. {
  669.     struct sockaddr_in *tmp, *dst;
  670.     struct sockaddr_in6 *tmp6, *dst6;
  671.     int             ret;
  672.     switch (pf) {
  673.     case PF_INET:
  674.         tmp = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
  675.         if (!tmp) {
  676.             config_perror("Resource failure in inet_addr_consistence()");
  677.             return -1;
  678.         }
  679.         memset(tmp, 0, sizeof(*tmp));
  680.         tmp->sin_family = PF_INET;
  681.         if (inet_addr_complement
  682.             (PF_INET, (struct in_addr *) mask, &tmp->sin_addr) != 0) {
  683.             config_perror("Fail in function of inet_addr_complement()");
  684.             free(tmp);
  685.             return -1;
  686.         }
  687.         dst = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
  688.         if (!dst) {
  689.             config_perror("Resource failure in inet_addr_consistence()");
  690.             free(tmp);
  691.             return -1;
  692.         }
  693.         memset(dst, 0, sizeof(*dst));
  694.         dst->sin_family = PF_INET;
  695.         if (inet_addr_and
  696.             (PF_INET, (struct in_addr *) net, &tmp->sin_addr,
  697.              &dst->sin_addr) != 0) {
  698.             config_perror("Fail in function of inet_addr_and()");
  699.             free(dst);
  700.             free(tmp);
  701.             return -1;
  702.         }
  703.         ret = ((dst->sin_addr.s_addr == INADDR_ANY) ? 0 : -1);
  704.         free(dst);
  705.         free(tmp);
  706.         break;
  707.     case PF_INET6:
  708.         tmp6 = (struct sockaddr_in6 *) malloc(sizeof(struct sockaddr_in6));
  709.         if (!tmp6) {
  710.             config_perror("Resource failure in inet_addr_consistence()");
  711.             return -1;
  712.         }
  713.         memset(tmp6, 0, sizeof(*tmp6));
  714.         tmp6->sin6_family = PF_INET6;
  715.         if (inet_addr_complement
  716.             (PF_INET6, (struct in6_addr *) mask, &tmp6->sin6_addr) != 0) {
  717.             config_perror("Fail in function of inet_addr_complement()");
  718.             free(tmp6);
  719.             return -1;
  720.         }
  721.         dst6 = (struct sockaddr_in6 *) malloc(sizeof(struct sockaddr_in6));
  722.         if (!dst6) {
  723.             config_perror("Resource failure in inet_addr_consistence()");
  724.             free(tmp6);
  725.             return -1;
  726.         }
  727.         memset(dst6, 0, sizeof(*dst6));
  728.         dst6->sin6_family = PF_INET6;
  729.         if (inet_addr_and
  730.             (PF_INET6, (struct in6_addr *) net, &tmp6->sin6_addr,
  731.              &dst6->sin6_addr)) {
  732.             config_perror("Fail in function of inet_addr_and()");
  733.             free(dst6);
  734.             free(tmp6);
  735.             return -1;
  736.         }
  737.         ret = (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) == 1 ? 0 : -1);
  738.         free(dst6);
  739.         free(tmp6);
  740.         break;
  741.     default:
  742.         return -1;
  743.     }
  744.     return ret;
  745. }
  746. /*
  747.  * int
  748.  * masked_address_are_equal (pf, from, mask, network) 
  749.  *      This function takes AND operation on address "from" and "mask",
  750.  *      and check the result is equal to address "network". 
  751.  *      From, net and mask are ususally sockaddr_in or sockaddr_in6.  
  752.  * Note:
  753.  *      Must spefiey protocol family in pf.
  754.  * return:
  755.  *      0 if address "from" masked by address "mask" is eqaul to 
  756.  *      address "network". 
  757.  *      -1 if address "from" masked by address "mask" isn't eqaul to 
  758.  *      address "network". For instance, address "from" is 
  759.  *       192.168.0.129 and "mask" is 255.255.255.128. Then, masked 
  760.  *      address is 192.168.0.128. If address "network" is 192.168.0.128,
  761.  *      return 0, otherwise -1.
  762.  *      Also retunn -1 if each address family of from, mask, network
  763.  *      isn't the same.
  764.  */
  765. int
  766. masked_address_are_equal(int af, struct sockaddr_storage *from,
  767.                          struct sockaddr_storage *mask,
  768.                          struct sockaddr_storage *network)
  769. {
  770.     struct sockaddr_storage ss;
  771.     memset(&ss, 0, sizeof(ss));
  772.     switch (af) {
  773.     case PF_INET:
  774.         if (mask->ss_family != PF_INET || network->ss_family != PF_INET) {
  775.             return -1;
  776.         }
  777.         ss.ss_family = PF_INET;
  778.         inet_addr_and(PF_INET,
  779.                       &((struct sockaddr_in *) from)->sin_addr,
  780.                       &((struct sockaddr_in *) mask)->sin_addr,
  781.                       &((struct sockaddr_in *) &ss)->sin_addr);
  782.         if (((struct sockaddr_in *) &ss)->sin_addr.s_addr ==
  783.             ((struct sockaddr_in *) network)->sin_addr.s_addr) {
  784.             return 0;
  785.         } else {
  786.             return -1;
  787.         }
  788.         break;
  789.     case PF_INET6:
  790.         if (mask->ss_family != PF_INET6 || network->ss_family != PF_INET6) {
  791.             return -1;
  792.         }
  793.         ss.ss_family = PF_INET6;
  794.         inet_addr_and(PF_INET6,
  795.                       &((struct sockaddr_in6 *) from)->sin6_addr,
  796.                       &((struct sockaddr_in6 *) mask)->sin6_addr,
  797.                       &((struct sockaddr_in6 *) &ss)->sin6_addr);
  798. #ifndef IN6_ARE_ADDR_EQUAL
  799. #define IN6_ARE_ADDR_EQUAL(a,b) IN6_ADDR_EQUAL(a,b)
  800. #endif
  801.         if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *) &ss)->sin6_addr,
  802.                                &((struct sockaddr_in6 *) network)->
  803.                                sin6_addr) == 1) {
  804.             return 0;
  805.         } else {
  806.             return -1;
  807.         }
  808.         break;
  809.     default:
  810.         return -1;
  811.     }
  812. }
  813. #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
  814. /*
  815.  * The following functions provide the "com2sec6" configuration token
  816.  * functionality for compatibility.  
  817.  */
  818. #define EXAMPLE_NETWORK       "NETWORK"
  819. #define EXAMPLE_COMMUNITY     "COMMUNITY"
  820. typedef struct _com2Sec6Entry {
  821.     char            community[VACMSTRINGLEN];
  822.     struct sockaddr_in6 network;
  823.     struct sockaddr_in6 mask;
  824.     char            secName[VACMSTRINGLEN];
  825.     char            contextName[VACMSTRINGLEN];
  826.     struct _com2Sec6Entry *next;
  827. } com2Sec6Entry;
  828. com2Sec6Entry  *com2Sec6List = NULL, *com2Sec6ListLast = NULL;
  829. void
  830. memmove_com2Sec6Entry(com2Sec6Entry * c,
  831.                       char *secName,
  832.                       char *community,
  833.                       struct sockaddr_in6 net, struct sockaddr_in6 mask,
  834.                       char *contextName)
  835. {
  836.     snprintf(c->secName, strlen(secName) + 1, "%s", secName);
  837.     snprintf(c->contextName, strlen(contextName) + 1, "%s", contextName);
  838.     snprintf(c->community, strlen(community) + 1, "%s", community);
  839.     memmove(&c->network, &net, sizeof(net));
  840.     memmove(&c->mask, &mask, sizeof(mask));
  841.     c->next = NULL;
  842. }
  843. void
  844. netsnmp_udp6_parse_security(const char *token, char *param)
  845. {
  846.     char            secName[VACMSTRINGLEN];
  847.     char            contextName[VACMSTRINGLEN];
  848.     char            community[VACMSTRINGLEN];
  849.     char            source[VACMSTRINGLEN];
  850.     char           *cp = NULL, *strnetwork = NULL, *strmask = NULL;
  851.     com2Sec6Entry  *e = NULL;
  852.     struct sockaddr_in6 net, mask;
  853.     struct sockaddr_in tmp;
  854.     memset(&net, 0, sizeof(net));
  855.     memset(&mask, 0, sizeof(mask));
  856.     memset(&tmp, 0, sizeof(tmp));
  857.     net.sin6_family = AF_INET6;
  858.     mask.sin6_family = AF_INET6;
  859.     tmp.sin_family = AF_INET;
  860.     /*
  861.      * Get security, source address/netmask and community strings.  
  862.      */
  863.     cp = copy_nword( param, secName, sizeof(secName));
  864.     if (strcmp(secName, "-Cn") == 0) {
  865.         if (!cp) {
  866.             config_perror("missing CONTEXT_NAME parameter");
  867.             return;
  868.         }
  869.         cp = copy_nword( cp, contextName, sizeof(contextName));
  870.         cp = copy_nword( cp, secName, sizeof(secName));
  871.     } else {
  872.         contextName[0] = '';
  873.     }
  874.     if (secName[0] == '') {
  875.         config_perror("missing NAME parameter");
  876.         return;
  877.     } else if (strlen(secName) > (VACMSTRINGLEN - 1)) {
  878.         config_perror("security name too long");
  879.         return;
  880.     }
  881.     cp = copy_nword( cp, source, sizeof(source));
  882.     if (source[0] == '') {
  883.         config_perror("missing SOURCE parameter");
  884.         return;
  885.     } else if (strncmp(source, EXAMPLE_NETWORK, strlen(EXAMPLE_NETWORK)) ==
  886.                0) {
  887.         config_perror("example config NETWORK not properly configured");
  888.         return;
  889.     }
  890.     cp = copy_nword( cp, community, sizeof(community));
  891.     if (community[0] == '') {
  892.         config_perror("missing COMMUNITY parametern");
  893.         return;
  894.     } else
  895.         if (strncmp
  896.             (community, EXAMPLE_COMMUNITY, strlen(EXAMPLE_COMMUNITY))
  897.             == 0) {
  898.         config_perror("example config COMMUNITY not properly configured");
  899.         return;
  900.     } else if (strlen(community) > (VACMSTRINGLEN - 1)) {
  901.         config_perror("community name too long");
  902.         return;
  903.     }
  904.     /*
  905.      * Process the source address/netmask string.  
  906.      */
  907.     cp = strchr(source, '/');
  908.     if (cp != NULL) {
  909.         /*
  910.          * Mask given.  
  911.          */
  912.         *cp = '';
  913.         strmask = cp + 1;
  914.     }
  915.     /*
  916.      * Deal with the network part first.  
  917.      */
  918.     if ((strcmp(source, "default") == 0) || (strcmp(source, "::") == 0)) {
  919.         strnetwork = strdup("0::0");
  920.         strmask = strdup("0::0");
  921.         inet_pton(AF_INET6, strnetwork, &net.sin6_addr);
  922.         inet_pton(AF_INET6, strmask, &mask.sin6_addr);
  923.         e = (com2Sec6Entry *) malloc(sizeof(com2Sec6Entry));
  924.         if (e == NULL) {
  925.             config_perror("memory error");
  926.             return;
  927.         }
  928.         /*
  929.          * Everything is okay.  Copy the parameters to the structure allocated
  930.          * above and add it to END of the list.  
  931.          */
  932.         if (strmask != NULL && strnetwork != NULL) {
  933.             DEBUGMSGTL(("netsnmp_udp6_parse_security",
  934.                         "<"%s", %s/%s> => "%s"n", community,
  935.                         strnetwork, strmask, secName));
  936.             free(strmask);
  937.             free(strnetwork);
  938.         } else {
  939.             DEBUGMSGTL(("netsnmp_udp6_parse_security",
  940.                         "Couldn't allocate enough memoryn"));
  941.         }
  942.         memmove_com2Sec6Entry(e, secName, community, net, mask, contextName);
  943.         if (com2Sec6ListLast != NULL) {
  944.             com2Sec6ListLast->next = e;
  945.             com2Sec6ListLast = e;
  946.         } else {
  947.             com2Sec6ListLast = com2Sec6List = e;
  948.         }
  949.     } else {
  950.         /*
  951.          * Try interpreting as IPv6 address.  
  952.          */
  953.         if (inet_pton(AF_INET6, source, &net.sin6_addr) == 1) {
  954.             if (strmask == NULL || *strmask == '') {
  955.                 inet_make_mask_addr(PF_INET6, &mask.sin6_addr, 128);
  956.             } else {
  957.                 if (strchr(strmask, ':')) {
  958.                     if (inet_pton(PF_INET6, strmask, &net.sin6_addr) != 1) {
  959.                         config_perror("bad mask");
  960.                         return;
  961.                     }
  962.                 } else {
  963.                     if (inet_make_mask_addr
  964.                         (PF_INET6, &mask.sin6_addr, atoi(strmask)) != 0) {
  965.                         config_perror("bad mask");
  966.                         return;
  967.                     }
  968.                 }
  969.             }
  970.             /*
  971.              * Check that the network and mask are consistent.  
  972.              */
  973.             if (inet_addrs_consistence
  974.                 (PF_INET6, &net.sin6_addr, &mask.sin6_addr) != 0) {
  975.                 config_perror("source/mask mismatch");
  976.                 return;
  977.             }
  978.             e = (com2Sec6Entry *) malloc(sizeof(com2Sec6Entry));
  979.             if (e == NULL) {
  980.                 config_perror("memory error");
  981.                 return;
  982.             }
  983.             /*
  984.              * Everything is okay.  Copy the parameters to the structure allocated
  985.              * above and add it to END of the list.  
  986.              */
  987.             if (strmask != NULL && strnetwork != NULL) {
  988.                 DEBUGMSGTL(("netsnmp_udp6_parse_security",
  989.                             "<"%s", %s/%s> => "%s"n", community,
  990.                             strnetwork, strmask, secName));
  991.                 free(strmask);
  992.                 free(strnetwork);
  993.             } else {
  994.                 DEBUGMSGTL(("netsnmp_udp6_parse_security",
  995.                             "Couldn't allocate enough memoryn"));
  996.             }
  997.             memmove_com2Sec6Entry(e, secName, community, net, mask,
  998.                                   contextName);
  999.             if (com2Sec6ListLast != NULL) {
  1000.                 com2Sec6ListLast->next = e;
  1001.                 com2Sec6ListLast = e;
  1002.             } else {
  1003.                 com2Sec6ListLast = com2Sec6List = e;
  1004.             }
  1005. #if HAVE_GETADDRINFO
  1006.         } else {
  1007.             /*
  1008.              * Nope, Must be a hostname.  
  1009.              */
  1010.             struct addrinfo hints, *ai, *res;
  1011.             char            hbuf[NI_MAXHOST];
  1012.             int             gai_error;
  1013.             memset(&hints, 0, sizeof(hints));
  1014.             hints.ai_family = PF_INET6;
  1015.             hints.ai_socktype = SOCK_DGRAM;
  1016.             if ((gai_error = getaddrinfo(source, NULL, &hints, &res)) != 0) {
  1017.                 config_perror(gai_strerror(gai_error));
  1018.                 return;
  1019.             }
  1020.             for (ai = res; ai != NULL; ai = ai->ai_next) {
  1021.                 if (getnameinfo
  1022.                     (ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL,
  1023.                      0, NI_NUMERICHOST)) {
  1024.                     config_perror("getnameinfo failed");
  1025.                 }
  1026.                 memmove(ai->ai_addr, &net, sizeof(struct sockaddr_in6));
  1027.                 inet_make_mask_addr(AF_INET6, &mask.sin6_addr, 127);
  1028.                 e = (com2Sec6Entry *) malloc(sizeof(com2Sec6Entry));
  1029.                 if (e == NULL) {
  1030.                     config_perror("memory error");
  1031.                     return;
  1032.                 }
  1033.                 /*
  1034.                  * Everything is okay.  Copy the parameters to the structure allocated
  1035.                  * above and add it to END of the list.  
  1036.                  */
  1037.                 DEBUGMSGTL(("netsnmp_udp6_parse_security",
  1038.                             "<"%s", %s> => "%s"n", community, hbuf,
  1039.                             secName));
  1040.                 memmove_com2Sec6Entry(e, secName, community, net, mask,
  1041.                                       contextName);
  1042.                 if (com2Sec6ListLast != NULL) {
  1043.                     com2Sec6ListLast->next = e;
  1044.                     com2Sec6ListLast = e;
  1045.                 } else {
  1046.                     com2Sec6ListLast = com2Sec6List = e;
  1047.                 }
  1048.             }
  1049.             if (res != NULL)
  1050.                 freeaddrinfo(res);
  1051. #endif /* HAVE_GETADDRINFO */
  1052.         }
  1053.         /*
  1054.          * free(strnetwork); 
  1055.          */
  1056.     }
  1057. }
  1058. void
  1059. netsnmp_udp6_com2Sec6List_free(void)
  1060. {
  1061.     com2Sec6Entry  *e = com2Sec6List;
  1062.     while (e != NULL) {
  1063.         com2Sec6Entry  *tmp = e;
  1064.         e = e->next;
  1065.         free(tmp);
  1066.     }
  1067.     com2Sec6List = com2Sec6ListLast = NULL;
  1068. }
  1069. #endif /* support for community based SNMP */
  1070. void
  1071. netsnmp_udp6_agent_config_tokens_register(void)
  1072. {
  1073. #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
  1074.     register_app_config_handler("com2sec6", netsnmp_udp6_parse_security,
  1075.                                 netsnmp_udp6_com2Sec6List_free,
  1076.                                 "[-Cn CONTEXT] secName IPv6-network-address[/netmask] community");
  1077. #endif /* support for community based SNMP */
  1078. }
  1079. #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
  1080. /*
  1081.  * Return 0 if there are no com2sec entries, or return 1 if there ARE com2sec 
  1082.  * entries.  On return, if a com2sec entry matched the passed parameters,
  1083.  * then *secName points at the appropriate security name, or is NULL if the
  1084.  * parameters did not match any com2sec entry.  
  1085.  */
  1086. int
  1087. netsnmp_udp6_getSecName(void *opaque, int olength,
  1088.                         const char *community,
  1089.                         int community_len, char **secName, char **contextName)
  1090. {
  1091.     com2Sec6Entry  *c;
  1092.     struct sockaddr_in6 *from = (struct sockaddr_in6 *) opaque;
  1093.     char           *ztcommunity = NULL;
  1094.     char            str6[INET6_ADDRSTRLEN];
  1095.     if (secName != NULL) {
  1096.         *secName = NULL;  /* Haven't found anything yet */
  1097.     }
  1098.     /*
  1099.      * Special case if there are NO entries (as opposed to no MATCHING
  1100.      * entries).  
  1101.      */
  1102.     if (com2Sec6List == NULL) {
  1103.         DEBUGMSGTL(("netsnmp_udp6_getSecName", "no com2sec entriesn"));
  1104.         return 0;
  1105.     }
  1106.     /*
  1107.      * If there is no IPv6 source address, 
  1108.      * then there can be no valid security name.  
  1109.      */
  1110.     if (opaque == NULL || olength != sizeof(struct sockaddr_in6)
  1111.         || from->sin6_family != PF_INET6) {
  1112.         DEBUGMSGTL(("netsnmp_udp6_getSecName",
  1113.                     "no IPv6 source address in PDU?n"));
  1114.         return 1;
  1115.     }
  1116.     ztcommunity = (char *) malloc(community_len + 1);
  1117.     if (ztcommunity != NULL) {
  1118.         memcpy(ztcommunity, community, community_len);
  1119.         ztcommunity[community_len] = '';
  1120.     }
  1121.     inet_ntop(AF_INET6, &from->sin6_addr, str6, sizeof(str6));
  1122.     DEBUGMSGTL(("netsnmp_udp6_getSecName", "resolve <"%s", %s>n",
  1123.                 ztcommunity ? ztcommunity : "<malloc error>", str6));
  1124.     for (c = com2Sec6List; c != NULL; c = c->next) {
  1125.         DEBUGMSGTL(("netsnmp_udp6_getSecName",
  1126.                     "compare <"%s", 0x%032/0x%032x>", c->community,
  1127.                     c->network, c->mask));
  1128.         if ((community_len == (int)strlen(c->community)) &&
  1129.             (memcmp(community, c->community, community_len) == 0) &&
  1130.             (masked_address_are_equal(from->sin6_family,
  1131.                                       (struct sockaddr_storage *) from,
  1132.                                       (struct sockaddr_storage *) &c->mask,
  1133.                                       (struct sockaddr_storage *) &c->
  1134.                                       network) == 0)) {
  1135.             DEBUGMSG(("netsnmp_udp6_getSecName", "... SUCCESSn"));
  1136.             if (secName != NULL) {
  1137.                 *secName = c->secName;
  1138.                 *contextName = c->contextName;
  1139.             }
  1140.             break;
  1141.         }
  1142.         DEBUGMSG(("netsnmp_udp6_getSecName", "... nopen"));
  1143.     }
  1144.     if (ztcommunity != NULL) {
  1145.         free(ztcommunity);
  1146.     }
  1147.     return 1;
  1148. }
  1149. #endif /* support for community based SNMP */
  1150. netsnmp_transport *
  1151. netsnmp_udp6_create_tstring(const char *str, int local)
  1152. {
  1153.     struct sockaddr_in6 addr;
  1154.     if (netsnmp_sockaddr_in6(&addr, str, 0)) {
  1155.         return netsnmp_udp6_transport(&addr, local);
  1156.     } else {
  1157.         return NULL;
  1158.     }
  1159. }
  1160. /*
  1161.  * See:
  1162.  * 
  1163.  * http://www.ietf.org/internet-drafts/draft-ietf-ops-taddress-mib-01.txt
  1164.  * 
  1165.  * (or newer equivalent) for details of the TC which we are using for
  1166.  * the mapping here.  
  1167.  */
  1168. netsnmp_transport *
  1169. netsnmp_udp6_create_ostring(const u_char * o, size_t o_len, int local)
  1170. {
  1171.     struct sockaddr_in6 addr;
  1172.     if (o_len == 18) {
  1173.         memset((u_char *) & addr, 0, sizeof(struct sockaddr_in6));
  1174.         addr.sin6_family = AF_INET6;
  1175.         memcpy((u_char *) & (addr.sin6_addr.s6_addr), o, 16);
  1176.         addr.sin6_port = (o[16] << 8) + o[17];
  1177.         return netsnmp_udp6_transport(&addr, local);
  1178.     }
  1179.     return NULL;
  1180. }
  1181. void
  1182. netsnmp_udp6_ctor(void)
  1183. {
  1184.     udp6Domain.name = netsnmp_UDPIPv6Domain;
  1185.     udp6Domain.name_length = sizeof(netsnmp_UDPIPv6Domain) / sizeof(oid);
  1186.     udp6Domain.f_create_from_tstring = netsnmp_udp6_create_tstring;
  1187.     udp6Domain.f_create_from_ostring = netsnmp_udp6_create_ostring;
  1188.     udp6Domain.prefix = calloc(5, sizeof(char *));
  1189.     udp6Domain.prefix[0] = "udp6";
  1190.     udp6Domain.prefix[1] = "ipv6";
  1191.     udp6Domain.prefix[2] = "udpv6";
  1192.     udp6Domain.prefix[3] = "udpipv6";
  1193.     netsnmp_tdomain_register(&udp6Domain);
  1194. }
  1195. #else
  1196. #ifdef NETSNMP_DLL
  1197. /* need this hook for win32 MSVC++ DLL build */
  1198. void
  1199. netsnmp_udp6_agent_config_tokens_register(void)
  1200. { }
  1201. #endif
  1202. #endif /* SNMP_TRANSPORT_UDPIPV6_DOMAIN */