Ejemplo n.º 1
0
/*
 * RFC 1908: Coexistence between SNMPv1 and SNMPv2
 *
 * These convert:
 *
 *   V1 PDUs from an ** AGENT **   to V2 PDUs for an ** MANAGER **
 *   V2 PDUs from an ** MANAGER ** to V1 PDUs for an ** AGENT **
 *
 * We will never convert V1 information from a manager into V2 PDUs.  V1
 * requests are always honored by V2 agents, and the responses will be
 * valid V1 responses.  (I think. XXXXX)
 *
 */
int
snmp_coexist_V2toV1(struct snmp_pdu *PDU)
{
    /* Per 3.1.1:
     */
    switch (PDU->command) {

    case SNMP_PDU_GET:
    case SNMP_PDU_GETNEXT:
#if SNMP_PDU_SET
    case SNMP_PDU_SET:
#endif
        return (1);
        break;

    case SNMP_PDU_GETBULK:
        PDU->non_repeaters = 0;
        PDU->max_repetitions = 0;
        PDU->command = SNMP_PDU_GETNEXT;
        return (1);
        break;

    default:
        snmplib_debug(2, "Unable to translate PDU %d to SNMPv1!\n", PDU->command);
        snmp_set_api_error(SNMPERR_PDU_TRANSLATION);
        return (0);
    }
}
Ejemplo n.º 2
0
u_char *
snmp_msg_Decode(u_char * Packet, int *PacketLenP,
                u_char * Community, int *CommLenP,
                int *Version, struct snmp_pdu * PDU)
{
    u_char *bufp;
    u_char type;

    bufp = asn_parse_header(Packet, PacketLenP, &type);
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n");
        ASN_PARSE_ERROR(NULL);
    }
    if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
        snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n");
        ASN_PARSE_ERROR(NULL);
    }
    bufp = asn_parse_int(bufp, PacketLenP,
                         &type,
                         (int *) Version, sizeof(*Version));
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Version)!\n");
        ASN_PARSE_ERROR(NULL);
    }
    bufp = asn_parse_string(bufp, PacketLenP, &type, Community, CommLenP);
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Community)!\n");
        ASN_PARSE_ERROR(NULL);
    }
    Community[*CommLenP] = '\0';

    if ((*Version != SNMP_VERSION_1) &&
            (*Version != SNMP_VERSION_2)) {

        /* Don't know how to handle this one. */
        snmplib_debug(4, "snmp_msg_Decode:Unable to parse Version %u\n", *Version);
        snmplib_debug(4, "snmp_msg_Decode:Continuing anyway\n");
    }
    /* Now that we know the header, decode the PDU */

    /* XXXXX -- More than one PDU? */
    bufp = snmp_pdu_decode(bufp, PacketLenP, PDU);
    if (bufp == NULL)
        /* snmp_pdu_decode registered failure */
        return (NULL);

    bufp = snmp_var_DecodeVarBind(bufp, PacketLenP, &(PDU->variables), *Version);
    if (bufp == NULL)
        /* snmp_var_DecodeVarBind registered failure */
        return (NULL);

    return (u_char *) bufp;
}
Ejemplo n.º 3
0
u_char *
snmp_msg_Encode(u_char * Buffer, int *BufLenP,
                u_char * Community, int CommLen,
                int Version,
                struct snmp_pdu *PDU)
{
    u_char *bufp, *tmp;
    u_char *PDUHeaderPtr, *VARHeaderPtr;
    u_char *PDUDataStart, *VARDataStart;
    u_char *MsgPtr;
    int FakeArg = 1024;

