⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smux.c

📁 snmp的源代码,已经在我的ubuntu下编译通过
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Smux module authored by Rohit Dube. * Rewritten by Nick Amato <naamato@merit.net>. */#include <net-snmp/net-snmp-config.h>#include <sys/types.h>#include <ctype.h>#if HAVE_IO_H                   /* win32 */#include <io.h>#endif#include <stdio.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_ERR_H#include <err.h>#endif#if TIME_WITH_SYS_TIME# ifdef WIN32#  include <sys/timeb.h># else#  include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include <errno.h>#if HAVE_NETDB_H#include <netdb.h>#endif#include <sys/stat.h>#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#elif HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_SYS_FILIO_H#include <sys/filio.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include "smux.h"#include "util_funcs.h"#include "mibdefs.h"#include "snmpd.h"long            smux_long;u_long          smux_ulong;struct sockaddr_in smux_sa;struct counter64 smux_counter64;oid             smux_objid[MAX_OID_LEN];u_char          smux_str[SMUXMAXSTRLEN];int             smux_listen_sd = -1;static struct timeval smux_rcv_timeout;static u_long   smux_reqid;void            init_smux(void);static u_char  *smux_open_process(int, u_char *, size_t *, int *);static u_char  *smux_rreq_process(int, u_char *, size_t *);static u_char  *smux_close_process(int, u_char *, size_t *);static u_char  *smux_trap_process(u_char *, size_t *);static u_char  *smux_parse(u_char *, oid *, size_t *, size_t *, u_char *);static u_char  *smux_parse_var(u_char *, size_t *, oid *, size_t *,                               size_t *, u_char *);static void     smux_send_close(int, int);static void     smux_list_detach(smux_reg **, smux_reg **);static void     smux_replace_active(smux_reg *, smux_reg *);static void     smux_peer_cleanup(int);static int      smux_auth_peer(oid *, size_t, char *, int);static int      smux_build(u_char, u_long, oid *,                           size_t *, u_char, u_char *, size_t, u_char *,                           size_t *);static int      smux_list_add(smux_reg **, smux_reg *);static int      smux_pdu_process(int, u_char *, size_t);static int      smux_send_rrsp(int, int);static smux_reg *smux_find_match(smux_reg *, int, oid *, size_t, long);static smux_reg *smux_find_replacement(oid *, size_t);u_char         *var_smux(struct variable *, oid *, size_t *, int, size_t *,                         WriteMethod ** write_method);int             var_smux_write(int, u_char *, u_char, size_t, u_char *,                               oid *, size_t);static smux_reg *ActiveRegs;    /* Active registrations                 */static smux_reg *PassiveRegs;   /* Currently unused registrations       */static smux_peer_auth *Auths[SMUX_MAX_PEERS];   /* Configured peers */static int      nauths, npeers = 0;struct variable2 smux_variables[] = {    /*     * bogus entry, as in pass.c      */    {MIBINDEX, ASN_INTEGER, RWRITE, var_smux, 0, {MIBINDEX}},};voidsmux_parse_smux_socket(const char *token, char *cptr){    DEBUGMSGTL(("smux", "port spec: %s\n", cptr));    netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_SMUX_SOCKET, cptr);}voidsmux_parse_peer_auth(const char *token, char *cptr){    smux_peer_auth *aptr;    if ((aptr =         (smux_peer_auth *) calloc(1, sizeof(smux_peer_auth))) == NULL) {        snmp_log_perror("smux_parse_peer_auth: malloc");        return;    }    aptr->sa_active_fd = -1;    if (!cptr) {        /*         * null passwords OK          */        Auths[nauths++] = aptr;        DEBUGMSGTL(("smux_conf", "null password\n"));        return;    }    if (*cptr == '.')        cptr++;    if (!isdigit(*cptr)) {        config_perror("second token is not an OID");        free((char *) aptr);        return;    }    /*     * oid      */    aptr->sa_oid_len = parse_miboid(cptr, aptr->sa_oid);    DEBUGMSGTL(("smux_conf", "parsing registration for: %s\n", cptr));    while (isdigit(*cptr) || *cptr == '.')        cptr++;    cptr = skip_white(cptr);    /*     * password      */    if (cptr)        strcpy(aptr->sa_passwd, cptr);    Auths[nauths++] = aptr;}voidsmux_free_peer_auth(void){    int             i;    for (i = 0; i < nauths; i++) {        free(Auths[i]);        Auths[i] = NULL;    }    nauths = 0;}voidinit_smux(void){    snmpd_register_config_handler("smuxpeer", smux_parse_peer_auth,                                  smux_free_peer_auth,                                  "OID-IDENTITY PASSWORD");    snmpd_register_config_handler("smuxsocket",                                  smux_parse_smux_socket, NULL,                                  "SMUX bind address");}voidreal_init_smux(void){    struct sockaddr_in lo_socket;    char           *smux_socket;    int             one = 1;    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {        smux_listen_sd = -1;        return;    }    /*     * Reqid      */    smux_reqid = 0;    smux_listen_sd = -1;    /*     * Receive timeout      */    smux_rcv_timeout.tv_sec = 0;    smux_rcv_timeout.tv_usec = 500000;    /*     * Get ready to listen on the SMUX port     */    memset(&lo_socket, (0), sizeof(lo_socket));    lo_socket.sin_family = AF_INET;    smux_socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 					NETSNMP_DS_SMUX_SOCKET);#ifdef LOCAL_SMUX    if (!smux_socket)        smux_socket = "127.0.0.1";   /* By default, listen on localhost only */#endif    netsnmp_sockaddr_in( &lo_socket, smux_socket, SMUXPORT );    if ((smux_listen_sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        snmp_log_perror("[init_smux] socket failed");        return;    }#ifdef SO_REUSEADDR    /*     * At least on Linux, when the master agent terminates, any     * TCP connections for SMUX peers are put in the TIME_WAIT     * state for about 60 seconds. If the master agent is started     * during this time, the bind for the listening socket will     * fail because the SMUX port is in use.     */    if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,                   sizeof(one)) < 0) {        snmp_log_perror("[init_smux] setsockopt(SO_REUSEADDR) failed");    }#endif                          /* SO_REUSEADDR */    if (bind(smux_listen_sd, (struct sockaddr *) &lo_socket,             sizeof(lo_socket)) < 0) {        snmp_log_perror("[init_smux] bind failed");        close(smux_listen_sd);        smux_listen_sd = -1;        return;    }#ifdef	SO_KEEPALIVE    if (setsockopt(smux_listen_sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,                   sizeof(one)) < 0) {        snmp_log_perror("[init_smux] setsockopt(SO_KEEPALIVE) failed");        close(smux_listen_sd);        smux_listen_sd = -1;        return;    }#endif                          /* SO_KEEPALIVE */    if (listen(smux_listen_sd, SOMAXCONN) == -1) {        snmp_log_perror("[init_smux] listen failed");        close(smux_listen_sd);        smux_listen_sd = -1;        return;    }    DEBUGMSGTL(("smux_init",                "[smux_init] done; smux listen sd is %d, smux port is %d\n",                smux_listen_sd, ntohs(lo_socket.sin_port)));}u_char         *var_smux(struct variable * vp,         oid * name,         size_t * length,         int exact, size_t * var_len, WriteMethod ** write_method){    u_char         *valptr, val_type;    smux_reg       *rptr;    *write_method = var_smux_write;    /*     * search the active registration list      */    for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {        if (0 >= snmp_oidtree_compare(vp->name, vp->namelen, rptr->sr_name,                                      rptr->sr_name_len))            break;    }    if (rptr == NULL)        return NULL;    else if (exact && (*length < rptr->sr_name_len))        return NULL;    valptr = smux_snmp_process(exact, name, length,                               var_len, &val_type, rptr->sr_fd);    if (valptr == NULL)        return NULL;    if ((snmp_oidtree_compare(name, *length, rptr->sr_name,                              rptr->sr_name_len)) != 0) {        /*         * the peer has returned a value outside         * * of the registered tree         */        return NULL;    } else {        /*         * set the type and return the value          */        vp->type = val_type;        return valptr;    }}intvar_smux_write(int action,               u_char * var_val,               u_char var_val_type,               size_t var_val_len,               u_char * statP, oid * name, size_t name_len){    smux_reg       *rptr;    u_char          buf[SMUXMAXPKTSIZE], *ptr, sout[3], type;    int             reterr;    size_t          var_len, datalen, name_length, packet_len;    ssize_t         len;    long            reqid, errsts, erridx;    u_char          var_type, *dataptr;    DEBUGMSGTL(("smux", "[var_smux_write] entering var_smux_write\n"));    len = SMUXMAXPKTSIZE;    reterr = SNMP_ERR_NOERROR;    var_len = var_val_len;    var_type = var_val_type;    name_length = name_len;    /*     * XXX find the descriptor again      */    for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {        if (!snmp_oidtree_compare(name, name_len, rptr->sr_name,                                  rptr->sr_name_len))            break;    }    switch (action) {    case RESERVE1:        DEBUGMSGTL(("smux", "[var_smux_write] entering RESERVE1\n"));        /*         * length might be long          */        var_len += (*(var_val + 1) & ASN_LONG_LEN) ?            var_len + ((*(var_val + 1) & 0x7F) + 2) : 2;        switch (var_val_type) {        case ASN_INTEGER:        case ASN_OCTET_STR:        case ASN_COUNTER:        case ASN_GAUGE:        case ASN_TIMETICKS:        case ASN_UINTEGER:        case ASN_COUNTER64:        case ASN_IPADDRESS:        case ASN_OPAQUE:        case ASN_NSAP:        case ASN_OBJECT_ID:        case ASN_BIT_STR:            datalen = var_val_len;            dataptr = var_val;            break;        case SNMP_NOSUCHOBJECT:        case SNMP_NOSUCHINSTANCE:        case SNMP_ENDOFMIBVIEW:        case ASN_NULL:        default:            DEBUGMSGTL(("smux",                        "[var_smux_write] variable not supported\n"));            return SNMP_ERR_GENERR;            break;        }        if ((smux_build((u_char) SMUX_SET, smux_reqid,                        name, &name_length, var_val_type, dataptr,                        datalen, buf, &len)) < 0) {            DEBUGMSGTL(("smux", "[var_smux_write] smux build failed\n"));            return SNMP_ERR_GENERR;        }        if (send(rptr->sr_fd, buf, len, 0) < 0) {            DEBUGMSGTL(("smux", "[var_smux_write] send failed\n"));            return SNMP_ERR_GENERR;        }        while (1) {            /*             * peek at what's received              */            if ((len = recv(rptr->sr_fd, buf,                            SMUXMAXPKTSIZE, MSG_PEEK)) <= 0) {                DEBUGMSGTL(("smux",                            "[var_smux_write] peek failed or timed out\n"));                /*                 * do we need to do a peer cleanup in this case??                  */                smux_peer_cleanup(rptr->sr_fd);                return SNMP_ERR_GENERR;            }            DEBUGMSGTL(("smux", "[var_smux_write] Peeked at %d bytes\n",                        len));            DEBUGDUMPSETUP("var_smux_write", buf, len);            /*             * determine if we received more than one packet              */            packet_len = len;            ptr = asn_parse_header(buf, &packet_len, &type);            packet_len += (ptr - buf);            if (len > (ssize_t)packet_len) {                /*                 * set length to receive only the first packet                  */                len = packet_len;            }            /*             * receive the first packet              */            if ((len = recv(rptr->sr_fd, buf, len, 0)) <= 0) {                DEBUGMSGTL(("smux",                            "[var_smux_write] recv failed or timed out\n"));                /*                 * do we need to do a peer cleanup in this case??                  */                smux_peer_cleanup(rptr->sr_fd);                return SNMP_ERR_GENERR;            }            DEBUGMSGTL(("smux", "[var_smux_write] Received %d bytes\n",                        len));            if (buf[0] == SMUX_TRAP) {                DEBUGMSGTL(("smux", "[var_smux_write] Received trap\n"));                snmp_log(LOG_INFO, "Got trap from peer on fd %d\n",                         rptr->sr_fd);                ptr = asn_parse_header(buf, &len, &type);                smux_trap_process(ptr, &len);                /*                 * go and peek at received data again                  */                /*                 * we could receive the reply or another trap                  */            } else {                ptr = buf;                ptr = asn_parse_header(ptr, &len, &type);                if ((ptr == NULL) || type != SNMP_MSG_RESPONSE)                    return SNMP_ERR_GENERR;                ptr =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -