Blame apps/agentxtrap.c

Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
Packit fcad23
#include <errno.h>
Packit fcad23
#include <signal.h>
Packit fcad23
#include <string.h>
Packit fcad23
#ifdef HAVE_UNISTD_H
Packit fcad23
#include <unistd.h> /* optind, optarg and optopt */
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/agent/ds_agent.h>
Packit fcad23
#include "../agent_global_vars.h"
Packit fcad23
Packit fcad23
#include "../agent/mibgroup/agentx/agentx_config.h"
Packit fcad23
#include "../agent/mibgroup/agentx/client.h"
Packit fcad23
#include "../agent/mibgroup/agentx/protocol.h"
Packit fcad23
#include "../agent/mibgroup/agentx/subagent.h"
Packit fcad23
Packit fcad23
netsnmp_feature_require(snmp_split_pdu)
Packit fcad23
netsnmp_feature_require(snmp_reset_var_types)
Packit fcad23
Packit fcad23
Packit fcad23
static void
Packit fcad23
usage(const char* progname)
Packit fcad23
{
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "USAGE: %s [OPTIONS] TRAP-PARAMETERS\n"
Packit fcad23
            "\n"
Packit fcad23
            "  Version:  %s\n"
Packit fcad23
            "  Web:      http://www.net-snmp.org/\n"
Packit fcad23
            "  Email:    net-snmp-coders@lists.sourceforge.net\n"
Packit fcad23
            "\n"
Packit fcad23
            "OPTIONS:\n", progname, netsnmp_get_version());
Packit fcad23
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -h\t\t\tdisplay this help message\n"
Packit fcad23
            "  -V\t\t\tdisplay package version number\n"
Packit fcad23
            "  -m MIB[" ENV_SEPARATOR "...]\t\tload given list of MIBs (ALL loads "
Packit fcad23
            "everything)\n"
Packit fcad23
            "  -M DIR[" ENV_SEPARATOR "...]\t\tlook in given list of directories for MIBs\n"
Packit fcad23
            "  -D[TOKEN[,...]]\tturn on debugging output for the specified "
Packit fcad23
            "TOKENs\n"
Packit fcad23
            "\t\t\t   (ALL gives extremely verbose debugging output)\n"
Packit fcad23
            "  -d\t\t\tdump all traffic\n");
Packit fcad23
#ifndef NETSNMP_DISABLE_MIB_LOADING
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -P MIBOPTS\t\tToggle various defaults controlling mib "
Packit fcad23
            "parsing:\n");
Packit fcad23
    snmp_mib_toggle_options_usage("\t\t\t  ", stderr);
Packit fcad23
#endif /* NETSNMP_DISABLE_MIB_LOADING */
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
Packit fcad23
    snmp_log_options_usage("\t\t\t  ", stderr);
Packit fcad23
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -c context\n"
Packit fcad23
            "  -U uptime\n"
Packit fcad23
            "  -x ADDRESS\t\tuse ADDRESS as AgentX address\n"
Packit fcad23
            "\n"
Packit fcad23
            "TRAP-PARAMETERS:\n"
Packit fcad23
            "  trapoid [OID TYPE VALUE] ...\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
