示例#1
0
/*
 * Return code:
 *	0  - End Of Table
 * 	-1 - Error
 *	-2 - Last change changed - again
 *	+1 - ok, continue
 */
static int
table_check_response(struct tabwork *work, const struct snmp_pdu *resp)
{
	const struct snmp_value *b;
	struct entry *e;

	if (resp->error_status != SNMP_ERR_NOERROR) {
		if (snmp_client.version == SNMP_V1 &&
		    resp->error_status == SNMP_ERR_NOSUCHNAME &&
		    resp->error_index ==
		    (work->descr->last_change.len == 0) ? 1 : 2)
			/* EOT */
			return (0);
		/* Error */
		seterr(&snmp_client, "error fetching table: status=%d index=%d",
		    resp->error_status, resp->error_index);
		return (-1);
	}

	for (b = resp->bindings; b < resp->bindings + resp->nbindings; b++) {
		if (work->descr->last_change.len != 0 && b == resp->bindings) {
			if (!asn_is_suboid(&work->descr->last_change, &b->var) ||
			    b->var.len != work->descr->last_change.len + 1 ||
			    b->var.subs[work->descr->last_change.len] != 0) {
				seterr(&snmp_client,
				    "last_change: bad response");
				return (-1);
			}
			if (b->syntax != SNMP_SYNTAX_TIMETICKS) {
				seterr(&snmp_client,
				    "last_change: bad syntax %u", b->syntax);
				return (-1);
			}
			if (work->first) {
				work->last_change = b->v.uint32;
				work->first = 0;

			} else if (work->last_change != b->v.uint32) {
				if (++work->iter >= work->descr->max_iter) {
					seterr(&snmp_client,
					    "max iteration count exceeded");
					return (-1);
				}
				table_free(work, 1);
				return (-2);
			}
					
			continue;
		}
		if (!asn_is_suboid(&work->descr->table, &b->var) ||
		    b->syntax == SNMP_SYNTAX_ENDOFMIBVIEW)
			return (0);

		if ((e = table_find(work, &b->var)) == NULL)
			return (-1);
		if (table_value(work->descr, e, b))
			return (-1);
	}
	return (+1);
}
示例#2
0
static void
query_next_response (int request, int code, struct snmp_value *value, void *arg)
{
	rb_item *item = arg;
	asn_subid_t subid;
	int matched;

	/*
	 * Called when we get the next OID in a table
	 */

	ASSERT (request == item->query_request);
	ASSERT (!item->field_request);

	/* Mark this item as done */
	item->query_request = 0;

	if (code == SNMP_ERR_NOERROR) {
		ASSERT (value);

		/* Convert these result codes into 'not found' */
		switch (value->syntax) {
		case SNMP_SYNTAX_NOSUCHOBJECT:
		case SNMP_SYNTAX_NOSUCHINSTANCE:
		case SNMP_SYNTAX_ENDOFMIBVIEW:
			code = SNMP_ERR_NOSUCHNAME;
			break;

		/*
		 * Make sure that we haven't gone past the end. For it to
		 * be in the table it must be exactly one longer (the table index)
		 * and otherwise identical.
		 */
		default:
			if (item->query_oid.len + 1 != value->var.len ||
			    !asn_is_suboid (&item->query_oid, &value->var))
				code = SNMP_ERR_NOSUCHNAME;
			break;
		};
	}

	if (code == SNMP_ERR_NOSUCHNAME)
		log_debug ("query couldn't find table index that matches: %s",
		           item->query_match ? item->query_match : "[null]");


	/* Problems communicating with the server, or not found */
	if (code != SNMP_ERR_NOERROR) {
		memset (&item->query_last, 0, sizeof (item->query_last));
		complete_requests (item, code);
		return;
	}

	/* Save away the last OID we've seen */
	item->query_last = value->var;
	item->query_searched = 1;

	ASSERT (value);

	/* Match the query value received */
	if (item->query_match)
		matched = snmp_engine_match (value, item->query_match);

	/* When query match is null, anything matches */
	else
		matched = 1;

	item->query_matched = matched;
	item->vtype = VALUE_UNSET;

	if (matched) {
		/* Do a query for the field value with this sub id */
		subid = value->var.subs[value->var.len - 1];
		query_value_request (item, subid);
	} else {
		/* Look for the next table index */
		query_search_request (item);
	}
}
示例#3
0
/*
 * Do a 'snmp walk' - according to command line options request for values lexicographically
 * subsequent and subrooted at a common node. Send a GetNext PDU requesting the value for each
 * next variable and print the responce. Stop when a Responce PDU is received that contains
 * the value of a variable not subrooted at the variable the walk started.
 */
