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

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. #include <atm.h>
  21. #if HAVE_DMALLOC_H
  22. #include <dmalloc.h>
  23. #endif
  24. #include <net-snmp/types.h>
  25. #include <net-snmp/output_api.h>
  26. #include <net-snmp/config_api.h>
  27. #include <net-snmp/library/snmp_transport.h>
  28. #include <net-snmp/library/snmpAAL5PVCDomain.h>
  29. oid netsnmp_AAL5PVCDomain[10] = { ENTERPRISE_MIB, 3, 3, 3 };
  30. static netsnmp_tdomain aal5pvcDomain;
  31. /*
  32.  * Return a string representing the address in data, or else the "far end"
  33.  * address if data is NULL.  
  34.  */
  35. static char *
  36. netsnmp_aal5pvc_fmtaddr(netsnmp_transport *t, void *data, int len)
  37. {
  38.     struct sockaddr_atmpvc *to = NULL;
  39.     if (data != NULL && len == sizeof(struct sockaddr_atmpvc)) {
  40.         to = (struct sockaddr_atmpvc *) data;
  41.     } else if (t != NULL && t->data != NULL &&
  42.                t->data_length == sizeof(struct sockaddr_atmpvc)) {
  43.         to = (struct sockaddr_atmpvc *) t->data;
  44.     }
  45.     if (to == NULL) {
  46.         return strdup("AAL5 PVC: unknown");
  47.     } else {
  48.         char tmp[64];
  49.         sprintf(tmp, "AAL5 PVC: %hd.%hd.%d", to->sap_addr.itf,
  50.                 to->sap_addr.vpi, to->sap_addr.vci);
  51.         return strdup(tmp);
  52.     }
  53. }
  54. /*
  55.  * You can write something into opaque that will subsequently get passed back 
  56.  * to your send function if you like.  For instance, you might want to
  57.  * remember where a PDU came from, so that you can send a reply there...  
  58.  */
  59. static int
  60. netsnmp_aal5pvc_recv(netsnmp_transport *t, void *buf, int size,
  61.      void **opaque, int *olength)
  62. {
  63.     int rc = -1;
  64.     if (t != NULL && t->sock >= 0) {
  65. while (rc < 0) {
  66.     rc = recv(t->sock, buf, size, 0);
  67.     if (rc < 0 && errno != EINTR) {
  68. break;
  69.     }
  70. }
  71.         if (rc >= 0) {
  72.             char *str = netsnmp_aal5pvc_fmtaddr(t, NULL, 0);
  73.             DEBUGMSGTL(("netsnmp_aal5pvc",
  74. "recv on fd %d got %d bytes (from %s)n", t->sock,
  75.                         rc, str));
  76.             free(str);
  77.         } else {
  78.             DEBUGMSGTL(("netsnmp_aal5pvc", "recv on fd %d err %d ("%s")n", 
  79. t->sock, errno, strerror(errno)));
  80.         }
  81.         *opaque = NULL;
  82.         *olength = 0;
  83.     }
  84.     return rc;
  85. }
  86. static int
  87. netsnmp_aal5pvc_send(netsnmp_transport *t, void *buf, int size,
  88.                   void **opaque, int *olength)
  89. {
  90.     int rc = -1;
  91.     struct sockaddr *to = NULL;
  92.     if (opaque != NULL && *opaque != NULL &&
  93.         *olength == sizeof(struct sockaddr_atmpvc)) {
  94.         to = (struct sockaddr *) (*opaque);
  95.     } else if (t != NULL && t->data != NULL &&
  96.                t->data_length == sizeof(struct sockaddr_atmpvc)) {
  97.         to = (struct sockaddr *) (t->data);
  98.     }
  99.     if (to != NULL && t != NULL && t->sock >= 0) {
  100.         char *str = netsnmp_aal5pvc_fmtaddr(NULL, (void *)to,
  101.     sizeof(struct sockaddr_atmpvc));
  102.         DEBUGMSGTL(("netsnmp_aal5pvc","send %d bytes from %p to %s on fd %dn",
  103.     size, buf, str, t->sock));
  104.         free(str);
  105. while (rc < 0) {
  106.     rc = send(t->sock, buf, size, 0);
  107.     if (rc < 0 && errno != EINTR) {
  108. break;
  109.     }
  110. }
  111.     }
  112.     return rc;
  113. }
  114. static int
  115. netsnmp_aal5pvc_close(netsnmp_transport *t)
  116. {
  117.     int rc = -1;
  118.     if (t->sock >= 0) {
  119.         DEBUGMSGTL(("netsnmp_aal5pvc", "close fd %dn", t->sock));
  120. #ifndef HAVE_CLOSESOCKET
  121.         rc = close(t->sock);
  122. #else
  123.         rc = closesocket(t->sock);
  124. #endif
  125.         t->sock = -1;
  126.     }
  127.     return rc;
  128. }
  129. /*
  130.  * Open an AAL5 PVC transport for SNMP.  Local is TRUE if addr is the local 
  131.  * NSAP to bind to (i.e. this is a server-type session); otherwise addr is 
  132.  * the remote NSAP to send things to.  
  133.  */
  134. netsnmp_transport *
  135. netsnmp_aal5pvc_transport(struct sockaddr_atmpvc *addr, int local)
  136. {
  137.     char           *str = NULL;
  138.     struct atm_qos  qos;
  139.     netsnmp_transport *t = NULL;
  140.     if (addr == NULL || addr->sap_family != AF_ATMPVC) {
  141.         return NULL;
  142.     }
  143.     t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
  144.     if (t == NULL) {
  145.         return NULL;
  146.     }
  147.     str = netsnmp_aal5pvc_fmtaddr(NULL, (void *) addr,
  148.                                   sizeof(struct sockaddr_atmpvc));
  149.     DEBUGMSGTL(("netsnmp_aal5pvc", "open %s %sn", local ? "local" : "remote",
  150.                 str));
  151.     free(str);
  152.     memset(t, 0, sizeof(netsnmp_transport));
  153.     t->domain = netsnmp_AAL5PVCDomain;
  154.     t->domain_length =
  155.         sizeof(netsnmp_AAL5PVCDomain) / sizeof(netsnmp_AAL5PVCDomain[0]);
  156.     t->sock = socket(PF_ATMPVC, SOCK_DGRAM, 0);
  157.     if (t->sock < 0) {
  158.         DEBUGMSGTL(("netsnmp_aal5pvc","socket failed (%s)n",strerror(errno)));
  159.         netsnmp_transport_free(t);
  160.         return NULL;
  161.     }
  162.     DEBUGMSGTL(("netsnmp_aal5pvc", "fd %d openedn", t->sock));
  163.     /*
  164.      * Set up the QOS parameters.  
  165.      */
  166.     memset(&qos, 0, sizeof(struct atm_qos));
  167.     qos.aal = ATM_AAL5;
  168.     qos.rxtp.traffic_class = ATM_UBR;
  169.     qos.rxtp.max_sdu = SNMP_MAX_LEN;    /*  Hmm -- this is a bit small?  */
  170.     qos.txtp = qos.rxtp;
  171.     if (setsockopt(t->sock, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
  172.         DEBUGMSGTL(("netsnmp_aal5pvc", "setsockopt failed (%s)n",
  173.                     strerror(errno)));
  174.         netsnmp_aal5pvc_close(t);
  175.         netsnmp_transport_free(t);
  176.         return NULL;
  177.     }
  178.     if (local) {
  179.         t->local = malloc(8);
  180.         if (t->local == NULL) {
  181.             netsnmp_transport_free(t);
  182.             return NULL;
  183.         }
  184.         t->local[0] = (addr->sap_addr.itf & 0xff00) >> 8;
  185.         t->local[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
  186.         t->local[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
  187.         t->local[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
  188.         t->local[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
  189.         t->local[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
  190.         t->local[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
  191.         t->local[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
  192.         t->local_length = 8;
  193.         if (bind(t->sock, (struct sockaddr *) addr,
  194.                  sizeof(struct sockaddr_atmpvc)) < 0) {
  195.             DEBUGMSGTL(("netsnmp_aal5pvc", "bind failed (%s)n",
  196.                         strerror(errno)));
  197.             netsnmp_aal5pvc_close(t);
  198.             netsnmp_transport_free(t);
  199.             return NULL;
  200.         }
  201.     } else {
  202.         t->remote = malloc(8);
  203.         if (t->remote == NULL) {
  204.             netsnmp_transport_free(t);
  205.             return NULL;
  206.         }
  207.         t->remote[0] = (addr->sap_addr.itf & 0xff00) >> 8;
  208.         t->remote[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
  209.         t->remote[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
  210.         t->remote[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
  211.         t->remote[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
  212.         t->remote[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
  213.         t->remote[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
  214.         t->remote[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
  215.         t->remote_length = 8;
  216.         if (connect(t->sock, (struct sockaddr *) addr,
  217.                     sizeof(struct sockaddr_atmpvc)) < 0) {
  218.             DEBUGMSGTL(("netsnmp_aal5pvc", "connect failed (%s)n",
  219.                         strerror(errno)));
  220.             netsnmp_aal5pvc_close(t);
  221.             netsnmp_transport_free(t);
  222.             return NULL;
  223.         }
  224.     }
  225.     t->data = malloc(sizeof(struct sockaddr_atmpvc));
  226.     if (t->data == NULL) {
  227.         netsnmp_transport_free(t);
  228.         return NULL;
  229.     }
  230.     memcpy(t->data, addr, sizeof(struct sockaddr_atmpvc));
  231.     t->data_length = sizeof(struct sockaddr_atmpvc);
  232.     /*
  233.      * 16-bit length field in the trailer, no headers.  
  234.      */
  235.     t->msgMaxSize = 0xffff;
  236.     t->f_recv     = netsnmp_aal5pvc_recv;
  237.     t->f_send     = netsnmp_aal5pvc_send;
  238.     t->f_close    = netsnmp_aal5pvc_close;
  239.     t->f_accept   = NULL;
  240.     t->f_fmtaddr  = netsnmp_aal5pvc_fmtaddr;
  241.     return t;
  242. }
  243. netsnmp_transport *
  244. netsnmp_aal5pvc_create_tstring(const char *str, int local)
  245. {
  246.     struct sockaddr_atmpvc addr;
  247.     if (str != NULL) {
  248.         addr.sap_family = AF_ATMPVC;
  249.         if (sscanf(str, "%hd.%hd.%d", &(addr.sap_addr.itf),
  250.                    &(addr.sap_addr.vpi), &(addr.sap_addr.vci)) == 3) {
  251.             return netsnmp_aal5pvc_transport(&addr, local);
  252.         } else if (sscanf(str, "%hd.%d", &(addr.sap_addr.vpi),
  253.                           &(addr.sap_addr.vci)) == 2) {
  254.             addr.sap_addr.itf = 0;
  255.             return netsnmp_aal5pvc_transport(&addr, local);
  256.         } else if (sscanf(str, "%d", &(addr.sap_addr.vci)) == 1) {
  257.             addr.sap_addr.itf = 0;
  258.             addr.sap_addr.vpi = 0;
  259.             return netsnmp_aal5pvc_transport(&addr, local);
  260.         } else {
  261.             return NULL;
  262.         }
  263.     } else {
  264.         return NULL;
  265.     }
  266. }
  267. netsnmp_transport *
  268. netsnmp_aal5pvc_create_ostring(const u_char * o, size_t o_len, int local)
  269. {
  270.     struct sockaddr_atmpvc addr;
  271.     if (o_len == 8) {
  272.         addr.sap_family = AF_ATMPVC;
  273.         addr.sap_addr.itf = (o[0] << 8) + (o[1] << 0);
  274.         addr.sap_addr.vpi = (o[2] << 8) + (o[3] << 0);
  275.         addr.sap_addr.vci =
  276.     (o[4] << 24) + (o[5] << 16) + (o[6] << 8) + (o[7] << 0);
  277.         return netsnmp_aal5pvc_transport(&addr, local);
  278.     }
  279.     return NULL;
  280. }
  281. void
  282. netsnmp_aal5pvc_ctor(void)
  283. {
  284.     aal5pvcDomain.name = netsnmp_AAL5PVCDomain;
  285.     aal5pvcDomain.name_length = sizeof(netsnmp_AAL5PVCDomain) / sizeof(oid);
  286.     aal5pvcDomain.prefix = calloc(3, sizeof(char *));
  287.     aal5pvcDomain.prefix[0] = "aal5pvc";
  288.     aal5pvcDomain.prefix[1] = "pvc";
  289.     aal5pvcDomain.f_create_from_tstring = netsnmp_aal5pvc_create_tstring;
  290.     aal5pvcDomain.f_create_from_ostring = netsnmp_aal5pvc_create_ostring;
  291.     netsnmp_tdomain_register(&aal5pvcDomain);
  292. }