struct tState_s;
Packit fcad23
typedef const struct tState_s* tState;
Packit fcad23
struct tState_s {
Packit fcad23
    void (*entry)(tState self); /**<< State entry action */
Packit fcad23
    void (*exit)(tState self); /**<< State exit action */
Packit fcad23
    /** Handler for AgentX-Response-PDU's */
Packit fcad23
    void (*response)(tState self, netsnmp_pdu *res);
Packit fcad23
    /** State to change to if an AgentX timeout occurs or the timer runs out */
Packit fcad23
    tState timeout;
Packit fcad23
    void (*disconnect)(tState self); /**<< Handler for disconnect indications */
Packit fcad23
    /** Handler for Close-PDU indications */
Packit fcad23
    void (*close)(tState self, netsnmp_pdu *res);
Packit fcad23
    const char* name; /**<< Name of the current state */
Packit fcad23
    int is_open; /**<< If the connection is open in this state */
Packit fcad23
};
Packit fcad23
Packit fcad23
static tState state; /**<< Current state of the state machine */
Packit fcad23
static tState next_state; /**<< Next state of the state machine */
Packit fcad23
Packit fcad23
static const char  *context = NULL; /**<< Context that delivers the trap */
Packit fcad23
static size_t       contextLen; /**<< Length of eventual context */
Packit fcad23
static int          result = 1; /**<< Program return value */
Packit fcad23
static netsnmp_pdu *pdu = NULL; /**<< The trap pdu that is to be sent */
Packit fcad23
/** The reference number of the next packet */
Packit fcad23
static long         packetid = 0;
Packit fcad23
/** The session id of the session to the master */
Packit fcad23
static long         session;
Packit fcad23
static void        *sessp = NULL; /**<< The current communication session */
Packit fcad23
Packit fcad23
#define STATE_CALL(method)                                              \
Packit fcad23
    if(!state->method) {                                                \
Packit fcad23
        snmp_log(LOG_ERR, "No " #method " method in %s, terminating\n", \
Packit fcad23
                 state->name);                                          \
Packit fcad23
        abort();                                                        \
Packit fcad23
    } else                                                              \
Packit fcad23
        state->method