    snmplib_debug(4, "Buffer=%p BufLenP=%p, buflen=%d\n", Buffer, BufLenP,
                  *BufLenP);
    /* Header for the entire thing, with a false, large length */
    bufp = asn_build_header(Buffer, BufLenP,
                            (u_char) (ASN_SEQUENCE |
                                      ASN_CONSTRUCTOR),
                            (*BufLenP));
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Header)!\n");
        return (NULL);
    }
    MsgPtr = bufp;

    /* Version */
    bufp = asn_build_int(bufp, BufLenP,
                         (u_char) (ASN_UNIVERSAL |
                                   ASN_PRIMITIVE |
                                   ASN_INTEGER),
                         (int *) (&Version), sizeof(Version));
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Version)!\n");
        return (NULL);
    }
    snmplib_debug(8, "snmp_msg_Encode: Encoding community (%s) (%d)\n", Community, CommLen);

    /* Community */
    bufp = asn_build_string(bufp, BufLenP,
                            (u_char) (ASN_UNIVERSAL |
                                      ASN_PRIMITIVE |
                                      ASN_OCTET_STR),
                            Community, CommLen);
    if (bufp == NULL) {
        snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Community)!\n");
        return (NULL);
    }
    /* Encode the rest. */

    /* A nice header for this PDU.
     * Encoded with the wrong length.  We'll fix it later.
     */
    snmplib_debug(8, "snmp_msg_Encode:Encoding PDU Header at 0x%p (fake len %d) (%d bytes so far)\n",
                  bufp, *BufLenP, *BufLenP);
    PDUHeaderPtr = bufp;
    bufp = asn_build_header(bufp, BufLenP,
                            (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                            (*BufLenP));
    if (bufp == NULL)
        return (NULL);

    /* Encode this PDU. */
    PDUDataStart = bufp;
    bufp = snmp_pdu_encode(bufp, BufLenP, PDU);
    if (bufp == NULL)
        return (NULL);		/* snmp_pdu_encode registered failure */

    VARHeaderPtr = bufp;
    bufp = asn_build_header(bufp, BufLenP,
                            (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                            FakeArg);
    if (bufp == NULL)
        return (NULL);
    VARDataStart = bufp;

    /* And build the variables */
    bufp = snmp_var_EncodeVarBind(bufp, BufLenP, PDU->variables, Version);
    if (bufp == NULL)
        return (NULL);		/* snmp_var_EncodeVarBind registered failure */

    /* Cool.  Now insert the appropriate lengths.
     */
#if DEBUG_MSG_ENCODE
    snmplib_debug(9, "Msg:  Vars returned 0x%x.  PDU Started at 0x%x\n",
                  bufp, PDUHeaderPtr);
    snmplib_debug(9, "MSG:  Entire PDU length is %d (0x%x - 0x%x)\n",
                  (int) (bufp - PDUDataStart), PDUHeaderPtr, bufp);
#endif
    tmp = asn_build_header(PDUHeaderPtr, &FakeArg,
                           (u_char) PDU->command,
                           (int) (bufp - PDUDataStart));
    /* Length of the PDU and Vars */
    if (tmp == NULL)
        return (NULL);

#if DEBUG_MSG_ENCODE
    snmplib_debug(9, "MSG:  Entire message length is %d (0x%x - 0x%x)\n",
                  (int) (bufp - MsgPtr), MsgPtr, bufp);
#endif
    tmp = asn_build_header(Buffer,
                           &FakeArg,
                           (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                           (bufp - MsgPtr));	/* Length of everything */
    if (tmp == NULL)
        return (NULL);

    tmp = asn_build_header(VARHeaderPtr,
                           &FakeArg,
                           (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                           (bufp - VARDataStart));	/* Length of everything */
    if (tmp == NULL)
        return (NULL);

    *BufLenP = (bufp - Buffer);
    return (u_char *) bufp;
}
Ejemplo n.º 4
0
static int
parse_subtree(struct snmp_mib_tree *subtree, char *input, oid *output, int *out_len)
{
    char buf[128], *to = buf;
    u_int subid = 0;
    struct snmp_mib_tree *tp;

    /*
     * No empty strings.  Can happen if there is a trailing '.' or two '.'s
     * in a row, i.e. "..".
     */
    if ((*input == '\0') ||
	(*input == '.'))
	return (0);

    if (xisdigit(*input)) {
	/*
	 * Read the number, then try to find it in the subtree.
	 */
	while (xisdigit(*input)) {
	    subid *= 10;
	    subid += *input++ - '0';
	}
	for (tp = subtree; tp; tp = tp->next_peer) {
	    if (tp->subid == subid)
		goto found;
	}
	tp = NULL;
    } else {
	/*
	 * Read the name into a buffer.
	 */
	while ((*input != '\0') &&
	    (*input != '.')) {
	    *to++ = *input++;
	}
	*to = '\0';

	/*
	 * Find the name in the subtree;
	 */
	for (tp = subtree; tp; tp = tp->next_peer) {
	    if (lc_cmp(tp->label, buf) == 0) {
		subid = tp->subid;
		goto found;
	    }
	}

	/*
	 * If we didn't find the entry, punt...
	 */
	if (tp == NULL) {
	    snmplib_debug(0, "sub-identifier not found: %s\n", buf);
	    return (0);
	}
    }

  found:
    if (subid > (u_int) MAX_SUBID) {
	snmplib_debug(0, "sub-identifier too large: %s\n", buf);
	return (0);
    }
    if ((*out_len)-- <= 0) {
	snmplib_debug(0, "object identifier too long\n");
	return (0);
    }
    *output++ = subid;

    if (*input != '.')
	return (1);
    if ((*out_len =
	    parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0)
	return (0);
    return (++*out_len);
}
Ejemplo n.º 5
0
/* Parse all Vars from the buffer */
u_char *
snmp_var_DecodeVarBind(u_char * Buffer, int *BufLen,
    struct variable_list ** VarP,
    int Version)
{
    struct variable_list *Var = NULL, **VarLastP;
    u_char *bufp, *tmp;
    u_char VarBindType;
    u_char *DataPtr;
    int DataLen;
    oid TmpBuf[MAX_NAME_LEN];

    int AllVarLen = *BufLen;
    int ThisVarLen = 0;

    VarLastP = VarP;
#ifdef DEBUG_VARS_DECODE
    printf("VARS: Decoding buffer of length %d\n", *BufLen);
#endif

    /* Now parse the variables */
    bufp = asn_parse_header(Buffer, &AllVarLen, &VarBindType);
    if (bufp == NULL)
	return (NULL);

    if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
	snmp_set_api_error(SNMPERR_PDU_PARSE);
	return (NULL);
    }
#ifdef DEBUG_VARS_DECODE
    printf("VARS: All Variable length %d\n", AllVarLen);
#endif

#define PARSE_ERROR { snmp_var_free(Var); return(NULL); }

    /* We know how long the variable list is.  Parse it. */
    while ((int) AllVarLen > 0) {

	/* Create a new variable */
	Var = snmp_var_new(NULL, MAX_NAME_LEN);
	if (Var == NULL)
	    return (NULL);

	/* Parse the header to find out the length of this variable. */
	ThisVarLen = AllVarLen;
	tmp = asn_parse_header(bufp, &ThisVarLen, &VarBindType);
	if (tmp == NULL)
	    PARSE_ERROR;

	/* Now that we know the length , figure out how it relates to 
	 * the entire variable list
	 */
	AllVarLen = AllVarLen - (ThisVarLen + (tmp - bufp));
	bufp = tmp;

	/* Is it valid? */
	if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
	    snmp_set_api_error(SNMPERR_PDU_PARSE);
	    PARSE_ERROR;
	}
#ifdef DEBUG_VARS_DECODE
	printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType, ThisVarLen);
#endif

	/* Parse the OBJID */
	bufp = asn_parse_objid(bufp, &ThisVarLen, &VarBindType,
	    Var->name, &(Var->name_length));
	if (bufp == NULL)
	    PARSE_ERROR;

	if (VarBindType != (u_char) (ASN_UNIVERSAL |
		ASN_PRIMITIVE |
		ASN_OBJECT_ID)) {
	    snmp_set_api_error(SNMPERR_PDU_PARSE);
	    PARSE_ERROR;
	}
#ifdef DEBUG_VARS_DECODE
	printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n",
	    Var->name_length, ThisVarLen);
#endif

	/* Keep a pointer to this object */
	DataPtr = bufp;
	DataLen = ThisVarLen;

	/* find out type of object */
	bufp = asn_parse_header(bufp, &ThisVarLen, &(Var->type));
	if (bufp == NULL)
	    PARSE_ERROR;
	ThisVarLen = DataLen;

#ifdef DEBUG_VARS_DECODE
	printf("VARS: Data type %d\n", Var->type);
#endif

	/* Parse the type */

	switch ((short) Var->type) {

	case ASN_INTEGER:
	    Var->val.integer = (int *) xmalloc(sizeof(int));
	    if (Var->val.integer == NULL) {
		snmp_set_api_error(SNMPERR_OS_ERR);
		PARSE_ERROR;
	    }
	    Var->val_len = sizeof(int);
	    bufp = asn_parse_int(DataPtr, &ThisVarLen,
		&Var->type, (int *) Var->val.integer,
		Var->val_len);
#ifdef DEBUG_VARS_DECODE
	    printf("VARS: Decoded integer '%d' (%d bytes left)\n",
		*(Var->val.integer), ThisVarLen);
#endif
	    break;

	case SMI_COUNTER32:
	case SMI_GAUGE32:
	    /*  case SMI_UNSIGNED32: */
	case SMI_TIMETICKS:
	    Var->val.integer = (int *) xmalloc(sizeof(u_int));
	    if (Var->val.integer == NULL) {
		snmp_set_api_error(SNMPERR_OS_ERR);
		PARSE_ERROR;
	    }
	    Var->val_len = sizeof(u_int);
	    bufp = asn_parse_unsigned_int(DataPtr, &ThisVarLen,
		&Var->type, (u_int *) Var->val.integer,
		Var->val_len);
#ifdef DEBUG_VARS_DECODE
	    printf("VARS: Decoded timeticks '%d' (%d bytes left)\n",
		*(Var->val.integer), ThisVarLen);
#endif
	    break;

	case ASN_OCTET_STR:
	case SMI_IPADDRESS:
	case SMI_OPAQUE:
	    Var->val_len = *&ThisVarLen;	/* String is this at most */
	    Var->val.string = (u_char *) xmalloc((unsigned) Var->val_len);
	    if (Var->val.string == NULL) {
		snmp_set_api_error(SNMPERR_OS_ERR);
		PARSE_ERROR;
	    }
	    bufp = asn_parse_string(DataPtr, &ThisVarLen,
		&Var->type, Var->val.string,
		&Var->val_len);
#ifdef DEBUG_VARS_DECODE
	    printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n",
		(Var->val.string), Var->val_len, ThisVarLen);
#endif
	    break;

	case ASN_OBJECT_ID:
	    Var->val_len = MAX_NAME_LEN;
	    bufp = asn_parse_objid(DataPtr, &ThisVarLen,
		&Var->type, TmpBuf, &Var->val_len);
	    Var->val_len *= sizeof(oid);
	    Var->val.objid = (oid *) xmalloc((unsigned) Var->val_len);
	    if (Var->val.integer == NULL) {
		snmp_set_api_error(SNMPERR_OS_ERR);
		PARSE_ERROR;
	    }
	    /* Only copy if we successfully decoded something */
	    if (bufp) {
		xmemcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len);
	    }
#ifdef DEBUG_VARS_DECODE
	    printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
		Var->val_len, ThisVarLen);
