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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * Smux module authored by Rohit Dube.
  3.  * Rewritten by Nick Amato <naamato@merit.net>.
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #include <sys/types.h>
  7. #include <ctype.h>
  8. #if HAVE_IO_H                   /* win32 */
  9. #include <io.h>
  10. #endif
  11. #include <stdio.h>
  12. #if HAVE_STDLIB_H
  13. #include <stdlib.h>
  14. #endif
  15. #if HAVE_STRING_H
  16. #include <string.h>
  17. #else
  18. #include <strings.h>
  19. #endif
  20. #if HAVE_UNISTD_H
  21. #include <unistd.h>
  22. #endif
  23. #if HAVE_ERR_H
  24. #include <err.h>
  25. #endif
  26. #if TIME_WITH_SYS_TIME
  27. # ifdef WIN32
  28. #  include <sys/timeb.h>
  29. # else
  30. #  include <sys/time.h>
  31. # endif
  32. # include <time.h>
  33. #else
  34. # if HAVE_SYS_TIME_H
  35. #  include <sys/time.h>
  36. # else
  37. #  include <time.h>
  38. # endif
  39. #endif
  40. #include <errno.h>
  41. #if HAVE_NETDB_H
  42. #include <netdb.h>
  43. #endif
  44. #include <sys/stat.h>
  45. #if HAVE_SYS_SOCKET_H
  46. #include <sys/socket.h>
  47. #elif HAVE_WINSOCK_H
  48. #include <winsock.h>
  49. #endif
  50. #if HAVE_SYS_FILIO_H
  51. #include <sys/filio.h>
  52. #endif
  53. #if HAVE_NETINET_IN_H
  54. #include <netinet/in.h>
  55. #endif
  56. #if HAVE_ARPA_INET_H
  57. #include <arpa/inet.h>
  58. #endif
  59. #if HAVE_SYS_IOCTL_H
  60. #include <sys/ioctl.h>
  61. #endif
  62. #include <net-snmp/net-snmp-includes.h>
  63. #include <net-snmp/agent/net-snmp-agent-includes.h>
  64. #include "smux.h"
  65. #include "util_funcs.h"
  66. #include "mibdefs.h"
  67. #include "snmpd.h"
  68. long            smux_long;
  69. u_long          smux_ulong;
  70. struct sockaddr_in smux_sa;
  71. struct counter64 smux_counter64;
  72. oid             smux_objid[MAX_OID_LEN];
  73. u_char          smux_str[SMUXMAXSTRLEN];
  74. int             smux_listen_sd = -1;
  75. static struct timeval smux_rcv_timeout;
  76. static long   smux_reqid;
  77. void            init_smux(void);
  78. static u_char  *smux_open_process(int, u_char *, size_t *, int *);
  79. static u_char  *smux_rreq_process(int, u_char *, size_t *);
  80. static u_char  *smux_close_process(int, u_char *, size_t *);
  81. static u_char  *smux_trap_process(u_char *, size_t *);
  82. static u_char  *smux_parse(u_char *, oid *, size_t *, size_t *, u_char *);
  83. static u_char  *smux_parse_var(u_char *, size_t *, oid *, size_t *,
  84.                                size_t *, u_char *);
  85. static void     smux_send_close(int, int);
  86. static void     smux_list_detach(smux_reg **, smux_reg **);
  87. static void     smux_replace_active(smux_reg *, smux_reg *);
  88. static void     smux_peer_cleanup(int);
  89. static int      smux_auth_peer(oid *, size_t, char *, int);
  90. static int      smux_build(u_char, long, oid *,
  91.                            size_t *, u_char, u_char *, size_t, u_char *,
  92.                            size_t *);
  93. static int      smux_list_add(smux_reg **, smux_reg *);
  94. static int      smux_pdu_process(int, u_char *, size_t);
  95. static int      smux_send_rrsp(int, int);
  96. static smux_reg *smux_find_match(smux_reg *, int, oid *, size_t, long);
  97. static smux_reg *smux_find_replacement(oid *, size_t);
  98. u_char         *var_smux(struct variable *, oid *, size_t *, int, size_t *,
  99.                          WriteMethod ** write_method);
  100. int             var_smux_write(int, u_char *, u_char, size_t, u_char *,
  101.                                oid *, size_t);
  102. static smux_reg *ActiveRegs;    /* Active registrations                 */
  103. static smux_reg *PassiveRegs;   /* Currently unused registrations       */
  104. static smux_peer_auth *Auths[SMUX_MAX_PEERS];   /* Configured peers */
  105. static int      nauths, npeers = 0;
  106. struct variable2 smux_variables[] = {
  107.     /*
  108.      * bogus entry, as in pass.c 
  109.      */
  110.     {MIBINDEX, ASN_INTEGER, RWRITE, var_smux, 0, {MIBINDEX}},
  111. };
  112. void
  113. smux_parse_smux_socket(const char *token, char *cptr)
  114. {
  115.     DEBUGMSGTL(("smux", "port spec: %sn", cptr));
  116.     netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_SMUX_SOCKET, cptr);
  117. }
  118. void
  119. smux_parse_peer_auth(const char *token, char *cptr)
  120. {
  121.     smux_peer_auth *aptr;
  122.     if ((aptr =
  123.          (smux_peer_auth *) calloc(1, sizeof(smux_peer_auth))) == NULL) {
  124.         snmp_log_perror("smux_parse_peer_auth: malloc");
  125.         return;
  126.     }
  127.     if (nauths == SMUX_MAX_PEERS) {
  128. config_perror("Too many smuxpeers");
  129. return;
  130.     }
  131.     aptr->sa_active_fd = -1;
  132.     if (!cptr) {
  133.         /*
  134.          * null passwords OK 
  135.          */
  136.         Auths[nauths++] = aptr;
  137.         DEBUGMSGTL(("smux_conf", "null passwordn"));
  138.         return;
  139.     }
  140.     /*
  141.      * oid 
  142.      */
  143.     aptr->sa_oid_len = MAX_OID_LEN;
  144.     read_objid( cptr, aptr->sa_oid, &aptr->sa_oid_len );
  145.     DEBUGMSGTL(("smux_conf", "parsing registration for: %sn", cptr));
  146.     cptr = skip_token(cptr);
  147.     DEBUGMSGTL(("smux_conf", "password is: %sn", cptr ? cptr : "NULL"));
  148.     /*
  149.      * password 
  150.      */
  151.     if (cptr)
  152.         strcpy(aptr->sa_passwd, cptr);
  153.     Auths[nauths++] = aptr;
  154. }
  155. void
  156. smux_free_peer_auth(void)
  157. {
  158.     int             i;
  159.     for (i = 0; i < nauths; i++) {
  160.         free(Auths[i]);
  161.         Auths[i] = NULL;
  162.     }
  163.     nauths = 0;
  164. }
  165. void
  166. init_smux(void)
  167. {
  168.     snmpd_register_config_handler("smuxpeer", smux_parse_peer_auth,
  169.                                   smux_free_peer_auth,
  170.                                   "OID-IDENTITY PASSWORD");
  171.     snmpd_register_config_handler("smuxsocket",
  172.                                   smux_parse_smux_socket, NULL,
  173.                                   "SMUX bind address");
  174. }
  175. void
  176. real_init_smux(void)
  177. {
  178.     struct sockaddr_in lo_socket;
  179.     char           *smux_socket;
  180.     int             one = 1;
  181.     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
  182.         smux_listen_sd = -1;
  183.         return;
  184.     }
  185.     /*
  186.      * Reqid 
  187.      */
  188.     smux_reqid = 0;
  189.     smux_listen_sd = -1;
  190.     /*
  191.      * Receive timeout 
  192.      */
  193.     smux_rcv_timeout.tv_sec = 0;
  194.     smux_rcv_timeout.tv_usec = 500000;
  195.     /*
  196.      * Get ready to listen on the SMUX port
  197.      */
  198.     memset(&lo_socket, (0), sizeof(lo_socket));
  199.     lo_socket.sin_family = AF_INET;
  200.     smux_socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 
  201. NETSNMP_DS_SMUX_SOCKET);
  202. #ifdef LOCAL_SMUX
  203.     if (!smux_socket)
  204.         smux_socket = "127.0.0.1";   /* By default, listen on localhost only */
  205. #endif
  206.     netsnmp_sockaddr_in( &lo_socket, smux_socket, SMUXPORT );
  207.     if ((smux_listen_sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  208.         snmp_log_perror("[init_smux] socket failed");
  209.         return;
  210.     }
  211. #ifdef SO_REUSEADDR
  212.     /*
  213.      * At least on Linux, when the master agent terminates, any
  214.      * TCP connections for SMUX peers are put in the TIME_WAIT
  215.      * state for about 60 seconds. If the master agent is started
  216.      * during this time, the bind for the listening socket will
  217.      * fail because the SMUX port is in use.
  218.      */
  219.     if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
  220.                    sizeof(one)) < 0) {
  221.         snmp_log_perror("[init_smux] setsockopt(SO_REUSEADDR) failed");
  222.     }
  223. #endif                          /* SO_REUSEADDR */
  224.     if (bind(smux_listen_sd, (struct sockaddr *) &lo_socket,
  225.              sizeof(lo_socket)) < 0) {
  226.         snmp_log_perror("[init_smux] bind failed");
  227.         close(smux_listen_sd);
  228.         smux_listen_sd = -1;
  229.         return;
  230.     }
  231. #ifdef SO_KEEPALIVE
  232.     if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
  233.                    sizeof(one)) < 0) {
  234.         snmp_log_perror("[init_smux] setsockopt(SO_KEEPALIVE) failed");
  235.         close(smux_listen_sd);
  236.         smux_listen_sd = -1;
  237.         return;
  238.     }
  239. #endif                          /* SO_KEEPALIVE */
  240.     if (listen(smux_listen_sd, SOMAXCONN) == -1) {
  241.         snmp_log_perror("[init_smux] listen failed");
  242.         close(smux_listen_sd);
  243.         smux_listen_sd = -1;
  244.         return;
  245.     }
  246.     DEBUGMSGTL(("smux_init",
  247.                 "[smux_init] done; smux listen sd is %d, smux port is %dn",
  248.                 smux_listen_sd, ntohs(lo_socket.sin_port)));
  249. }
  250. u_char         *
  251. var_smux(struct variable * vp,
  252.          oid * name,
  253.          size_t * length,
  254.          int exact, size_t * var_len, WriteMethod ** write_method)
  255. {
  256.     u_char         *valptr, val_type;
  257.     smux_reg       *rptr;
  258.     *write_method = var_smux_write;
  259.     /*
  260.      * search the active registration list 
  261.      */
  262.     for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
  263.         if (0 >= snmp_oidtree_compare(vp->name, vp->namelen, rptr->sr_name,
  264.                                       rptr->sr_name_len))
  265.             break;
  266.     }
  267.     if (rptr == NULL)
  268.         return NULL;
  269.     else if (exact && (*length < rptr->sr_name_len))
  270.         return NULL;
  271.     valptr = smux_snmp_process(exact, name, length,
  272.                                var_len, &val_type, rptr->sr_fd);
  273.     if (valptr == NULL)
  274.         return NULL;
  275.     if ((snmp_oidtree_compare(name, *length, rptr->sr_name,
  276.                               rptr->sr_name_len)) != 0) {
  277.         /*
  278.          * the peer has returned a value outside
  279.          * * of the registered tree
  280.          */
  281.         return NULL;
  282.     } else {
  283.         /*
  284.          * set the type and return the value 
  285.          */
  286.         vp->type = val_type;
  287.         return valptr;
  288.     }
  289. }
  290. int
  291. var_smux_write(int action,
  292.                u_char * var_val,
  293.                u_char var_val_type,
  294.                size_t var_val_len,
  295.                u_char * statP, oid * name, size_t name_len)
  296. {
  297.     smux_reg       *rptr;
  298.     u_char          buf[SMUXMAXPKTSIZE], *ptr, sout[3], type;
  299.     int             reterr;
  300.     size_t          var_len, datalen, name_length, packet_len;
  301.     ssize_t         len;
  302.     long            reqid, errsts, erridx;
  303.     u_char          var_type, *dataptr;
  304.     DEBUGMSGTL(("smux", "[var_smux_write] entering var_smux_writen"));
  305.     len = SMUXMAXPKTSIZE;
  306.     reterr = SNMP_ERR_NOERROR;
  307.     var_len = var_val_len;
  308.     var_type = var_val_type;
  309.     name_length = name_len;
  310.     /*
  311.      * XXX find the descriptor again 
  312.      */
  313.     for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
  314.         if (!snmp_oidtree_compare(name, name_len, rptr->sr_name,
  315.                                   rptr->sr_name_len))
  316.             break;
  317.     }
  318.     switch (action) {
  319.     case RESERVE1:
  320.         DEBUGMSGTL(("smux", "[var_smux_write] entering RESERVE1n"));
  321.         /*
  322.          * length might be long 
  323.          */
  324.         var_len += (*(var_val + 1) & ASN_LONG_LEN) ?
  325.             var_len + ((*(var_val + 1) & 0x7F) + 2) : 2;
  326.         switch (var_val_type) {
  327.         case ASN_INTEGER:
  328.         case ASN_OCTET_STR:
  329.         case ASN_COUNTER:
  330.         case ASN_GAUGE:
  331.         case ASN_TIMETICKS:
  332.         case ASN_UINTEGER:
  333.         case ASN_COUNTER64:
  334.         case ASN_IPADDRESS:
  335.         case ASN_OPAQUE:
  336.         case ASN_NSAP:
  337.         case ASN_OBJECT_ID:
  338.         case ASN_BIT_STR:
  339.             datalen = var_val_len;
  340.             dataptr = var_val;
  341.             break;
  342.         case SNMP_NOSUCHOBJECT:
  343.         case SNMP_NOSUCHINSTANCE:
  344.         case SNMP_ENDOFMIBVIEW:
  345.         case ASN_NULL:
  346.         default:
  347.             DEBUGMSGTL(("smux",
  348.                         "[var_smux_write] variable not supportedn"));
  349.             return SNMP_ERR_GENERR;
  350.             break;
  351.         }
  352.         if ((smux_build((u_char) SMUX_SET, smux_reqid,
  353.                         name, &name_length, var_val_type, dataptr,
  354.                         datalen, buf, &len)) < 0) {
  355.             DEBUGMSGTL(("smux", "[var_smux_write] smux build failedn"));
  356.             return SNMP_ERR_GENERR;
  357.         }
  358.         if (send(rptr->sr_fd, buf, len, 0) < 0) {
  359.             DEBUGMSGTL(("smux", "[var_smux_write] send failedn"));
  360.             return SNMP_ERR_GENERR;
  361.         }
  362.         while (1) {
  363.             /*
  364.              * peek at what's received 
  365.              */
  366.             if ((len = recv(rptr->sr_fd, buf,
  367.                             SMUXMAXPKTSIZE, MSG_PEEK)) <= 0) {
  368.                 DEBUGMSGTL(("smux",
  369.                             "[var_smux_write] peek failed or timed outn"));
  370.                 /*
  371.                  * do we need to do a peer cleanup in this case?? 
  372.                  */
  373.                 smux_peer_cleanup(rptr->sr_fd);
  374.                 return SNMP_ERR_GENERR;
  375.             }
  376.             DEBUGMSGTL(("smux", "[var_smux_write] Peeked at %d bytesn",
  377.                         len));
  378.             DEBUGDUMPSETUP("var_smux_write", buf, len);
  379.             /*
  380.              * determine if we received more than one packet 
  381.              */
  382.             packet_len = len;
  383.             ptr = asn_parse_header(buf, &packet_len, &type);
  384.             packet_len += (ptr - buf);
  385.             if (len > (ssize_t)packet_len) {
  386.                 /*
  387.                  * set length to receive only the first packet 
  388.                  */
  389.                 len = packet_len;
  390.             }
  391.             /*
  392.              * receive the first packet 
  393.              */
  394.             if ((len = recv(rptr->sr_fd, buf, len, 0)) <= 0) {
  395.                 DEBUGMSGTL(("smux",
  396.                             "[var_smux_write] recv failed or timed outn"));
  397.                 /*
  398.                  * do we need to do a peer cleanup in this case?? 
  399.                  */
  400.                 smux_peer_cleanup(rptr->sr_fd);
  401.                 return SNMP_ERR_GENERR;
  402.             }
  403.             DEBUGMSGTL(("smux", "[var_smux_write] Received %d bytesn",
  404.                         len));
  405.             if (buf[0] == SMUX_TRAP) {
  406.                 DEBUGMSGTL(("smux", "[var_smux_write] Received trapn"));
  407.                 snmp_log(LOG_INFO, "Got trap from peer on fd %dn",
  408.                          rptr->sr_fd);
  409.                 ptr = asn_parse_header(buf, &len, &type);
  410.                 smux_trap_process(ptr, &len);
  411.                 /*
  412.                  * go and peek at received data again 
  413.                  */
  414.                 /*
  415.                  * we could receive the reply or another trap 
  416.                  */
  417.             } else {
  418.                 ptr = buf;
  419.                 ptr = asn_parse_header(ptr, &len, &type);
  420.                 if ((ptr == NULL) || type != SNMP_MSG_RESPONSE)
  421.                     return SNMP_ERR_GENERR;
  422.                 ptr =
  423.                     asn_parse_int(ptr, &len, &type, &reqid, sizeof(reqid));
  424.                 if ((ptr == NULL) || type != ASN_INTEGER)
  425.                     return SNMP_ERR_GENERR;
  426.                 ptr =
  427.                     asn_parse_int(ptr, &len, &type, &errsts,
  428.                                   sizeof(errsts));
  429.                 if ((ptr == NULL) || type != ASN_INTEGER)
  430.                     return SNMP_ERR_GENERR;
  431.                 if (errsts) {
  432.                     DEBUGMSGTL(("smux",
  433.                                 "[var_smux_write] errsts returnedn"));
  434.                     return (errsts);
  435.                 }
  436.                 ptr =
  437.                     asn_parse_int(ptr, &len, &type, &erridx,
  438.                                   sizeof(erridx));
  439.                 if ((ptr == NULL) || type != ASN_INTEGER)
  440.                     return SNMP_ERR_GENERR;
  441.                 reterr = SNMP_ERR_NOERROR;
  442.                 break;
  443.             }
  444.         }                       /* while (1) */
  445.         break;                  /* case Action == RESERVE1 */
  446.     case RESERVE2:
  447.         DEBUGMSGTL(("smux", "[var_smux_write] entering RESERVE2n"));
  448.         reterr = SNMP_ERR_NOERROR;
  449.         break;                  /* case Action == RESERVE2 */
  450.     case FREE:
  451.     case COMMIT:
  452.         ptr = sout;
  453.         *(ptr++) = (u_char) SMUX_SOUT;
  454.         *(ptr++) = (u_char) 1;
  455.         if (action == FREE) {
  456.             *ptr = (u_char) 1;  /* rollback */
  457.             DEBUGMSGTL(("smux",
  458.                         "[var_smux_write] entering FREE - sending RollBack n"));
  459.         } else {
  460.             *ptr = (u_char) 0;  /* commit */
  461.             DEBUGMSGTL(("smux",
  462.                         "[var_smux_write] entering FREE - sending Commit n"));
  463.         }
  464.         if ((send(rptr->sr_fd, sout, 3, 0)) < 0) {
  465.             DEBUGMSGTL(("smux",
  466.                         "[var_smux_write] send rollback/commit failedn"));
  467.             return SNMP_ERR_GENERR;
  468.         }
  469.         reterr = SNMP_ERR_NOERROR;
  470.         break;                  /* case Action == COMMIT */
  471.     default:
  472.         break;
  473.     }
  474.     return reterr;
  475. }
  476. int
  477. smux_accept(int sd)
  478. {
  479.     u_char          data[SMUXMAXPKTSIZE], *ptr, type;
  480.     struct sockaddr_in in_socket;
  481.     struct timeval  tv;
  482.     int             fail, fd, alen;
  483.     int             length;
  484.     ssize_t         len;
  485.     alen = sizeof(struct sockaddr_in);
  486.     /*
  487.      * this may be too high 
  488.      */
  489.     tv.tv_sec = 5;
  490.     tv.tv_usec = 0;
  491.     /*
  492.      * connection request 
  493.      */
  494.     DEBUGMSGTL(("smux", "[smux_accept] Calling accept()n"));
  495.     errno = 0;
  496.     if ((fd = accept(sd, (struct sockaddr *) &in_socket, &alen)) < 0) {
  497.         snmp_log_perror("[smux_accept] accept failed");
  498.         return -1;
  499.     } else {
  500.         snmp_log(LOG_INFO, "[smux_accept] accepted fd %d from %s:%dn",
  501.                  fd, inet_ntoa(in_socket.sin_addr),
  502.                  ntohs(in_socket.sin_port));
  503.         if (npeers + 1 == SMUXMAXPEERS) {
  504.             snmp_log(LOG_ERR,
  505.                      "[smux_accept] denied peer on fd %d, limit %d reached",
  506.                      fd, SMUXMAXPEERS);
  507.             close(sd);
  508.             return -1;
  509.         }
  510.         /*
  511.          * now block for an OpenPDU 
  512.          */
  513.         if ((length = recv(fd, (char *) data, SMUXMAXPKTSIZE, 0)) <= 0) {
  514.             DEBUGMSGTL(("smux",
  515.                         "[smux_accept] peer on fd %d died or timed outn",
  516.                         fd));
  517.             close(fd);
  518.             return -1;
  519.         }
  520.         /*
  521.          * try to authorize him 
  522.          */
  523.         ptr = data;
  524.         len = length;
  525.         if ((ptr = asn_parse_header(ptr, &len, &type)) == NULL) {
  526.             smux_send_close(fd, SMUXC_PACKETFORMAT);
  527.             close(fd);
  528.             DEBUGMSGTL(("smux", "[smux_accept] peer on %d sent bad open"));
  529.             return -1;
  530.         } else if (type != (u_char) SMUX_OPEN) {
  531.             smux_send_close(fd, SMUXC_PROTOCOLERROR);
  532.             close(fd);
  533.             DEBUGMSGTL(("smux",
  534.                         "[smux_accept] peer on %d did not send open: (%d)n",
  535.                         type));
  536.             return -1;
  537.         }
  538.         ptr = smux_open_process(fd, ptr, &len, &fail);
  539.         if (fail) {
  540.             smux_send_close(fd, SMUXC_AUTHENTICATIONFAILURE);
  541.             close(fd);
  542.             DEBUGMSGTL(("smux",
  543.                         "[smux_accept] peer on %d failed authenticationn",
  544.                         fd));
  545.             return -1;
  546.         }
  547.         /*
  548.          * he's OK 
  549.          */
  550. #ifdef SO_RCVTIMEO
  551.         if (setsockopt
  552.             (fd, SOL_SOCKET, SO_RCVTIMEO, (void *) &tv, sizeof(tv)) < 0) {
  553.             DEBUGMSGTL(("smux",
  554.                         "[smux_accept] setsockopt(SO_RCVTIMEO) failed fd %dn",
  555.                         fd));
  556.             snmp_log_perror("smux_accept: setsockopt SO_RCVTIMEO");
  557.         }
  558. #endif
  559.         npeers++;
  560.         DEBUGMSGTL(("smux", "[smux_accept] fd %dn", fd));
  561.         /*
  562.          * Process other PDUs already read, e.g. a registerRequest. 
  563.          */
  564.         len = length - (ptr - data);
  565.         if (smux_pdu_process(fd, ptr, len) < 0) {
  566.             /*
  567.              * Easy come, easy go.  Clean-up is already done. 
  568.              */
  569.             return -1;
  570.         }
  571.     }
  572.     return fd;
  573. }
  574. int
  575. smux_process(int fd)
  576. {
  577.     int             length;
  578.     u_char          data[SMUXMAXPKTSIZE];
  579.     length = recv(fd, (char *) data, SMUXMAXPKTSIZE, 0);
  580.     if (length <= 0) {
  581.         /*
  582.          * the peer went away, close this descriptor 
  583.          * * and delete it from the list
  584.          */
  585.         DEBUGMSGTL(("smux",
  586.                     "[smux_process] peer on fd %d died or timed outn",
  587.                     fd));
  588.         smux_peer_cleanup(fd);
  589.         return -1;
  590.     }
  591.     return smux_pdu_process(fd, data, length);
  592. }
  593. static int
  594. smux_pdu_process(int fd, u_char * data, size_t length)
  595. {
  596.     int             error;
  597.     size_t          len;
  598.     u_char         *ptr, type;
  599.     DEBUGMSGTL(("smux", "[smux_pdu_process] Processing %d bytesn",
  600.                 length));
  601.     error = 0;
  602.     ptr = data;
  603.     while (error == 0 && ptr != NULL && ptr < data + length) {
  604.         len = length - (ptr - data);
  605.         ptr = asn_parse_header(ptr, &len, &type);
  606.         DEBUGMSGTL(("smux", "[smux_pdu_process] type is %dn",
  607.                     (int) type));
  608.         switch (type) {
  609.         case SMUX_OPEN:
  610.             smux_send_close(fd, SMUXC_PROTOCOLERROR);
  611.             DEBUGMSGTL(("smux",
  612.                         "[smux_pdu_process] peer on fd %d sent duplicate open?n",
  613.                         fd));
  614.             smux_peer_cleanup(fd);
  615.             error = -1;
  616.             break;
  617.         case SMUX_CLOSE:
  618.             ptr = smux_close_process(fd, ptr, &len);
  619.             smux_peer_cleanup(fd);
  620.             error = -1;
  621.             break;
  622.         case SMUX_RREQ:
  623.             ptr = smux_rreq_process(fd, ptr, &len);
  624.             break;
  625.         case SMUX_RRSP:
  626.             error = -1;
  627.             smux_send_close(fd, SMUXC_PROTOCOLERROR);
  628.             smux_peer_cleanup(fd);
  629.             DEBUGMSGTL(("smux",
  630.                         "[smux_pdu_process] peer on fd %d sent RRSP!n",
  631.                         fd));
  632.             break;
  633.         case SMUX_SOUT:
  634.             error = -1;
  635.             smux_send_close(fd, SMUXC_PROTOCOLERROR);
  636.             smux_peer_cleanup(fd);
  637.             DEBUGMSGTL(("smux", "This shouldn't have happened!n"));
  638.             break;
  639.         case SMUX_TRAP:
  640.             snmp_log(LOG_INFO, "Got trap from peer on fd %dn", fd);
  641.             ptr = smux_trap_process(ptr, &len);
  642.             /*
  643.              * watch out for close on top of this...should return correct end 
  644.              */
  645.             /*
  646.              * debug this... 
  647.              */
  648.             ptr = NULL;
  649.             break;
  650.         default:
  651.             smux_send_close(fd, SMUXC_PACKETFORMAT);
  652.             smux_peer_cleanup(fd);
  653.             DEBUGMSGTL(("smux", "[smux_pdu_process] Wrong type %dn",
  654.                         (int) type));
  655.             error = -1;
  656.             break;
  657.         }
  658.     }
  659.     return error;
  660. }
  661. static u_char  *
  662. smux_open_process(int fd, u_char * ptr, size_t * len, int *fail)
  663. {
  664.     u_char          type;
  665.     long            version;
  666.     oid             oid_name[MAX_OID_LEN];
  667.     char            passwd[SMUXMAXSTRLEN];
  668.     char            descr[SMUXMAXSTRLEN];
  669.     char            oid_print[SMUXMAXSTRLEN];
  670.     int             i;
  671.     size_t          oid_name_len, string_len;
  672.     if (!(ptr = asn_parse_int(ptr, len, &type, &version, sizeof(version)))) {
  673.         DEBUGMSGTL(("smux", "[smux_open_process] version parse failedn"));
  674.         *fail = TRUE;
  675.         return ((ptr += *len));
  676.     }
  677.     DEBUGMSGTL(("smux",
  678.                 "[smux_open_process] version %d, len %d, type %dn",
  679.                 version, *len, (int) type));
  680.     oid_name_len = MAX_OID_LEN;
  681.     if ((ptr = asn_parse_objid(ptr, len, &type, oid_name,
  682.                                &oid_name_len)) == NULL) {
  683.         DEBUGMSGTL(("smux", "[smux_open_process] oid parse failedn"));
  684.         *fail = TRUE;
  685.         return ((ptr += *len));
  686.     }
  687.     snprint_objid(oid_print, sizeof(oid_print), oid_name, oid_name_len);
  688.     if (snmp_get_do_debugging()) {
  689.         DEBUGMSGTL(("smux", "[smux_open_process] smux peer: %sn",
  690.                     oid_print));
  691.         DEBUGMSGTL(("smux", "[smux_open_process] len %d, type %dn", *len,
  692.                     (int) type));
  693.     }
  694.     string_len = SMUXMAXSTRLEN;
  695.     if ((ptr = asn_parse_string(ptr, len, &type, (u_char *) descr,
  696.                                 &string_len)) == NULL) {
  697.         DEBUGMSGTL(("smux", "[smux_open_process] descr parse failedn"));
  698.         *fail = TRUE;
  699.         return ((ptr += *len));
  700.     }
  701.     if (snmp_get_do_debugging()) {
  702.         DEBUGMSGTL(("smux", "[smux_open_process] smux peer descr: "));
  703.         for (i = 0; i < (int) string_len; i++)
  704.             DEBUGMSG(("smux", "%c", descr[i]));
  705.         DEBUGMSG(("smux", "n"));
  706.         DEBUGMSGTL(("smux", "[smux_open_process] len %d, type %dn", *len,
  707.                     (int) type));
  708.     }
  709.     descr[string_len] = 0;
  710.     string_len = SMUXMAXSTRLEN;
  711.     if ((ptr = asn_parse_string(ptr, len, &type, (u_char *) passwd,
  712.                                 &string_len)) == NULL) {
  713.         DEBUGMSGTL(("smux", "[smux_open_process] passwd parse failedn"));
  714.         *fail = TRUE;
  715.         return ((ptr += *len));
  716.     }
  717.     if (snmp_get_do_debugging()) {
  718.         DEBUGMSGTL(("smux", "[smux_open_process] smux peer passwd: "));
  719.         for (i = 0; i < (int) string_len; i++)
  720.             DEBUGMSG(("smux", "%c", passwd[i]));
  721.         DEBUGMSG(("smux", "n"));
  722.         DEBUGMSGTL(("smux", "[smux_open_process] len %d, type %dn", *len,
  723.                     (int) type));
  724.     }
  725.     passwd[string_len] = '';
  726.     if (!smux_auth_peer(oid_name, oid_name_len, passwd, fd)) {
  727.         snmp_log(LOG_WARNING,
  728.                  "refused smux peer: oid %s, descr %sn",
  729.                  oid_print, descr);
  730.         *fail = TRUE;
  731.         return ptr;
  732.     }
  733.     snmp_log(LOG_INFO,
  734.              "accepted smux peer: oid %s, descr %sn",
  735.              oid_print, descr);
  736.     *fail = FALSE;
  737.     return ptr;
  738. }
  739. static void
  740. smux_send_close(int fd, int reason)
  741. {
  742.     u_char          outpacket[3], *ptr;
  743.     ptr = outpacket;
  744.     *(ptr++) = (u_char) SMUX_CLOSE;
  745.     *(ptr++) = (u_char) 1;
  746.     *ptr = (u_char) (reason & 0xFF);
  747.     if (snmp_get_do_debugging())
  748.         DEBUGMSGTL(("smux",
  749.                     "[smux_close] sending close to fd %d, reason %dn", fd,
  750.                     reason));
  751.     /*
  752.      * send a response back 
  753.      */
  754.     if (send(fd, (char *) outpacket, 3, 0) < 0) {
  755.         snmp_log_perror("[smux_snmp_close] send failed");
  756.     }
  757. }
  758. static int
  759. smux_auth_peer(oid * name, size_t namelen, char *passwd, int fd)
  760. {
  761.     int             i;
  762.     for (i = 0; i < nauths; i++) {
  763.         if (snmp_oid_compare(Auths[i]->sa_oid, Auths[i]->sa_oid_len,
  764.                              name, namelen) == 0) {
  765.             if (!(strcmp(Auths[i]->sa_passwd, passwd)) &&
  766.                 (Auths[i]->sa_active_fd == -1)) {
  767.                 /*
  768.                  * matched, mark the auth 
  769.                  */
  770.                 Auths[i]->sa_active_fd = fd;
  771.                 return 1;
  772.             }
  773.         }
  774.     }
  775.     /*
  776.      * did not match oid and passwd 
  777.      */
  778.     return 0;
  779. }
  780. /*
  781.  * XXX - Bells and Whistles:
  782.  * Need to catch signal when snmpd goes down and send close pdu to gated 
  783.  */
  784. static u_char  *
  785. smux_close_process(int fd, u_char * ptr, size_t * len)
  786. {
  787.     long            down = 0;
  788.     int             length = *len;
  789.     /*
  790.      * This is the integer part of the close pdu 
  791.      */
  792.     while (length--) {
  793.         down = (down << 8) | (long) *ptr;
  794.         ptr++;
  795.     }
  796.     DEBUGMSGTL(("smux",
  797.                 "[smux_close_process] close from peer on fd %d reason %dn",
  798.                 fd, down));
  799.     smux_peer_cleanup(fd);
  800.     return NULL;
  801. }
  802. static u_char  *
  803. smux_rreq_process(int sd, u_char * ptr, size_t * len)
  804. {
  805.     long            priority, rpriority;
  806.     long            operation;
  807.     oid             oid_name[MAX_OID_LEN];
  808.     size_t          oid_name_len;
  809.     int             i, result;
  810.     u_char          type;
  811.     smux_reg       *rptr, *nrptr;
  812.     oid_name_len = MAX_OID_LEN;
  813.     ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len);
  814.     DEBUGMSGTL(("smux", "[smux_rreq_process] smux subtree: "));
  815.     DEBUGMSGOID(("smux", oid_name, oid_name_len));
  816.     DEBUGMSG(("smux", "n"));
  817.     if ((ptr = asn_parse_int(ptr, len, &type, &priority,
  818.                              sizeof(priority))) == NULL) {
  819.         DEBUGMSGTL(("smux",
  820.                     "[smux_rreq_process] priority parse failedn"));
  821.         smux_send_rrsp(sd, -1);
  822.         return NULL;
  823.     }
  824.     DEBUGMSGTL(("smux", "[smux_rreq_process] priority %dn", priority));
  825.     if ((ptr = asn_parse_int(ptr, len, &type, &operation,
  826.                              sizeof(operation))) == NULL) {
  827.         DEBUGMSGTL(("smux",
  828.                     "[smux_rreq_process] operation parse failedn"));
  829.         smux_send_rrsp(sd, -1);
  830.         return NULL;
  831.     }
  832.     DEBUGMSGTL(("smux", "[smux_rreq_process] operation %dn", operation));
  833.     if (operation == SMUX_REGOP_DELETE) {
  834.         /*
  835.          * search the active list for this registration 
  836.          */
  837.         rptr =
  838.             smux_find_match(ActiveRegs, sd, oid_name, oid_name_len,
  839.                             priority);
  840.         if (rptr) {
  841.             rpriority = rptr->sr_priority;
  842.             /*
  843.              * unregister the mib 
  844.              */
  845.             unregister_mib(rptr->sr_name, rptr->sr_name_len);
  846.             /*
  847.              * find a replacement 
  848.              */
  849.             nrptr =
  850.                 smux_find_replacement(rptr->sr_name, rptr->sr_name_len);
  851.             if (nrptr) {
  852.                 /*
  853.                  * found one 
  854.                  */
  855.                 smux_replace_active(rptr, nrptr);
  856.             } else {
  857.                 /*
  858.                  * no replacement found 
  859.                  */
  860.                 smux_list_detach(&ActiveRegs, &rptr);
  861.                 free(rptr);
  862.             }
  863.             smux_send_rrsp(sd, rpriority);
  864.             return ptr;
  865.         }
  866.         /*
  867.          * search the passive list for this registration 
  868.          */
  869.         rptr =
  870.             smux_find_match(PassiveRegs, sd, oid_name, oid_name_len,
  871.                             priority);
  872.         if (rptr) {
  873.             rpriority = rptr->sr_priority;
  874.             smux_list_detach(&PassiveRegs, &rptr);
  875.             free(rptr);
  876.             smux_send_rrsp(sd, rpriority);
  877.             return ptr;
  878.         }
  879.         /*
  880.          * This peer cannot unregister the tree, it does not
  881.          * * belong to him.  Send him an error.
  882.          */
  883.         smux_send_rrsp(sd, -1);
  884.         return ptr;
  885.     } else if ((operation == SMUX_REGOP_REGISTER_RO) ||
  886.                (operation == SMUX_REGOP_REGISTER_RW)) {
  887.         if (priority < -1) {
  888.             DEBUGMSGTL(("smux",
  889.                         "[smux_rreq_process] peer fd %d invalid priority",
  890.                         sd, priority));
  891.             smux_send_rrsp(sd, -1);
  892.             return NULL;
  893.         }
  894.         if ((nrptr = malloc(sizeof(smux_reg))) == NULL) {
  895.             snmp_log_perror("[smux_rreq_process] malloc");
  896.             smux_send_rrsp(sd, -1);
  897.             return NULL;
  898.         }
  899.         nrptr->sr_priority = priority;
  900.         nrptr->sr_name_len = oid_name_len;
  901.         nrptr->sr_fd = sd;
  902.         for (i = 0; i < (int) oid_name_len; i++)
  903.             nrptr->sr_name[i] = oid_name[i];
  904.         /*
  905.          * See if this tree matches or scopes any of the
  906.          * * active trees.
  907.          */
  908.         for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {
  909.             result =
  910.                 snmp_oid_compare(oid_name, oid_name_len, rptr->sr_name,
  911.                                  rptr->sr_name_len);
  912.             if (result == 0) {
  913.                 if ((oid_name_len == rptr->sr_name_len)) {
  914.                     if ((nrptr->sr_priority == -1)) {
  915.                         nrptr->sr_priority = rptr->sr_priority;
  916.                         do {
  917.                             nrptr->sr_priority++;
  918.                         } while (smux_list_add(&PassiveRegs, nrptr));
  919.                         goto done;
  920.                     } else if (nrptr->sr_priority < rptr->sr_priority) {
  921.                         /*
  922.                          * Better priority.  There are no better
  923.                          * * priorities for this tree in the passive list,
  924.                          * * so replace the current active tree.
  925.                          */
  926.                         smux_replace_active(rptr, nrptr);
  927.                         goto done;
  928.                     } else {
  929.                         /*
  930.                          * Equal or worse priority 
  931.                          */
  932.                         do {
  933.                             nrptr->sr_priority++;
  934.                         } while (smux_list_add(&PassiveRegs, nrptr) == -1);
  935.                         goto done;
  936.                     }
  937.                 } else if (oid_name_len < rptr->sr_name_len) {
  938.                     /*
  939.                      * This tree scopes a current active
  940.                      * * tree.  Replace the current active tree.
  941.                      */
  942.                     smux_replace_active(rptr, nrptr);
  943.                     goto done;
  944.                 } else {        /* oid_name_len > rptr->sr_name_len */
  945.                     /*
  946.                      * This tree is scoped by a current
  947.                      * * active tree.  
  948.                      */
  949.                     do {
  950.                         nrptr->sr_priority++;
  951.                     } while (smux_list_add(&PassiveRegs, nrptr) == -1);
  952.                     goto done;
  953.                 }
  954.             }
  955.         }
  956.         /*
  957.          * We didn't find it in the active list.  Add it at
  958.          * * the requested priority.
  959.          */
  960.         if (nrptr->sr_priority == -1)
  961.             nrptr->sr_priority = 0;
  962.         smux_list_add(&ActiveRegs, nrptr);
  963.         register_mib("smux", (struct variable *)
  964.                      smux_variables, sizeof(struct variable2),
  965.                      1, nrptr->sr_name, nrptr->sr_name_len);
  966.       done:
  967.         smux_send_rrsp(sd, nrptr->sr_priority);
  968.         return ptr;
  969.     } else {
  970.         DEBUGMSGTL(("smux", "[smux_rreq_process] unknown operationn"));
  971.         smux_send_rrsp(sd, -1);
  972.         return NULL;
  973.     }
  974. }
  975. /*
  976.  * Find the registration with a matching descriptor, OID and priority.  If
  977.  * the priority is -1 then find a registration with a matching descriptor,
  978.  * a matching OID, and the highest priority.
  979.  */
  980. static smux_reg *
  981. smux_find_match(smux_reg * regs, int sd, oid * oid_name,
  982.                 size_t oid_name_len, long priority)
  983. {
  984.     smux_reg       *rptr, *bestrptr;
  985.     bestrptr = NULL;
  986.     for (rptr = regs; rptr; rptr = rptr->sr_next) {
  987.         if (rptr->sr_fd != sd)
  988.             continue;
  989.         if (snmp_oid_compare
  990.             (rptr->sr_name, rptr->sr_name_len, oid_name, oid_name_len))
  991.             continue;
  992.         if (rptr->sr_priority == priority)
  993.             return rptr;
  994.         if (priority != -1)
  995.             continue;
  996.         if (bestrptr) {
  997.             if (bestrptr->sr_priority > rptr->sr_priority)
  998.                 bestrptr = rptr;
  999.         } else {
  1000.             bestrptr = rptr;
  1001.         }
  1002.     }
  1003.     return bestrptr;
  1004. }
  1005. static void
  1006. smux_replace_active(smux_reg * actptr, smux_reg * pasptr)
  1007. {
  1008.     smux_list_detach(&ActiveRegs, &actptr);
  1009.     unregister_mib(actptr->sr_name, actptr->sr_name_len);
  1010.     smux_list_detach(&PassiveRegs, &pasptr);
  1011.     (void) smux_list_add(&ActiveRegs, pasptr);
  1012.     register_mib("smux", (struct variable *) smux_variables,
  1013.                  sizeof(struct variable2), 1, pasptr->sr_name,
  1014.                  pasptr->sr_name_len);
  1015.     free(actptr);
  1016. }
  1017. static void
  1018. smux_list_detach(smux_reg ** head, smux_reg ** m_remove)
  1019. {
  1020.     smux_reg       *rptr, *rptr2;
  1021.     if (*head == NULL) {
  1022.         DEBUGMSGTL(("smux", "[smux_list_detach] Ouch!"));
  1023.         return;
  1024.     }
  1025.     if (*head == *m_remove) {
  1026.         *m_remove = *head;
  1027.         *head = (*head)->sr_next;
  1028.         return;
  1029.     }
  1030.     for (rptr = *head, rptr2 = rptr->sr_next; rptr2;
  1031.          rptr2 = rptr2->sr_next, rptr = rptr->sr_next) {
  1032.         if (rptr2 == *m_remove) {
  1033.             *m_remove = rptr2;
  1034.             rptr->sr_next = rptr2->sr_next;
  1035.             return;
  1036.         }
  1037.     }
  1038. }
  1039. /*
  1040.  * Attempt to add a registration (in order) to a list.  If the
  1041.  * add fails (because of an existing registration with equal
  1042.  * priority) return -1.
  1043.  */
  1044. static int
  1045. smux_list_add(smux_reg ** head, smux_reg * add)
  1046. {
  1047.     smux_reg       *rptr;
  1048.     int             result;
  1049.     if (*head == NULL) {
  1050.         *head = add;
  1051.         (*head)->sr_next = NULL;
  1052.         return 0;
  1053.     }
  1054.     for (rptr = *head; rptr->sr_next; rptr = rptr->sr_next) {
  1055.         result = snmp_oid_compare(add->sr_name, add->sr_name_len,
  1056.                                   rptr->sr_name, rptr->sr_name_len);
  1057.         if ((result == 0) && (add->sr_priority == rptr->sr_priority)) {
  1058.             /*
  1059.              * same tree, same pri, nope 
  1060.              */
  1061.             return -1;
  1062.         } else if (result < 0) {
  1063.             /*
  1064.              * this can only happen if we go before the head 
  1065.              */
  1066.             add->sr_next = *head;
  1067.             *head = add;
  1068.             return 0;
  1069.         } else if ((snmp_oid_compare(add->sr_name, add->sr_name_len,
  1070.                                      rptr->sr_next->sr_name,
  1071.                                      rptr->sr_next->sr_name_len)) < 0) {
  1072.             /*
  1073.              * insert here 
  1074.              */
  1075.             add->sr_next = rptr->sr_next;
  1076.             rptr->sr_next = add;
  1077.             return 0;
  1078.         }
  1079.     }
  1080.     /*
  1081.      * compare the last one 
  1082.      */
  1083.     if ((snmp_oid_compare(add->sr_name, add->sr_name_len, rptr->sr_name,
  1084.                           rptr->sr_name_len) == 0)
  1085.         && add->sr_priority == rptr->sr_priority)
  1086.         return -1;
  1087.     else {
  1088.         rptr->sr_next = add;
  1089.         add->sr_next = NULL;
  1090.     }
  1091.     return 0;
  1092. }
  1093. /*
  1094.  * Find a replacement for this registration.  In order
  1095.  * of preference:
  1096.  *
  1097.  *      - Least difference in subtree length
  1098.  *      - Best (lowest) priority
  1099.  *
  1100.  * For example, if we need to replace .1.3.6.1.69, 
  1101.  * we would pick .1.3.6.1.69.1 instead of .1.3.6.69.1.1
  1102.  *
  1103.  */
  1104. static smux_reg *
  1105. smux_find_replacement(oid * name, size_t name_len)
  1106. {
  1107.     smux_reg       *rptr, *bestptr;
  1108.     int             bestlen, difflen;
  1109.     bestlen = SMUX_MAX_PRIORITY;
  1110.     bestptr = NULL;
  1111.     for (rptr = PassiveRegs; rptr; rptr = rptr->sr_next) {
  1112.         if (!snmp_oidtree_compare(rptr->sr_name, rptr->sr_name_len,
  1113.                                   name, name_len)) {
  1114.             if ((difflen = rptr->sr_name_len - name_len)
  1115.                 < bestlen) {
  1116.                 bestlen = difflen;
  1117.                 bestptr = rptr;
  1118.             } else if ((difflen == bestlen) &&
  1119.                        (rptr->sr_priority < bestptr->sr_priority))
  1120.                 bestptr = rptr;
  1121.         }
  1122.     }
  1123.     return bestptr;
  1124. }
  1125. u_char         *
  1126. smux_snmp_process(int exact,
  1127.                   oid * objid,
  1128.                   size_t * len,
  1129.                   size_t * return_len, u_char * return_type, int sd)
  1130. {
  1131.     u_char          packet[SMUXMAXPKTSIZE], *ptr, result[SMUXMAXPKTSIZE];
  1132.     size_t          length = SMUXMAXPKTSIZE;
  1133.     u_char          type;
  1134.     size_t          packet_len;
  1135.     /*
  1136.      * Send the query to the peer
  1137.      */
  1138.     smux_reqid++;
  1139.     if (exact)
  1140.         type = SMUX_GET;
  1141.     else
  1142.         type = SMUX_GETNEXT;
  1143.     if (smux_build(type, smux_reqid, objid, len, 0, NULL,
  1144.                    *len, packet, &length) < 0) {
  1145.         snmp_log(LOG_ERR, "[smux_snmp_process]: smux_build failedn");
  1146.         return NULL;
  1147.     }
  1148.     DEBUGMSGTL(("smux", "[smux_snmp_process] oid from build: "));
  1149.     DEBUGMSGOID(("smux", objid, *len));
  1150.     DEBUGMSG(("smux", "n"));
  1151.     if (send(sd, (char *) packet, length, 0) < 0) {
  1152.         snmp_log_perror("[smux_snmp_process] send failed");
  1153.     }
  1154.     DEBUGMSGTL(("smux",
  1155.                 "[smux_snmp_process] Sent %d request to peer; %d bytesn",
  1156.                 (int) type, length));
  1157.     while (1) {
  1158.         /*
  1159.          * peek at what's received 
  1160.          */
  1161.         length = recv(sd, (char *) result, SMUXMAXPKTSIZE, MSG_PEEK);
  1162.         if (length < 0) {
  1163.             snmp_log_perror("[smux_snmp_process] peek failed");
  1164.             smux_peer_cleanup(sd);
  1165.             return NULL;
  1166.         }
  1167.         DEBUGMSGTL(("smux", "[smux_snmp_process] Peeked at %d bytesn",
  1168.                     length));
  1169.         DEBUGDUMPSETUP("smux_snmp_process", result, length);
  1170.         /*
  1171.          * determine if we received more than one packet 
  1172.          */
  1173.         packet_len = length;
  1174.         ptr = asn_parse_header(result, &packet_len, &type);
  1175.         packet_len += (ptr - result);
  1176.         if (length > packet_len) {
  1177.             /*
  1178.              * set length to receive only the first packet 
  1179.              */
  1180.             length = packet_len;
  1181.         }
  1182.         /*
  1183.          * receive the first packet 
  1184.          */
  1185.         length = recv(sd, (char *) result, length, 0);
  1186.         if (length < 0) {
  1187.             snmp_log_perror("[smux_snmp_process] recv failed");
  1188.             smux_peer_cleanup(sd);
  1189.             return NULL;
  1190.         }
  1191.         DEBUGMSGTL(("smux", "[smux_snmp_process] Received %d bytesn",
  1192.                     length));
  1193.         if (result[0] == SMUX_TRAP) {
  1194.             DEBUGMSGTL(("smux", "[smux_snmp_process] Received trapn"));
  1195.             snmp_log(LOG_INFO, "Got trap from peer on fd %dn", sd);
  1196.             ptr = asn_parse_header(result, &length, &type);
  1197.             smux_trap_process(ptr, &length);
  1198.             /*
  1199.              * go and peek at received data again 
  1200.              */
  1201.             /*
  1202.              * we could receive the reply or another trap 
  1203.              */
  1204.         } else {
  1205.             /*
  1206.              * Interpret reply 
  1207.              */
  1208.             ptr = smux_parse(result, objid, len, return_len, return_type);
  1209.             /*
  1210.              * ptr will point to query result or NULL if error 
  1211.              */
  1212.             break;
  1213.         }
  1214.     }                           /* while (1) */
  1215.     return ptr;
  1216. }
  1217. static u_char  *
  1218. smux_parse(u_char * rsp,
  1219.            oid * objid,
  1220.            size_t * oidlen, size_t * return_len, u_char * return_type)
  1221. {
  1222.     size_t          length = SMUXMAXPKTSIZE;
  1223.     u_char         *ptr, type;
  1224.     long            reqid, errstat, errindex;
  1225.     ptr = rsp;
  1226.     /*
  1227.      * Return pointer to the snmp/smux return value.
  1228.      * return_len should contain the number of bytes in the value
  1229.      * returned above.
  1230.      * objid is the next object, with len for GETNEXT.
  1231.      * objid and len are not changed for GET
  1232.      */
  1233.     ptr = asn_parse_header(ptr, &length, &type);
  1234.     if (ptr == NULL || type != SNMP_MSG_RESPONSE)
  1235.         return NULL;
  1236.     if ((ptr = asn_parse_int(ptr, &length, &type, &reqid,
  1237.                              sizeof(reqid))) == NULL) {
  1238.         DEBUGMSGTL(("smux", "[smux_parse] parse of reqid failedn"));
  1239.         return NULL;
  1240.     }
  1241.     if ((ptr = asn_parse_int(ptr, &length, &type, &errstat,
  1242.                              sizeof(errstat))) == NULL) {
  1243.         DEBUGMSGTL(("smux",
  1244.                     "[smux_parse] parse of error status failedn"));
  1245.         return NULL;
  1246.     }
  1247.     if ((ptr = asn_parse_int(ptr, &length, &type, &errindex,
  1248.                              sizeof(errindex))) == NULL) {
  1249.         DEBUGMSGTL(("smux", "[smux_parse] parse of error index failedn"));
  1250.         return NULL;
  1251.     }
  1252.     /*
  1253.      * XXX How to send something intelligent back in case of an error 
  1254.      */
  1255.     DEBUGMSGTL(("smux",
  1256.                 "[smux_parse] Message type %d, reqid %d, errstat %d, nterrindex %dn",
  1257.                 (int) type, reqid, errstat, errindex));
  1258.     if (ptr == NULL || errstat != SNMP_ERR_NOERROR)
  1259.         return NULL;
  1260.     /*
  1261.      * stuff to return 
  1262.      */
  1263.     return (smux_parse_var
  1264.             (ptr, &length, objid, oidlen, return_len, return_type));
  1265. }
  1266. static u_char  *
  1267. smux_parse_var(u_char * varbind,
  1268.                size_t * varbindlength,
  1269.                oid * objid,
  1270.                size_t * oidlen, size_t * varlength, u_char * vartype)
  1271. {
  1272.     oid             var_name[MAX_OID_LEN];
  1273.     size_t          var_name_len;
  1274.     size_t          var_val_len;
  1275.     u_char         *var_val;
  1276.     size_t          str_len, objid_len;
  1277.     size_t          len;
  1278.     u_char         *ptr;
  1279.     u_char          type;
  1280.     ptr = varbind;
  1281.     len = *varbindlength;
  1282.     DEBUGMSGTL(("smux", "[smux_parse_var] before any processing: "));
  1283.     DEBUGMSGOID(("smux", objid, *oidlen));
  1284.     DEBUGMSG(("smux", "n"));
  1285.     ptr = asn_parse_header(ptr, &len, &type);
  1286.     if (ptr == NULL || type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
  1287.         snmp_log(LOG_NOTICE, "[smux_parse_var] Panic: type %dn",
  1288.                  (int) type);
  1289.         return NULL;
  1290.     }
  1291.     /*
  1292.      * get hold of the objid and the asn1 coded value 
  1293.      */
  1294.     var_name_len = MAX_OID_LEN;
  1295.     ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, vartype,
  1296.                             &var_val_len, &var_val, &len);
  1297.     *oidlen = var_name_len;
  1298.     memcpy(objid, var_name, var_name_len * sizeof(oid));
  1299.     DEBUGMSGTL(("smux", "[smux_parse_var] returning oid : "));
  1300.     DEBUGMSGOID(("smux", objid, *oidlen));
  1301.     DEBUGMSG(("smux", "n"));
  1302.     /*
  1303.      * XXX 
  1304.      */
  1305.     len = SMUXMAXPKTSIZE;
  1306.     DEBUGMSGTL(("smux",
  1307.                 "[smux_parse_var] Asn coded len of var %d, type %dn",
  1308.                 var_val_len, (int) *vartype));
  1309.     switch ((short) *vartype) {
  1310.     case ASN_INTEGER:
  1311.         *varlength = sizeof(long);
  1312.         asn_parse_int(var_val, &len, vartype,
  1313.                       (long *) &smux_long, *varlength);
  1314.         return (u_char *) & smux_long;
  1315.         break;
  1316.     case ASN_COUNTER:
  1317.     case ASN_GAUGE:
  1318.     case ASN_TIMETICKS:
  1319.     case ASN_UINTEGER:
  1320.         *varlength = sizeof(u_long);
  1321.         asn_parse_unsigned_int(var_val, &len, vartype,
  1322.                                (u_long *) & smux_ulong, *varlength);
  1323.         return (u_char *) & smux_ulong;
  1324.         break;
  1325.     case ASN_COUNTER64:
  1326.         *varlength = sizeof(smux_counter64);
  1327.         asn_parse_unsigned_int64(var_val, &len, vartype,
  1328.                                  (struct counter64 *) &smux_counter64,
  1329.                                  *varlength);
  1330.         return (u_char *) & smux_counter64;
  1331.         break;
  1332.     case ASN_IPADDRESS:
  1333.         *varlength = 4;
  1334.         /*
  1335.          * consume the tag and length, but just copy here
  1336.          * because we know it is an ip address
  1337.          */
  1338.         if ((var_val = asn_parse_header(var_val, &len, &type)) == NULL)
  1339.             return NULL;
  1340.         memcpy((u_char *) & (smux_sa.sin_addr.s_addr), var_val,
  1341.                *varlength);
  1342.         return (u_char *) & (smux_sa.sin_addr.s_addr);
  1343.         break;
  1344.     case ASN_OCTET_STR:
  1345.         /*
  1346.          * XXX 
  1347.          */
  1348.         if (len == 0)
  1349.             return NULL;
  1350.         str_len = SMUXMAXSTRLEN;
  1351.         asn_parse_string(var_val, &len, vartype, smux_str, &str_len);
  1352.         *varlength = str_len;
  1353.         return smux_str;
  1354.         break;
  1355.     case ASN_OPAQUE:
  1356.     case ASN_NSAP:
  1357.     case ASN_OBJECT_ID:
  1358.         objid_len = MAX_OID_LEN;
  1359.         asn_parse_objid(var_val, &len, vartype, smux_objid, &objid_len);
  1360.         *varlength = objid_len * sizeof(oid);
  1361.         return (u_char *) smux_objid;
  1362.         break;
  1363.     case SNMP_NOSUCHOBJECT:
  1364.     case SNMP_NOSUCHINSTANCE:
  1365.     case SNMP_ENDOFMIBVIEW:
  1366.     case ASN_NULL:
  1367.         return NULL;
  1368.         break;
  1369.     case ASN_BIT_STR:
  1370.         /*
  1371.          * XXX 
  1372.          */
  1373.         if (len == 0)
  1374.             return NULL;
  1375.         str_len = SMUXMAXSTRLEN;
  1376.         asn_parse_bitstring(var_val, &len, vartype, smux_str, &str_len);
  1377.         *varlength = str_len;
  1378.         return (u_char *) smux_str;
  1379.         break;
  1380.     default:
  1381.         snmp_log(LOG_ERR, "bad type returned (%x)n", *vartype);
  1382.         return NULL;
  1383.         break;
  1384.     }
  1385. }
  1386. /*
  1387.  * XXX This is a bad hack - do not want to muck with ucd code 
  1388.  */
  1389. static int
  1390. smux_build(u_char type,
  1391.            long reqid,
  1392.            oid * objid,
  1393.            size_t * oidlen,
  1394.            u_char val_type,
  1395.            u_char * val, size_t val_len, u_char * packet, size_t * length)
  1396. {
  1397.     u_char         *ptr, *save1, *save2;
  1398.     size_t          len;
  1399.     long            errstat = 0;
  1400.     long            errindex = 0;
  1401.     /*
  1402.      * leave space for Seq and length 
  1403.      */
  1404.     save1 = packet;
  1405.     ptr = packet + 4;
  1406.     len = *length - 4;
  1407.     /*
  1408.      * build reqid 
  1409.      */
  1410.     ptr = asn_build_int(ptr, &len,
  1411.                                  (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
  1412.                                            ASN_INTEGER), &reqid,
  1413.                                  sizeof(reqid));
  1414.     if (ptr == NULL) {
  1415.         return -1;
  1416.     }
  1417.     /*
  1418.      * build err stat 
  1419.      */
  1420.     ptr = asn_build_int(ptr, &len,
  1421.                         (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
  1422.                                   ASN_INTEGER), &errstat, sizeof(errstat));
  1423.     if (ptr == NULL) {
  1424.         return -1;
  1425.     }
  1426.     /*
  1427.      * build err index 
  1428.      */
  1429.     ptr = asn_build_int(ptr, &len,
  1430.                         (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
  1431.                                   ASN_INTEGER), &errindex,
  1432.                         sizeof(errindex));
  1433.     if (ptr == NULL) {
  1434.         return -1;
  1435.     }
  1436.     save2 = ptr;
  1437.     ptr += 4;
  1438.     len -= 4;
  1439.     if (type != SMUX_SET) {
  1440.         val_type = ASN_NULL;
  1441.         val_len = 0;
  1442.     }
  1443.     /*
  1444.      * build var list : snmp_build_var_op not liked by gated XXX 
  1445.      */
  1446.     ptr = snmp_build_var_op(ptr, objid, oidlen, val_type, val_len,
  1447.                             val, &len);
  1448.     if (ptr == NULL) {
  1449.         return -1;
  1450.     }
  1451.     len = ptr - save1;
  1452.     asn_build_sequence(save1, &len, type, (ptr - save1 - 4));
  1453.     len = ptr - save2;
  1454.     asn_build_sequence(save2, &len,
  1455.                        (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  1456.                        (ptr - save2 - 4));
  1457.     *length = ptr - packet;
  1458.     return 0;
  1459. }
  1460. static void
  1461. smux_peer_cleanup(int sd)
  1462. {
  1463.     smux_reg       *nrptr, *rptr, *rptr2;
  1464.     int             nfound, i;
  1465.     nfound = 0;
  1466.     /*
  1467.      * close the descriptor 
  1468.      */
  1469.     close(sd);
  1470.     /*
  1471.      * delete all of the passive registrations that this peer owns 
  1472.      */
  1473.     for (rptr = PassiveRegs; rptr; rptr = nrptr) {
  1474.         nrptr = rptr->sr_next;
  1475.         if (rptr->sr_fd == sd) {
  1476.             smux_list_detach(&PassiveRegs, &rptr);
  1477.             free(rptr);
  1478.         }
  1479.         rptr = nrptr;
  1480.     }
  1481.     /*
  1482.      * find replacements for all of the active registrations found 
  1483.      */
  1484.     for (rptr = ActiveRegs; rptr; rptr = rptr2) {
  1485.         rptr2 = rptr->sr_next;
  1486.         if (rptr->sr_fd == sd) {
  1487.             smux_list_detach(&ActiveRegs, &rptr);
  1488.             unregister_mib(rptr->sr_name, rptr->sr_name_len);
  1489.             if ((nrptr = smux_find_replacement(rptr->sr_name,
  1490.                                                rptr->sr_name_len)) !=
  1491.                 NULL) {
  1492.                 smux_list_detach(&PassiveRegs, &nrptr);
  1493.                 smux_list_add(&ActiveRegs, nrptr);
  1494.                 register_mib("smux", (struct variable *)
  1495.                              smux_variables, sizeof(struct variable2),
  1496.                              1, nrptr->sr_name, nrptr->sr_name_len);
  1497.             }
  1498.             free(rptr);
  1499.         }
  1500.     }
  1501.     /*
  1502.      * decrement the peer count 
  1503.      */
  1504.     npeers--;
  1505.     /*
  1506.      * make his auth available again 
  1507.      */
  1508.     for (i = 0; i < nauths; i++) {
  1509.         if (Auths[i]->sa_active_fd == sd) {
  1510.             char            oid_name[128];
  1511.             Auths[i]->sa_active_fd = -1;
  1512.             snprint_objid(oid_name, sizeof(oid_name), Auths[i]->sa_oid,
  1513.                           Auths[i]->sa_oid_len);
  1514.             snmp_log(LOG_INFO, "peer disconnected: %sn", oid_name);
  1515.         }
  1516.     }
  1517. }
  1518. int
  1519. smux_send_rrsp(int sd, int pri)
  1520. {
  1521.     u_char          outdata[2 + sizeof(int)];
  1522.     u_char         *ptr = outdata;
  1523.     int             intsize = sizeof(int);
  1524.     u_int           mask = ((u_int) 0xFF) << (8 * (sizeof(int) - 1));
  1525.     /*
  1526.      * e.g. mask is 0xFF000000 on a 32-bit machine 
  1527.      */
  1528.     int             sent;
  1529.     /*
  1530.      * This is kind of like calling asn_build_int(), but the
  1531.      * encoding will always be the size of an integer on this
  1532.      * machine, never shorter.
  1533.      */
  1534.     *ptr++ = (u_char) SMUX_RRSP;
  1535.     *ptr++ = (u_char) intsize;
  1536.     /*
  1537.      * Copy each byte, most significant first. 
  1538.      */
  1539.     while (intsize--) {
  1540.         *ptr++ = (u_char) ((pri & mask) >> (8 * (sizeof(int) - 1)));
  1541.         pri <<= 8;
  1542.     }
  1543.     sent = send(sd, (char *) outdata, sizeof outdata, 0);
  1544.     if (sent < 0) {
  1545.         DEBUGMSGTL(("smux", "[smux_send_rrsp] send failedn"));
  1546.     }
  1547.     return (sent);
  1548. }
  1549. static u_char  *
  1550. smux_trap_process(u_char * rsp, size_t * len)
  1551. {
  1552.     oid             sa_enterpriseoid[MAX_OID_LEN], var_name[MAX_OID_LEN];
  1553.     size_t          datalen, var_name_len, var_val_len, maxlen;
  1554.     size_t          sa_enterpriseoid_len;
  1555.     u_char          vartype, *ptr, *var_val;
  1556.     long            trap, specific;
  1557.     u_long          timestamp;
  1558.     netsnmp_variable_list *snmptrap_head, *snmptrap_ptr, *snmptrap_tmp;
  1559.     snmptrap_head = NULL;
  1560.     snmptrap_ptr = NULL;
  1561.     ptr = rsp;
  1562.     /*
  1563.      * parse the sub-agent enterprise oid 
  1564.      */
  1565.     sa_enterpriseoid_len = MAX_OID_LEN;
  1566.     if ((ptr = asn_parse_objid(ptr, len,
  1567.                                &vartype, (oid *) & sa_enterpriseoid,
  1568.                                &sa_enterpriseoid_len)) == NULL) {
  1569.         DEBUGMSGTL(("smux",
  1570.                     "[smux_trap_process] asn_parse_objid failedn"));
  1571.         return NULL;
  1572.     }
  1573.     /*
  1574.      * parse the agent-addr ipAddress 
  1575.      */
  1576.     datalen = SMUXMAXSTRLEN;
  1577.     if (((ptr = asn_parse_string(ptr, len,
  1578.                                  &vartype, smux_str,
  1579.                                  &datalen)) == NULL) ||
  1580.         (vartype != (u_char) ASN_IPADDRESS)) {
  1581.         DEBUGMSGTL(("smux",
  1582.                     "[smux_trap_process] asn_parse_string failedn"));
  1583.         return NULL;
  1584.     }
  1585.     /*
  1586.      * parse the generic trap int 
  1587.      */
  1588.     datalen = sizeof(long);
  1589.     if ((ptr = asn_parse_int(ptr, len, &vartype, &trap, datalen)) == NULL) {
  1590.         DEBUGMSGTL(("smux",
  1591.                     "[smux_trap_process] asn_parse_int generic failedn"));
  1592.         return NULL;
  1593.     }
  1594.     /*
  1595.      * parse the specific trap int 
  1596.      */
  1597.     datalen = sizeof(long);
  1598.     if ((ptr = asn_parse_int(ptr, len,
  1599.                              &vartype, &specific, datalen)) == NULL) {
  1600.         DEBUGMSGTL(("smux",
  1601.                     "[smux_trap_process] asn_parse_int specific failedn"));
  1602.         return NULL;
  1603.     }
  1604.     /*
  1605.      * parse the timeticks timestamp 
  1606.      */
  1607.     datalen = sizeof(u_long);
  1608.     if (((ptr = asn_parse_unsigned_int(ptr, len,
  1609.                                        &vartype, (u_long *) & timestamp,
  1610.                                        datalen)) == NULL) ||
  1611.         (vartype != (u_char) ASN_TIMETICKS)) {
  1612.         DEBUGMSGTL(("smux",
  1613.                     "[smux_trap_process] asn_parse_unsigned_int (timestamp) failedn"));
  1614.         return NULL;
  1615.     }
  1616.     /*
  1617.      * parse out the overall sequence 
  1618.      */
  1619.     ptr = asn_parse_header(ptr, len, &vartype);
  1620.     if (ptr == NULL || vartype != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
  1621.         return NULL;
  1622.     }
  1623.     /*
  1624.      * parse the variable bindings 
  1625.      */
  1626.     while (ptr && *len) {
  1627.         /*
  1628.          * get the objid and the asn1 coded value 
  1629.          */
  1630.         var_name_len = MAX_OID_LEN;
  1631.         ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, &vartype,
  1632.                                 &var_val_len, (u_char **) & var_val, len);
  1633.         if (ptr == NULL) {
  1634.             return NULL;
  1635.         }
  1636.         maxlen = SMUXMAXPKTSIZE;
  1637.         switch ((short) vartype) {
  1638.         case ASN_INTEGER:
  1639.             var_val_len = sizeof(long);
  1640.             asn_parse_int(var_val, &maxlen, &vartype,
  1641.                           (long *) &smux_long, var_val_len);
  1642.             var_val = (u_char *) & smux_long;
  1643.             break;
  1644.         case ASN_COUNTER:
  1645.         case ASN_GAUGE:
  1646.         case ASN_TIMETICKS:
  1647.         case ASN_UINTEGER:
  1648.             var_val_len = sizeof(u_long);
  1649.             asn_parse_unsigned_int(var_val, &maxlen, &vartype,
  1650.                                    (u_long *) & smux_ulong, var_val_len);
  1651.             var_val = (u_char *) & smux_ulong;
  1652.             break;
  1653.         case ASN_COUNTER64:
  1654.             var_val_len = sizeof(smux_counter64);
  1655.             asn_parse_unsigned_int64(var_val, &maxlen, &vartype,
  1656.                                      (struct counter64 *) &smux_counter64,
  1657.                                      var_val_len);
  1658.             var_val = (u_char *) & smux_counter64;
  1659.             break;
  1660.         case ASN_IPADDRESS:
  1661.             var_val_len = 4;
  1662.             /*
  1663.              * consume the tag and length, but just copy here
  1664.              * because we know it is an ip address
  1665.              */
  1666.             if ((var_val =
  1667.                  asn_parse_header(var_val, &maxlen, &vartype)) == NULL)
  1668.                 return NULL;
  1669.             memcpy((u_char *) & (smux_sa.sin_addr.s_addr), var_val,
  1670.                    var_val_len);
  1671.             var_val = (u_char *) & (smux_sa.sin_addr.s_addr);
  1672.             break;
  1673.         case ASN_OPAQUE:
  1674.         case ASN_OCTET_STR:
  1675.             /*
  1676.              * XXX 
  1677.              */
  1678.             if (len == 0)
  1679.                 return NULL;
  1680.             var_val_len = SMUXMAXSTRLEN;
  1681.             asn_parse_string(var_val, &maxlen, &vartype,
  1682.                              smux_str, &var_val_len);
  1683.             var_val = smux_str;
  1684.             break;
  1685.         case ASN_OBJECT_ID:
  1686.             var_val_len = MAX_OID_LEN;
  1687.             asn_parse_objid(var_val, &maxlen, &vartype,
  1688.                             smux_objid, &var_val_len);
  1689.             var_val_len *= sizeof(oid);
  1690.             var_val = (u_char *) smux_objid;
  1691.             break;
  1692.         case SNMP_NOSUCHOBJECT:
  1693.         case SNMP_NOSUCHINSTANCE:
  1694.         case SNMP_ENDOFMIBVIEW:
  1695.         case ASN_NULL:
  1696.             var_val = NULL;
  1697.             break;
  1698.         case ASN_BIT_STR:
  1699.             /*
  1700.              * XXX 
  1701.              */
  1702.             if (len == 0)
  1703.                 return NULL;
  1704.             var_val_len = SMUXMAXSTRLEN;
  1705.             asn_parse_bitstring(var_val, &maxlen, &vartype,
  1706.                                 smux_str, &var_val_len);
  1707.             var_val = (u_char *) smux_str;
  1708.             break;
  1709.         case ASN_NSAP:
  1710.         default:
  1711.             snmp_log(LOG_ERR, "bad type returned (%x)n", vartype);
  1712.             var_val = NULL;
  1713.             break;
  1714.         }
  1715.         snmptrap_tmp =
  1716.             (netsnmp_variable_list *)
  1717.             malloc(sizeof(netsnmp_variable_list));
  1718.         if (snmptrap_tmp == NULL)
  1719.             return NULL;
  1720.         memset(snmptrap_tmp, 0, sizeof(netsnmp_variable_list));
  1721.         if (snmptrap_head == NULL) {
  1722.             snmptrap_head = snmptrap_tmp;
  1723.             snmptrap_ptr = snmptrap_head;
  1724.         } else {
  1725.             snmptrap_ptr->next_variable = snmptrap_tmp;
  1726.             snmptrap_ptr = snmptrap_ptr->next_variable;
  1727.         }
  1728.         snmp_set_var_objid(snmptrap_ptr, var_name, var_name_len);
  1729.         snmp_set_var_value(snmptrap_ptr, (char *) var_val, var_val_len);
  1730.         snmptrap_ptr->type = vartype;
  1731.         snmptrap_ptr->next_variable = NULL;
  1732.     }
  1733.     /*
  1734.      * send the traps 
  1735.      */
  1736.     send_enterprise_trap_vars(trap, specific, (oid *) & sa_enterpriseoid,
  1737.                               sa_enterpriseoid_len, snmptrap_head);
  1738.     /*
  1739.      * free trap variables 
  1740.      */
  1741.     snmp_free_varbind(snmptrap_head);
  1742.     return ptr;
  1743. }