Кодирование SNMP-ловушки с использованием функций модуля Net-SNMP asn1.c

Я хотел бы создать ловушку SNMP, используя модуль asn1.c, поставляемый как часть Net-SNMP 5.7.3. Я могу использовать структуры Net-SNMP, такие как snmp_pdu, но я бы хотел сам закодировать пакет в буфер символов (скомпилированный и связанный с asn1.o).

Ниже приведен код, который я пытался написать, но в моей кодировке ASN.1, похоже, есть ошибки, и мне нужно также закодировать некоторые varbind.

Может кто-нибудь помочь с моей кодировкой ASN.1 и сообщить мне, что я делаю неправильно?

Заранее спасибо.

#include <stdlib.h>

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/types.h>
#include <net-snmp/library/asn1.h>

// based on part of _snmp_build() function in Net-SNMP 5.7.3
int trap_build(struct snmp_pdu *pdu, u_char *pkt, size_t *pkt_len, int af_family)
{
    size_t len = *pkt_len;

    u_char *cp;
    u_char *h0e = NULL;
    u_char *h1e = NULL;
    u_char *h1 = NULL;

    size_t length;

    /*
     * save length 
     */
    length = *pkt_len;

    /*
     * Save current location and build SEQUENCE tag and length
     * placeholder for SNMP message sequence
     * (actual length will be inserted later) 
     */
    cp = asn_build_sequence(pkt,
                            pkt_len,
                            (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                            0);
    if (cp == NULL) {
        printf("asn_build_sequence() returned NULL\n");
        return -1;
    }
    h0e = cp;

    /*
     * store the version field 
     */
    long version = pdu->version;
    cp = asn_build_int(cp, pkt_len,
                               (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                         ASN_INTEGER), (long *) &version,
                               sizeof(version));
    if (cp == NULL) {
        printf("asn_build_int() returned NULL\n");
        return -1;
    }

    /*
     * store the community string 
     */
    cp = asn_build_string(cp, pkt_len,
                                 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                            ASN_OCTET_STR),  pdu->community,
                              pdu->community_len);
    if (cp == NULL) {
        printf("asn_build_string() returned NULL\n");
        return -1;
    }

    // TODO Check return code ?
    asn_build_sequence(pkt, &length,
                           (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                           cp - h0e);

    h1 = cp;
    cp = asn_build_sequence(cp, &length, (u_char)pdu->command, 0);
    if (cp == NULL) {
        printf("asn_build_sequence() returned NULL");
        return -1;
    }
    h1e = cp;

    switch(af_family) {
    case AF_INET:
        cp = snmp_pdu_build(pdu, cp, &length);
        break;
#ifdef CYGPKG_NET_FREEBSD_INET6
    case AF_INET6:
        cp = snmp_pdu_build_v6(pdu, cp, &length);
        break;
#endif /* CYGPKG_NET_FREEBSD_INET6 */
    default:
        printf("unsupported address family = %d\n", af_family);
        return -1;
        break;
    }

    // insert the actual length of the message sequence
    if ((pdu->version == SNMP_VERSION_1)
        || (pdu->version == SNMP_VERSION_2c))  {
        asn_build_sequence(cp, &length,
                       (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
                       cp - h0e);
    }
    else {
        printf("unsupported SNMP version = %ld\n", pdu->version);
        return -1;
    }

    return 0;
}

int main()
{
    size_t *pkt_len;
    size_t len = 256;
    pkt_len = &len;
    u_char pkt[len];

    netsnmp_pdu *pdu = NULL;

    pdu = calloc(1, sizeof(netsnmp_pdu));
    if (pdu == NULL) {
        printf("malloc() returned NULL\n");
        return -1;
    }

    memset(pkt, 0, len);

    int af_family = AF_INET; // or AF_INET6

    pdu->version = SNMP_VERSION_2c;
    pdu->community = strdup("public");
    pdu->community_len = strlen(pdu->community);
    pdu->command = SNMP_MSG_INFORM; // or SNMP_MSG_TRAP2 or SNMP_MSG_TRAP
    if (pdu->command == SNMP_MSG_INFORM) {
        pdu->flags &= UCD_MSG_FLAG_EXPECT_RESPONSE;
    }
    else {
        pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE);
    }
    pdu->reqid = 239162894;
    pdu->errstat = 0;
    pdu->errindex = 0;
    // pdu->variables (struct variable_list) TODO varbinds

    printf("pdu->command = %s(%x)\n", snmp_pdu_type(pdu->command), pdu->command);

    int ret = trap_build(pdu, pkt, pkt_len, af_family);

    printf("packet len = %d: [ ", (int)*pkt_len);
    for (int i = 0; i < *pkt_len; i++) {
        printf("%2.2X ", pkt[i]);
    }
    printf("]\n");

    exit(ret);
}

Вот (начало) вывода, который я получаю из вышеуказанной программы:

pdu->command = INFORM(a6)
packet len = 241: [ 30 82 00 0B 02 01 01 04 06 70 75 62 6C 69 63 A6 82 00 00 A6 82 00 10 02 04 0E 41 56 0E 02 01 00 02 01 00 30 82 00 00 30 82 00 23 00 00 00 00 00 00 00 ...

0 ответов

Другие вопросы по тегам