#endif
	    break;

	case ASN_NULL:
	case SMI_NOSUCHINSTANCE:
	case SMI_NOSUCHOBJECT:
	case SMI_ENDOFMIBVIEW:
	    break;

	case SMI_COUNTER64:
	    snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n");
	    snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE);
	    PARSE_ERROR;

	default:
	    snmplib_debug(2, "bad type returned (%x)\n", Var->type);
	    snmp_set_api_error(SNMPERR_PDU_PARSE);
	    PARSE_ERROR;
	}			/* End of var type switch */

	if (bufp == NULL)
	    PARSE_ERROR;

#ifdef DEBUG_VARS_DECODE
	printf("VARS:  Adding to list.\n");
#endif
	/* Add variable to the list */
	*VarLastP = Var;
	VarLastP = &(Var->next_variable);
    }
#undef PARSE_ERROR

    return (bufp);
}
Ejemplo n.º 6
0
/* Build a variable binding.
 *
 * RFC 1905: Protocol Operations for SNMPv2
 *
 * VarBind ::= 
 *   SEQUENCE {
 *     name ObjectName
 *     CHOICE {
 *       value ObjectSyntax
 *       unSpecified NULL
 *       noSuchObject[0] NULL
 *       noSuchInstance[1] NULL
 *       endOfMibView[2] NULL
 *     }
 *   }
 */