Packit fcad23
Packit fcad23
static void
Packit fcad23
change_state(tState new_state)
Packit fcad23
{
Packit fcad23
    if (next_state && next_state != new_state)
Packit fcad23
        DEBUGMSGTL(("process", "Ignore transition to %s\n", next_state->name));
Packit fcad23
    next_state = new_state;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
handle_agentx_response(int operation, netsnmp_session *sp, int reqid,
Packit fcad23
                       netsnmp_pdu *act, void *magic)
Packit fcad23
{
Packit fcad23
    switch(operation) {
Packit fcad23
    case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
Packit fcad23
        if(act->command == AGENTX_MSG_CLEANUPSET) {
Packit fcad23
            /* Do nothing - no response and no action as nothing get
Packit fcad23
             * allocated in any handler here
Packit fcad23
             */
Packit fcad23
        } else if(act->command != AGENTX_MSG_RESPONSE) {
Packit fcad23
            /* Copy the head to a response */
Packit fcad23
            netsnmp_pdu* res = snmp_split_pdu(act, 0, 0);
Packit fcad23
            res->command = AGENTX_MSG_RESPONSE;
Packit fcad23
            if (act->sessid != session || !state->is_open)
Packit fcad23
                res->errstat = AGENTX_ERR_NOT_OPEN;
Packit fcad23
            if(res->errstat == AGENTX_ERR_NOERROR)
Packit fcad23
                switch(act->command) {
Packit fcad23
                case AGENTX_MSG_GET:
Packit fcad23
                    res->variables = snmp_clone_varbind(act->variables);
Packit fcad23
                    snmp_reset_var_types(res->variables, SNMP_NOSUCHOBJECT);
Packit fcad23
                    break;
Packit fcad23
                case AGENTX_MSG_GETNEXT:
Packit fcad23
                case AGENTX_MSG_GETBULK:
Packit fcad23
                    res->variables = snmp_clone_varbind(act->variables);
Packit fcad23
                    snmp_reset_var_types(res->variables, SNMP_ENDOFMIBVIEW);
Packit fcad23
                    break;
Packit fcad23
                case AGENTX_MSG_TESTSET:
Packit fcad23
                    res->errstat = SNMP_ERR_NOTWRITABLE;
Packit fcad23
                    res->errindex = 1;
Packit fcad23
                    break;
Packit fcad23
                case AGENTX_MSG_COMMITSET:
Packit fcad23
                    res->errstat = SNMP_ERR_COMMITFAILED;
Packit fcad23
                    res->errindex = 1;
Packit fcad23
                    break;
Packit fcad23
                case AGENTX_MSG_UNDOSET:
Packit fcad23
                    /* Success - could undo not setting any value :-) */
Packit fcad23
                    break;
Packit fcad23
                case AGENTX_MSG_CLOSE:
Packit fcad23
                    /* Always let the master succeed! */
Packit fcad23
                    break;
Packit fcad23
                default:
Packit fcad23
                    /* Unknown command */
Packit fcad23
                    res->errstat = AGENTX_ERR_PARSE_FAILED;
Packit fcad23
                    break;
Packit fcad23
                }
Packit fcad23
            if(snmp_send(sp, res) == 0)
Packit fcad23
                snmp_free_pdu(res);
Packit fcad23
            switch(act->command) {
Packit fcad23
            case AGENTX_MSG_CLOSE:
Packit fcad23
                /* Take action once the answer is sent! */
Packit fcad23
                STATE_CALL(close)(state, act);
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                /* Do nothing */
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
        } else
Packit fcad23
            /* RESPONSE act->time, act->errstat, act->errindex, varlist */
Packit fcad23
            STATE_CALL(response)(state, act);
Packit fcad23
        break;
Packit fcad23
    case NETSNMP_CALLBACK_OP_TIMED_OUT:
Packit fcad23
        change_state(state->timeout);
Packit fcad23
        break;
Packit fcad23
    case NETSNMP_CALLBACK_OP_DISCONNECT:
Packit fcad23
        STATE_CALL(disconnect)(state);
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
extern const struct tState_s Connecting;
Packit fcad23
extern const struct tState_s Opening;
Packit fcad23
extern const struct tState_s Notifying;
Packit fcad23
extern const struct tState_s Closing;
Packit fcad23
extern const struct tState_s Disconnecting;
Packit fcad23
extern const struct tState_s Exit;
Packit fcad23
Packit fcad23
static void
Packit fcad23
StateDisconnect(tState self)
Packit fcad23
{
Packit fcad23
    snmp_log(LOG_ERR, "Unexpected disconnect in state %s\n", self->name);
Packit fcad23
    change_state(&Disconnecting);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
StateClose(tState self, netsnmp_pdu *act)
Packit fcad23
{
Packit fcad23
    snmp_log(LOG_ERR, "Unexpected close with reason code %ld in state %s\n",
Packit fcad23
             act->errstat, self->name);
Packit fcad23
    change_state(&Disconnecting);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
ConnectingEntry(tState self)
Packit fcad23
{
Packit fcad23
    netsnmp_session init;
Packit fcad23
    netsnmp_transport* t;
Packit fcad23
    void* sess;
Packit fcad23
Packit fcad23
    if(sessp) {
Packit fcad23
        snmp_sess_close(sessp);
Packit fcad23
        sessp = NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snmp_sess_init(&init);
Packit fcad23
    init.version = AGENTX_VERSION_1;
Packit fcad23
    init.retries = 0; /* Retries are handled by the state machine */
Packit fcad23
    init.timeout = SNMP_DEFAULT_TIMEOUT;
Packit fcad23
    init.flags |= SNMP_FLAGS_STREAM_SOCKET;
Packit fcad23
    init.callback = handle_agentx_response;
Packit fcad23
    init.authenticator = NULL;
Packit fcad23
Packit fcad23
    if(!(t = netsnmp_transport_open_client(
Packit fcad23
             "agentx", netsnmp_ds_get_string(
Packit fcad23
                 NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)))) {
Packit fcad23
        snmp_log(LOG_ERR, "Failed to connect to AgentX server\n");
Packit fcad23
        change_state(&Exit;;
Packit fcad23
    } else if(!(sess = snmp_sess_add_ex(
Packit fcad23
                    &init, t, NULL, agentx_parse, NULL, NULL,
Packit fcad23
                    agentx_realloc_build, agentx_check_packet, NULL))) {
Packit fcad23
      snmp_log(LOG_ERR, "Failed to create session\n");
Packit fcad23
        change_state(&Exit;;
Packit fcad23
    } else {
Packit fcad23
        sessp = sess;
Packit fcad23
        change_state(&Opening);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
const struct tState_s Connecting = {
Packit fcad23
    ConnectingEntry,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    StateDisconnect,
Packit fcad23
    NULL,
Packit fcad23
    "Connnecting",
Packit fcad23
    0
Packit fcad23
};
Packit fcad23
Packit fcad23
static netsnmp_pdu*
Packit fcad23
pdu_create_opt_context(int command, const char* context, size_t len)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu* res = snmp_pdu_create(command);
Packit fcad23
    if (res)
Packit fcad23
        if (context) {
Packit fcad23
            if (snmp_clone_mem((void**)&res->contextName, context, len)) {
Packit fcad23
                snmp_free_pdu(res);
Packit fcad23
                res = NULL;
Packit fcad23
            } else
Packit fcad23
                res->contextNameLen = len;
Packit fcad23
        }
Packit fcad23
    return res;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
OpeningEntry(tState self)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu* act =
Packit fcad23
        pdu_create_opt_context(AGENTX_MSG_OPEN, context, contextLen);
Packit fcad23
    if(act) {
Packit fcad23
        act->sessid = 0;
Packit fcad23
        act->transid = 0;
Packit fcad23
        act->reqid = ++packetid;
Packit fcad23
        act->time = 0;
Packit fcad23
        snmp_pdu_add_variable(act, NULL, 0, ASN_OCTET_STR, NULL, 0);
Packit fcad23
        if(snmp_sess_send(sessp, act) == 0)
Packit fcad23
            snmp_free_pdu(act);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
OpeningRes(tState self, netsnmp_pdu *act)
Packit fcad23
{
Packit fcad23
    if(act->errstat == AGENTX_ERR_NOERROR) {
Packit fcad23
        session = act->sessid;
Packit fcad23
        change_state(&Notifying);
Packit fcad23
    } else {
Packit fcad23
        snmp_log(LOG_ERR, "Failed to open session");
Packit fcad23
        change_state(&Exit;;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
const struct tState_s Opening = {
Packit fcad23
    OpeningEntry,
Packit fcad23
    NULL,
Packit fcad23
    OpeningRes,
Packit fcad23
    &Disconnecting,
Packit fcad23
    StateDisconnect,
Packit fcad23
    StateClose,
Packit fcad23
    "Opening",
Packit fcad23
    0
Packit fcad23
};
Packit fcad23
Packit fcad23
static void
Packit fcad23
NotifyingEntry(tState self)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu* act = snmp_clone_pdu(pdu);
Packit fcad23
    if(act) {
Packit fcad23
        act->sessid = session;
Packit fcad23
        act->transid = 0;
Packit fcad23
        act->reqid = ++packetid;
Packit fcad23
        if(snmp_sess_send(sessp, act) == 0)
Packit fcad23
            snmp_free_pdu(act);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
NotifyingRes(tState self, netsnmp_pdu *act)
Packit fcad23
{
Packit fcad23
    if(act->errstat == AGENTX_ERR_NOERROR)
Packit fcad23
        result = 0;
Packit fcad23
    else
Packit fcad23
        snmp_log(LOG_ERR, "Failed to send notification");
Packit fcad23
    /** \todo: Retry handling --- ClosingReconnect??? */
Packit fcad23
    change_state(&Closing);
Packit fcad23
}
Packit fcad23
Packit fcad23
const struct tState_s Notifying = {
Packit fcad23
    NotifyingEntry,
Packit fcad23
    NULL,
Packit fcad23
    NotifyingRes,
Packit fcad23
    NULL,            /** \todo: Retry handling? */
Packit fcad23
    StateDisconnect, /** \todo: Retry handling? */
Packit fcad23
    StateClose,
Packit fcad23
    "Notifying",
Packit fcad23
    1
Packit fcad23
};
Packit fcad23
Packit fcad23
static void
Packit fcad23
ClosingEntry(tState self)
Packit fcad23
{
Packit fcad23
    /* CLOSE pdu->errstat */
Packit fcad23
    netsnmp_pdu* act =
Packit fcad23
        pdu_create_opt_context(AGENTX_MSG_CLOSE, context, contextLen);
Packit fcad23
    if(act) {
Packit fcad23
        act->sessid = session;
Packit fcad23
        act->transid = 0;
Packit fcad23
        act->reqid = ++packetid;
Packit fcad23
        act->errstat = AGENTX_CLOSE_SHUTDOWN;
Packit fcad23
        if(snmp_sess_send(sessp, act) == 0)
Packit fcad23
            snmp_free_pdu(act);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
ClosingRes(tState self, netsnmp_pdu *act)
Packit fcad23
{
Packit fcad23
    if(act->errstat != AGENTX_ERR_NOERROR) {
Packit fcad23
        snmp_log(LOG_ERR, "AgentX error status of %ld\n", act->errstat);
Packit fcad23
    }
Packit fcad23
    change_state(&Disconnecting);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
ClosingDisconnect(tState self)
Packit fcad23
{
Packit fcad23
    change_state(&Disconnecting);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
ClosingClose(tState self, netsnmp_pdu *act)
Packit fcad23
{
Packit fcad23
    change_state(&Disconnecting);
Packit fcad23
}
Packit fcad23
Packit fcad23
const struct tState_s Closing = {
Packit fcad23
    ClosingEntry,
Packit fcad23
    NULL,
Packit fcad23
    ClosingRes,
Packit fcad23
    &Disconnecting,
Packit fcad23
    ClosingDisconnect,
Packit fcad23
    ClosingClose,
Packit fcad23
    "Closing",
Packit fcad23
    1
Packit fcad23
};
Packit fcad23
Packit fcad23
static void
Packit fcad23
DisconnectingEntry(tState self)
Packit fcad23
{
Packit fcad23
    snmp_sess_close(sessp);
Packit fcad23
    sessp = NULL;
Packit fcad23
    change_state(&Exit;;
Packit fcad23
}
Packit fcad23
Packit fcad23
const struct tState_s Disconnecting = {
Packit fcad23
    DisconnectingEntry,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    "Disconnecting",
Packit fcad23
    0
Packit fcad23
};
Packit fcad23
Packit fcad23
const struct tState_s Exit = {
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    NULL,
Packit fcad23
    "Exit",
Packit fcad23
    0
Packit fcad23
};
Packit fcad23
Packit fcad23
int
Packit fcad23
main(int argc, char *argv[])
Packit fcad23
{
Packit fcad23
    int             arg;
Packit fcad23
    char           *prognam;
Packit fcad23
    char           *cp = NULL;
Packit fcad23
    const char*     sysUpTime = NULL;
Packit fcad23
Packit fcad23
    /* initialize tcpip, if necessary */
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    prognam = strrchr(argv[0], '/');
Packit fcad23
    if (prognam)
Packit fcad23
        ++prognam;
Packit fcad23
    else
Packit fcad23
        prognam = argv[0];
Packit fcad23
Packit fcad23
    putenv(strdup("POSIXLY_CORRECT=1"));
Packit fcad23
Packit fcad23
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
			   NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD, 1);
Packit fcad23
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
			   NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE, 1);
Packit fcad23
Packit fcad23
    while ((arg = getopt(argc, argv, ":Vhm:M:D:dP:L:U:c:x:")) != -1) {
Packit fcad23
        switch (arg) {
Packit fcad23
        case 'h':
Packit fcad23
            usage(prognam);
Packit fcad23
            result = 0;
Packit fcad23
            goto out;
Packit fcad23
        case 'm':
Packit fcad23
            setenv("MIBS", optarg, 1);
Packit fcad23
            break;
Packit fcad23
        case 'M':
Packit fcad23
            setenv("MIBDIRS", optarg, 1);
Packit fcad23
            break;
Packit fcad23
        case 'c':
Packit fcad23
            context = optarg;
Packit fcad23
            contextLen = strlen(context);
Packit fcad23
            break;
Packit fcad23
        case 'D':
Packit fcad23
            debug_register_tokens(optarg);
Packit fcad23
            snmp_set_do_debugging(1);
Packit fcad23
            break;
Packit fcad23
        case 'd':
Packit fcad23
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                   NETSNMP_DS_LIB_DUMP_PACKET, 1);
Packit fcad23
            break;
Packit fcad23
        case 'U':
Packit fcad23
            sysUpTime = optarg;
Packit fcad23
            break;
Packit fcad23
        case 'V':
Packit fcad23
            fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());
Packit fcad23
            result = 0;
Packit fcad23
            goto out;
Packit fcad23
#ifndef DISABLE_MIB_LOADING
Packit fcad23
        case 'P':
Packit fcad23
            cp = snmp_mib_toggle_options(optarg);
Packit fcad23
            if (cp != NULL) {
Packit fcad23
                fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp);
Packit fcad23
                usage(prognam);
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
#endif /* DISABLE_MIB_LOADING */
Packit fcad23
        case 'L':
Packit fcad23
            if (snmp_log_options(optarg, argc, argv) < 0)
Packit fcad23
                goto out;
Packit fcad23
            break;
Packit fcad23
        case 'x':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
                                      NETSNMP_DS_AGENT_X_SOCKET, optarg);
Packit fcad23
            } else
Packit fcad23
                usage(argv[0]);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case ':':
Packit fcad23
            fprintf(stderr, "Option -%c requires an operand\n", optopt);
Packit fcad23
            usage(prognam);
Packit fcad23
            goto out;
Packit fcad23
        case '?':
Packit fcad23
            fprintf(stderr, "Unrecognized option: -%c\n", optopt);
Packit fcad23
            usage(prognam);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    arg = optind;
Packit fcad23
Packit fcad23
    init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
Packit fcad23
    agentx_config_init();
Packit fcad23
Packit fcad23
    /* NOTIFY varlist */
Packit fcad23
    pdu = pdu_create_opt_context(AGENTX_MSG_NOTIFY, context, contextLen);
Packit fcad23
Packit fcad23
    if (sysUpTime)
Packit fcad23
        snmp_add_var(pdu, sysuptime_oid, sysuptime_oid_len, 't', sysUpTime);
Packit fcad23
Packit fcad23
    if (arg == argc) {
Packit fcad23
        fprintf(stderr, "Missing trap-oid parameter\n");
Packit fcad23
        usage(prognam);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (snmp_add_var(pdu, snmptrap_oid, snmptrap_oid_len, 'o', argv[arg])) {
Packit fcad23
        snmp_perror(argv[arg]);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
    ++arg;
Packit fcad23
Packit fcad23
    while (arg < argc) {
Packit fcad23
        oid    name[MAX_OID_LEN];
Packit fcad23
        size_t name_length = MAX_OID_LEN;
Packit fcad23
        arg += 3;
Packit fcad23
        if (arg > argc) {
Packit fcad23
            fprintf(stderr, "%s: Missing type/value for variable\n",
Packit fcad23
                    argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) {
Packit fcad23
            snmp_perror(argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (snmp_add_var(pdu, name, name_length, argv[arg - 2][0],
Packit fcad23
                         argv[arg - 1]) != 0) {
Packit fcad23
            snmp_perror(argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    packetid = 0;
Packit fcad23
Packit fcad23
    state = &Connecting;
Packit fcad23
    next_state = NULL;
Packit fcad23
    if(state->entry) state->entry(state);
Packit fcad23
Packit fcad23
    /* main loop here... */
Packit fcad23
    for(;;) {
Packit fcad23
        int block = 1;
Packit fcad23
        int numfds = 0;
Packit fcad23
        int count;
Packit fcad23
        fd_set fdset;
Packit fcad23
        struct timeval timeout;
Packit fcad23
Packit fcad23
        while(next_state) {
Packit fcad23
            if(state->exit) state->exit(state);
Packit fcad23
            DEBUGMSGTL(("process", "State transition: %s -> %s\n",
Packit fcad23
                        state->name, next_state->name));
Packit fcad23
            state = next_state;
Packit fcad23
            next_state = NULL;
Packit fcad23
            if(state->entry) state->entry(state);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if(state == &Exit)
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        FD_ZERO(&fdset);
Packit fcad23
        snmp_sess_select_info(sessp, &numfds, &fdset, &timeout, &block);
Packit fcad23
        count = select(numfds, &fdset, NULL, NULL, !block ? &timeout : NULL);
Packit fcad23
        if (count > 0)
Packit fcad23
            snmp_sess_read(sessp, &fdset);
Packit fcad23
        else if (count == 0)
Packit fcad23
            snmp_sess_timeout(sessp);
Packit fcad23
        else if (errno != EINTR) {
Packit fcad23
            snmp_log(LOG_ERR, "select error [%s]\n", strerror(errno));
Packit fcad23
            change_state(&Exit;;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /* at shutdown time */
Packit fcad23
    snmp_free_pdu(pdu);
Packit fcad23
    pdu = NULL;
Packit fcad23
Packit fcad23
    snmp_shutdown(NETSNMP_APPLICATION_CONFIG_TYPE);
Packit fcad23
Packit fcad23
out:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
    return result;
Packit fcad23
}