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

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <ctype.h>
  5. #include <errno.h>
  6. #if HAVE_STRING_H
  7. #include <string.h>
  8. #else
  9. #include <strings.h>
  10. #endif
  11. #if HAVE_STDLIB_H
  12. #include <stdlib.h>
  13. #endif
  14. #if HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #if HAVE_SYS_SOCKET_H
  18. #include <sys/socket.h>
  19. #endif
  20. #if HAVE_NETINET_IN_H
  21. #include <netinet/in.h>
  22. #endif
  23. #if HAVE_DMALLOC_H
  24. #include <dmalloc.h>
  25. #endif
  26. #include <net-snmp/types.h>
  27. #include <net-snmp/output_api.h>
  28. #include <net-snmp/config_api.h>
  29. #include <net-snmp/library/snmp_transport.h>
  30. #include <net-snmp/library/snmpIPXDomain.h>
  31. #define SNMP_IPX_DEFAULT_PORT 36879   /*  Specified in RFC 1420.  */
  32. static netsnmp_tdomain ipxDomain;
  33. /*
  34.  * Return a string representing the address in data, or else the "far end"
  35.  * address if data is NULL.  
  36.  */
  37. static char *
  38. netsnmp_ipx_fmtaddr(netsnmp_transport *t, void *data, int len)
  39. {
  40.     struct sockaddr_ipx *to = NULL;
  41.     if (data != NULL && len == sizeof(struct sockaddr_ipx)) {
  42.         to = (struct sockaddr_ipx *) data;
  43.     } else if (t != NULL && t->data != NULL) {
  44.         to = (struct sockaddr_ipx *) t->data;
  45.     }
  46.     if (to == NULL) {
  47.         return strdup("IPX: unknown");
  48.     } else {
  49.         char tmp[64];
  50.         sprintf(tmp, "IPX: %08X:%02X%02X%02X%02X%02X%02X/%hu",
  51.                 ntohl(to->sipx_network), to->sipx_node[0],
  52.                 to->sipx_node[1], to->sipx_node[2], to->sipx_node[3],
  53.                 to->sipx_node[4], to->sipx_node[5], ntohs(to->sipx_port));
  54.         return strdup(tmp);
  55.     }
  56. }
  57. /*
  58.  * You can write something into opaque that will subsequently get passed back 
  59.  * to your send function if you like.  For instance, you might want to
  60.  * remember where a PDU came from, so that you can send a reply there...  
  61.  */
  62. static int
  63. netsnmp_ipx_recv(netsnmp_transport *t, void *buf, int size,
  64.  void **opaque, int *olength)
  65. {
  66.     int rc = -1, fromlen = sizeof(struct sockaddr);
  67.     struct sockaddr *from;
  68.     if (t != NULL && t->sock >= 0) {
  69.         from = (struct sockaddr *)malloc(sizeof(struct sockaddr_ipx));
  70.         if (from == NULL) {
  71.             *opaque = NULL;
  72.             *olength = 0;
  73.             return -1;
  74.         } else {
  75.             memset(from, 0, fromlen);
  76.         }
  77. while (rc < 0) {
  78.   rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
  79.   if (rc < 0 && errno != EINTR) {
  80.     break;
  81.   }
  82. }
  83.         if (rc >= 0) {
  84.             char *str = netsnmp_ipx_fmtaddr(NULL, from, fromlen);
  85.             DEBUGMSGTL(("netsnmp_ipx","recvfrom fd %d got %d bytes(from %s)n",
  86. t->sock, rc, str));
  87.             free(str);
  88.         } else {
  89.             DEBUGMSGTL(("netsnmp_ipx", "recvfrom fd %d err %d ("%s")n",
  90.                         t->sock, errno, strerror(errno)));
  91.         }
  92.         *opaque = (void *) from;
  93.         *olength = sizeof(struct sockaddr_ipx);
  94.     }
  95.     return rc;
  96. }
  97. static int
  98. netsnmp_ipx_send(netsnmp_transport *t, void *buf, int size,
  99.  void **opaque, int *olength)
  100. {
  101.     int rc = -1;
  102.     struct sockaddr *to = NULL;
  103.     if (opaque != NULL && *opaque != NULL &&
  104. *olength == sizeof(struct sockaddr_ipx)) {
  105.         to = (struct sockaddr *) (*opaque);
  106.     } else if (t != NULL && t->data != NULL &&
  107.                t->data_length == sizeof(struct sockaddr_ipx)) {
  108.         to = (struct sockaddr *) (t->data);
  109.     }
  110.     if (to != NULL && t != NULL && t->sock >= 0) {
  111.         char *str = netsnmp_ipx_fmtaddr(NULL, (void *)to,
  112. sizeof(struct sockaddr_ipx));
  113.         DEBUGMSGTL(("netsnmp_ipx", "send %d bytes from %p to %s on fd %dn",
  114.                     size, buf, str, t->sock));
  115.         free(str);
  116. while (rc < 0) {
  117.     rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
  118.     if (rc < 0 && errno != EINTR) {
  119. break;
  120.     }
  121. }
  122.     }
  123.     return rc;
  124. }
  125. static int
  126. netsnmp_ipx_close(netsnmp_transport *t)
  127. {
  128.     int rc = -1;
  129.     if (t->sock >= 0) {
  130. #ifndef HAVE_CLOSESOCKET
  131.         rc = close(t->sock);
  132. #else
  133.         rc = closesocket(t->sock);
  134. #endif
  135.         t->sock = -1;
  136.     }
  137.     return rc;
  138. }
  139. /*
  140.  * Open a IPX-based transport for SNMP.  Local is TRUE if addr is the local
  141.  * address to bind to (i.e. this is a server-type session); otherwise addr is 
  142.  * the remote address to send things to.  
  143.  */
  144. netsnmp_transport *
  145. netsnmp_ipx_transport(struct sockaddr_ipx *addr, int local)
  146. {
  147.     netsnmp_transport *t = NULL;
  148.     int             rc = 0;
  149.     char           *str = NULL;
  150.     if (addr == NULL || addr->sipx_family != AF_IPX) {
  151.         return NULL;
  152.     }
  153.     t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
  154.     if (t == NULL) {
  155.         return NULL;
  156.     }
  157.     str = netsnmp_ipx_fmtaddr(NULL, (void *)addr, 
  158.  sizeof(struct sockaddr_ipx));
  159.     DEBUGMSGTL(("netsnmp_ipx", "open %s %sn", local ? "local" : "remote",
  160.                 str));
  161.     free(str);
  162.     memset(t, 0, sizeof(netsnmp_transport));
  163.     t->domain = netsnmpIPXDomain;
  164.     t->domain_length = netsnmpIPXDomain_len;
  165.     t->sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
  166.     if (t->sock < 0) {
  167.         netsnmp_transport_free(t);
  168.         return NULL;
  169.     }
  170.     if (local) {
  171.         t->local = malloc(12);
  172.         if (t->local == NULL) {
  173.             netsnmp_transport_free(t);
  174.             return NULL;
  175.         }
  176.         memcpy(&(t->local[00]), (u_char *) & (addr->sipx_network), 4);
  177.         memcpy(&(t->local[04]), (u_char *) & (addr->sipx_node), 6);
  178.         memcpy(&(t->local[10]), (u_char *) & (addr->sipx_port), 2);
  179.         t->local_length = 12;
  180.         /*
  181.          * This session is inteneded as a server, so we must bind on to the
  182.          * given address (which may include a particular network and/or node
  183.          * address, but definitely includes a port number).
  184.          */
  185.         rc = bind(t->sock, (struct sockaddr *) addr,
  186.                   sizeof(struct sockaddr));
  187.         if (rc != 0) {
  188.             netsnmp_ipx_close(t);
  189.             netsnmp_transport_free(t);
  190.             return NULL;
  191.         }
  192.         t->data = NULL;
  193.         t->data_length = 0;
  194.     } else {
  195.         t->remote = malloc(12);
  196.         if (t->remote == NULL) {
  197.             netsnmp_transport_free(t);
  198.             return NULL;
  199.         }
  200.         memcpy(&(t->remote[00]), (u_char *) & (addr->sipx_network), 4);
  201.         memcpy(&(t->remote[04]), (u_char *) & (addr->sipx_node), 6);
  202.         memcpy(&(t->remote[10]), (u_char *) & (addr->sipx_port), 2);
  203.         t->remote_length = 12;
  204.         /*
  205.          * This is a client session.  Save the address in the
  206.          * transport-specific data pointer for later use by snmp_ipx_send.
  207.          */
  208.         t->data = malloc(sizeof(struct sockaddr_ipx));
  209.         if (t->data == NULL) {
  210.             netsnmp_transport_free(t);
  211.             return NULL;
  212.         }
  213.         memcpy(t->data, addr, sizeof(struct sockaddr_ipx));
  214.         t->data_length = sizeof(struct sockaddr_ipx);
  215.     }
  216.     /*
  217.      * Maximum size of an IPX PDU is 576 bytes including a 30-byte header.
  218.      * Ridiculous!  
  219.      */
  220.     t->msgMaxSize = 576 - 30;
  221.     t->f_recv     = netsnmp_ipx_recv;
  222.     t->f_send     = netsnmp_ipx_send;
  223.     t->f_close    = netsnmp_ipx_close;
  224.     t->f_accept   = NULL;
  225.     t->f_fmtaddr  = netsnmp_ipx_fmtaddr;
  226.     return t;
  227. }
  228. /*
  229.  * Attempt to parse a string of the form [%08x]:%12x[/%d] where the parts
  230.  * are the network number, the node address and the port in that order.  
  231.  */
  232. int
  233. netsnmp_sockaddr_ipx(struct sockaddr_ipx *addr, const char *peername)
  234. {
  235.     char           *cp = NULL;
  236.     unsigned int    network = 0, i = 0;
  237.     if (addr == NULL) {
  238.         return 0;
  239.     }
  240.     memset(addr, 0, sizeof(struct sockaddr_ipx));
  241.     DEBUGMSGTL(("netsnmp_sockaddr_ipx", "addr %p, peername "%s"n",
  242.                 addr, peername ? peername : "[NIL]"));
  243.     addr->sipx_family = AF_IPX;
  244.     addr->sipx_type = 4;        /*  Specified in RFC 1420.  */
  245.     if (peername == NULL) {
  246.         return 0;
  247.     }
  248.     /*
  249.      * Skip leading white space.  
  250.      */
  251.     while (*peername && isspace((int) *peername)) {
  252.         peername++;
  253.     }
  254.     if (!*peername) {
  255.         /*
  256.          * Completely blank address.  Let this mean "any network, any address,
  257.          * default SNMP port".  
  258.          */
  259.         addr->sipx_network = htonl(0);
  260.         for (i = 0; i < 6; i++) {
  261.             addr->sipx_node[i] = 0;
  262.         }
  263.         addr->sipx_port = htons(SNMP_IPX_DEFAULT_PORT);
  264.         return 1;
  265.     }
  266.     /*
  267.      * Try to get a leading network address.  
  268.      */
  269.     network = strtoul(peername, &cp, 16);
  270.     if (cp != peername) {
  271.         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "network parsed okayn"));
  272.         addr->sipx_network = htonl(network);
  273.         peername = cp;
  274.     } else {
  275.         DEBUGMSGTL(("netsnmp_sockaddr_ipx",
  276.                     "no network part of addressn"));
  277.         addr->sipx_network = htonl(0);
  278.     }
  279.     if (*peername == ':') {
  280.         /*
  281.          * Okay we are looking for a node number plus optionally a port here.  
  282.          */
  283.         int             node[6] = { 0, 0, 0, 0, 0, 0 }, rc = 0;
  284.         unsigned short  port = 0;
  285.         rc = sscanf(peername, ":%02X%02X%02X%02X%02X%02X/%hu",
  286.                     &node[0], &node[1], &node[2], &node[3], &node[4],
  287.                     &node[5], &port);
  288.         if (rc < 6) {
  289.             DEBUGMSGTL(("netsnmp_sockaddr_ipx",
  290.                         "no node -- fail (rc %d)n", rc));
  291.             return 0;
  292.         } else if (rc == 6) {
  293.             DEBUGMSGTL(("netsnmp_sockaddr_ipx", "node, no portn"));
  294.             for (i = 0; i < 6; i++) {
  295.                 addr->sipx_node[i] = node[i];
  296.             }
  297.             addr->sipx_port = htons(SNMP_IPX_DEFAULT_PORT);
  298.         } else if (rc == 7) {
  299.             DEBUGMSGTL(("netsnmp_sockaddr_ipx", "node and portn"));
  300.             for (i = 0; i < 6; i++) {
  301.                 addr->sipx_node[i] = node[i];
  302.             }
  303.             addr->sipx_port = htons(port);
  304.         }
  305.     } else if (*peername == '/') {
  306.         /*
  307.          * Okay we are just looking for a port number here.  
  308.          */
  309.         unsigned short  port = 0;
  310.         for (i = 0; i < 6; i++) {
  311.             addr->sipx_node[i] = 0;
  312.         }
  313.         if (sscanf(peername, "/%hu", &port) != 1) {
  314.             DEBUGMSGTL(("netsnmp_sockaddr_ipx", "no portn"));
  315.             addr->sipx_port = htons(SNMP_IPX_DEFAULT_PORT);
  316.         } else {
  317.             addr->sipx_port = htons(port);
  318.         }
  319.     } else {
  320.         return 0;
  321.     }
  322.     return 1;
  323. }
  324. netsnmp_transport *
  325. netsnmp_ipx_create_tstring(const char *str, int local)
  326. {
  327.     struct sockaddr_ipx addr;
  328.     if (netsnmp_sockaddr_ipx(&addr, str)) {
  329.         return netsnmp_ipx_transport(&addr, local);
  330.     } else {
  331.         return NULL;
  332.     }
  333. }
  334. netsnmp_transport *
  335. netsnmp_ipx_create_ostring(const u_char * o, size_t o_len, int local)
  336. {
  337.     struct sockaddr_ipx addr;
  338.     if (o_len == 12) {
  339.         addr.sipx_family = AF_IPX;
  340.         memcpy((u_char *) & (addr.sipx_network), &(o[00]), 4);
  341.         memcpy((u_char *) & (addr.sipx_node), &(o[04]), 6);
  342.         memcpy((u_char *) & (addr.sipx_port), &(o[10]), 2);
  343.         return netsnmp_ipx_transport(&addr, local);
  344.     }
  345.     return NULL;
  346. }
  347. void
  348. netsnmp_ipx_ctor(void)
  349. {
  350.     ipxDomain.name = netsnmpIPXDomain;
  351.     ipxDomain.name_length = netsnmpIPXDomain_len;
  352.     ipxDomain.prefix = calloc(2, sizeof(char *));
  353.     ipxDomain.prefix[0] = "ipx";
  354.     ipxDomain.f_create_from_tstring = netsnmp_ipx_create_tstring;
  355.     ipxDomain.f_create_from_ostring = netsnmp_ipx_create_ostring;
  356.     netsnmp_tdomain_register(&ipxDomain);
  357. }