u_char *
snmp_var_EncodeVarBind(u_char * Buffer, int *BufLenP,
    variable_list * VarList,
    int Version)
{
    struct variable_list *Vars;
    u_char *bufp;
    u_char *HeaderStart;
    u_char *HeaderEnd;
    int FakeArg = *BufLenP;

    bufp = Buffer;

    for (Vars = VarList; Vars; Vars = Vars->next_variable) {

	/* Build the header for this variable
	 *
	 * Use Maximum size.
	 */
	HeaderStart = bufp;
	HeaderEnd = asn_build_header(HeaderStart, BufLenP,
	    (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
	    FakeArg);
	if (HeaderEnd == NULL)
	    return (NULL);

	/* Now, let's put the Object Identifier into the buffer */
	bufp = asn_build_objid(HeaderEnd, BufLenP,
	    (u_char) (ASN_UNIVERSAL |
		ASN_PRIMITIVE |
		ASN_OBJECT_ID),
	    Vars->name, Vars->name_length);
	if (bufp == NULL)
	    return (NULL);

	/* Now put the data in */
	switch (Vars->type) {

	case ASN_INTEGER:
	    bufp = asn_build_int(bufp,
		BufLenP, Vars->type,
		(int *) Vars->val.integer, Vars->val_len);
	    break;

	case SMI_COUNTER32:
	case SMI_GAUGE32:
	    /*  case SMI_UNSIGNED32: */
	case SMI_TIMETICKS:
	    bufp = asn_build_unsigned_int(bufp, BufLenP,
		Vars->type,
		(u_int *) Vars->val.integer, Vars->val_len);
	    break;

	case ASN_OCTET_STR:
	case SMI_IPADDRESS:
	case SMI_OPAQUE:
	    bufp = asn_build_string(bufp, BufLenP, Vars->type,
		Vars->val.string, Vars->val_len);
	    break;

	case ASN_OBJECT_ID:
	    bufp = asn_build_objid(bufp, BufLenP, Vars->type,
		(oid *) Vars->val.objid, Vars->val_len / sizeof(oid));
	    break;

	case SMI_NOSUCHINSTANCE:
	case SMI_NOSUCHOBJECT:
	case SMI_ENDOFMIBVIEW:
	    if (Version == SNMP_VERSION_1) {
		/* SNMP Version 1 does not support these error codes. */
		bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT);
	    } else {
		bufp = asn_build_exception(bufp, BufLenP, Vars->type);
	    }
	    break;

	case ASN_NULL:
	    bufp = asn_build_null(bufp, BufLenP, Vars->type);
	    break;

	case SMI_COUNTER64:
	    snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n");
	    /* Fall through */

	default:
	    snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE);
	    return (NULL);
	}

	/* ASSERT:  bufp should now point to the next valid byte. */
	if (bufp == NULL)
	    return (NULL);

	/* Rebuild the header with the appropriate length */
	HeaderEnd = asn_build_header(HeaderStart, &FakeArg,
	    (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
	    (bufp - HeaderEnd));

	/* Returns NULL */
	if (HeaderEnd == NULL)
	    return (NULL);

    }

    /* or the end of the entire thing */
    return (bufp);
}