int
main(int argc, char ** argv)
{
    struct snmp_toolinfo *tool;
    struct snmp_client *client_context;
    struct asn_oid root; /* keep the inital oid */
    struct snmp_pdu pdu_to_send, pdu_to_recv;
    int oid, opt_num, outputs;

    tool = snmptool_init(helptxt);
    client_context = tool->client;

    if ((opt_num = snmpwalk_parse_options(tool, argc, argv)) < 0) {
        snmp_tool_freeall(tool);
        exit(0);
    }

    if (snmp_import_all(tool) < 0) {
        snmp_tool_freeall(tool);
        exit(0);
    }

    oid = argc - opt_num - 1;

    switch (oid) {
    case 0:
        if (snmp_object_add(tool, snmpwalk_add_default, NULL) < 0) {
            snmp_tool_freeall(tool);
            errx(1, "Error setting default tree OID to walk");
        }
        break;
    case 1:
        /* last command line argument will always be the OID to start the walk from */
        if ((snmp_object_add(tool, snmpwalk_parse_oid, argv[argc - 1])) < 0) {
            snmp_tool_freeall(tool);
            exit(1);
        }
        break;
    default:
        snmp_tool_freeall(tool);
        errx(1, "Only one OID allowed");
    }

    snmp_pdu_create(client_context, &pdu_to_send, SNMP_PDU_GETNEXT);

    if (snmp_pdu_add_bindings(tool, (snmp_verify_vbind_f) NULL,
                              snmpwalk_add_vbind, &pdu_to_send) < 0) {
        snmp_tool_freeall(tool);
        exit(1);
    }

    if (snmp_open(client_context, NULL, NULL, NULL, NULL)) {
        snmp_tool_freeall(tool);
        err(1, "Failed to open snmp session");
    }

    /* remember the root where the walk started from */
    memset(&root, 0 ,sizeof(struct asn_oid));
    asn_append_oid(&root, &(pdu_to_send.bindings[0].var));

    outputs = 0;
    while (snmp_dialog(client_context, &pdu_to_send, &pdu_to_recv) >= 0) {

        if ((snmp_parse_resp(client_context, &pdu_to_recv, &pdu_to_send)) < 0) {
            snmp_output_err_resp(tool, &pdu_to_recv);
            snmp_pdu_free(&pdu_to_recv);
            outputs = -1;
            break;
        }

        if (!(asn_is_suboid(&root, &(pdu_to_recv.bindings[0].var)))) {
            snmp_pdu_free(&pdu_to_recv);
            break;
        }
        snmp_output_resp(tool, &pdu_to_recv);
        outputs++;
        snmp_pdu_free(&pdu_to_recv);

        snmpwalk_nextpdu_create(client_context, SNMP_PDU_GETNEXT,
                                &(pdu_to_recv.bindings[0].var), &pdu_to_send);
    }

    /* Just a case our root was a leaf */
    if (outputs == 0) {

        snmpwalk_nextpdu_create(client_context, SNMP_PDU_GET, &root, &pdu_to_send);

        if (snmp_dialog(client_context, &pdu_to_send, &pdu_to_recv) == SNMP_CODE_OK /* 0 */) {

            if(snmp_parse_resp(client_context, &pdu_to_recv,&pdu_to_send)  < 0)
                snmp_output_err_resp(tool, &pdu_to_recv);
            else
                snmp_output_resp(tool, &(pdu_to_recv));

            snmp_pdu_free(&pdu_to_recv);
        } else
            err(1, "Snmp dialog");
    }

    snmp_tool_freeall(tool);

    exit(0);
}