0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 10:11:53 +00:00
bird/proto/snmp/snmp_utils.c

837 lines
20 KiB
C
Raw Normal View History

2022-11-22 13:16:09 +00:00
/*
* BIRD -- Simple Network Management Protocol (SNMP) helper functions
*
* (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
* (c) 2022 CZ.NIC z.s.p.o
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
*/
#include "snmp_utils.h"
inline void
snmp_pdu_context(const struct snmp_proto *p, struct snmp_pdu *pdu, sock *sk)
{
pdu->error = AGENTX_RES_NO_ERROR;
if (!snmp_is_partial(p))
{
pdu->buffer = sk->tpos;
pdu->size = sk->tbuf + sk->tbsize - sk->tpos;
pdu->index = 0;
return;
}
pdu->buffer = sk->tbuf + p->header_offset + p->last_size;
pdu->size = sk->tbuf + sk->tbsize - pdu->buffer;
pdu->index = p->last_index;
}
inline void
snmp_session(const struct snmp_proto *p, struct agentx_header *h)
{
STORE_U32(h->session_id, p->session_id);
STORE_U32(h->transaction_id, p->transaction_id);
STORE_U32(h->packet_id, p->packet_id);
//log(L_INFO "storing packet id %u into the header %p", p->packet_id, h);
}
inline int
snmp_has_context(const struct agentx_header *h)
{
return h->flags & AGENTX_NON_DEFAULT_CONTEXT;
}
inline byte *
snmp_add_context(struct snmp_proto *p, struct agentx_header *h, uint contid)
{
u8 flags = LOAD_U8(h->flags);
STORE_U8(h->flags, flags | AGENTX_NON_DEFAULT_CONTEXT);
// TODO append the context after the header
(void)p;
(void)contid;
return (void *)h + AGENTX_HEADER_SIZE;
}
inline void *
snmp_varbind_data(const struct agentx_varbind *vb)
{
uint name_size = snmp_oid_size(&vb->name);
return (void *)&vb->name + name_size;
}
2022-11-22 13:16:09 +00:00
/**
2022-12-17 17:16:19 +00:00
* snmp_is_oid_empty - check if oid is null-valued
2022-11-22 13:16:09 +00:00
* @oid: object identifier to check
*
* Test if the oid header is full of zeroes. For @oid NULL returns 0.
*/
int
2023-07-26 12:02:23 +00:00
snmp_is_oid_empty(const struct oid *oid)
2022-11-22 13:16:09 +00:00
{
if (oid != NULL)
return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0 &&
LOAD_U8(oid->include) == 0;
2022-11-22 13:16:09 +00:00
else
return 0;
}
/**
* snmp_pkt_len - returns size of SNMP packet payload (without header)
* @buf: packet first byte
* @pkt: first byte past packet end
*/
2023-07-26 12:02:23 +00:00
uint
snmp_pkt_len(const byte *start, const byte *end)
2023-07-26 12:02:23 +00:00
{
return (end - start) - AGENTX_HEADER_SIZE;
}
/*
* snmp_oid_copy - copy OID from one place to another
* @dest: destination to use
* @src: OID to be copied from
2023-07-26 12:02:23 +00:00
*/
void
snmp_oid_copy(struct oid *dest, const struct oid *src)
2023-07-26 12:02:23 +00:00
{
STORE_U8(dest->n_subid, src->n_subid);
STORE_U8(dest->prefix, src->prefix);
STORE_U8(dest->include, src->include ? 1 : 0);
2023-07-26 12:02:23 +00:00
STORE_U8(dest->pad, 0);
for (int i = 0; i < LOAD_U8(src->n_subid); i++)
2023-07-26 12:02:23 +00:00
STORE_U32(dest->ids[i], src->ids[i]);
}
/*
* snmp_oid_duplicate - duplicate an OID from memory pool
* @pool: pool to use
* @oid: OID to be duplicated
2023-07-26 12:02:23 +00:00
*/
struct oid *
snmp_oid_duplicate(pool *pool, const struct oid *oid)
2022-11-22 13:16:09 +00:00
{
2023-07-26 12:02:23 +00:00
struct oid *res = mb_alloc(pool, snmp_oid_size(oid));
memcpy(res, oid, snmp_oid_size(oid));
return res;
2022-11-22 13:16:09 +00:00
}
2022-12-10 17:08:00 +00:00
/**
* create new null oid (blank)
* @p: pool hodling snmp_proto structure
*/
struct oid *
snmp_oid_blank(struct snmp_proto *p)
{
return mb_allocz(p->p.pool, sizeof(struct oid));
}
/**
* snmp_str_size_from_len - return in-buffer octet-string size
* @len: length of C-string, returned from strlen()
*/
2023-07-26 12:02:23 +00:00
size_t
snmp_str_size_from_len(uint len)
{
return 4 + BIRD_ALIGN(len, 4);
}
2022-11-22 13:16:09 +00:00
/**
* snmp_str_size - return in packet size of supplied string
* @str: measured string
*
* Returned value is string length aligned to 4 byte with 32bit length
* annotation included.
*/
2023-07-26 12:02:23 +00:00
inline size_t
2022-11-22 13:16:09 +00:00
snmp_str_size(const char *str)
{
2023-07-26 12:02:23 +00:00
return snmp_str_size_from_len(strlen(str));
2022-11-22 13:16:09 +00:00
}
/**
* snmp_oid_size - measure size of oid in bytes
* @o: object identifier to use
*/
uint
2023-07-26 12:02:23 +00:00
snmp_oid_size(const struct oid *o)
2022-11-22 13:16:09 +00:00
{
2023-03-14 13:09:45 +00:00
return 4 + (o->n_subid * 4);
2022-11-22 13:16:09 +00:00
}
2022-12-10 17:08:00 +00:00
/**
* snmp_get_size - calculate size for allocation
* @n_subid: number of ids in oid
*/
inline size_t
snmp_oid_sizeof(uint n_subid)
{
return sizeof(struct oid) + n_subid * sizeof(u32);
}
/*
* snmp_varbind_hdr_size_from_oid - return in-buffer size of VarBind
* @oid: OID used as VarBind's name
*
* This function assume @oid to be not NULL.
*/
uint
snmp_varbind_hdr_size_from_oid(const struct oid *oid)
{
ASSUME(oid);
return snmp_oid_size(oid) + OFFSETOF(struct agentx_varbind, name);
}
/*
* snmp_set_varbind_type - set VarBind's type field
* @vb: Varbind inside TX-buffer
* @t: a valid type to be set
*
* This function assumes valid @t.
*/
inline void
snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t)
2023-07-26 12:02:23 +00:00
{
ASSUME(t != AGENTX_INVALID);
STORE_U16(vb->type, t);
}
/* Internal wrapper */
static inline u16
snmp_load_varbind_type(const struct agentx_varbind *vb)
{
return LOAD_U16(vb->type);
}
/*
* snmp_get_varbind_type - loads a VarBind type
* @vb: VarBind pointer to TX-buffer
*
* This function assumes VarBind with valid type, always call snmp_test_varbind
* for in TX-buffer VarBinds!
*/
inline enum agentx_type
snmp_get_varbind_type(const struct agentx_varbind *vb)
{
ASSUME(snmp_test_varbind(vb));
return (enum agentx_type) snmp_load_varbind_type(vb);
}
static inline uint
snmp_get_octet_size(const struct agentx_octet_str *str)
{
return LOAD_U32(str->length);
2023-07-26 12:02:23 +00:00
}
2022-11-22 13:16:09 +00:00
/**
* snmp_varbind_header_size - measure size of VarBind without data in bytes
* @vb: VarBind to use
*
* Return size including whole OID as well as the VarBind header.
2022-11-22 13:16:09 +00:00
*/
uint
snmp_varbind_header_size(const struct agentx_varbind *vb)
2022-11-22 13:16:09 +00:00
{
2023-07-26 12:02:23 +00:00
return snmp_varbind_hdr_size_from_oid(&vb->name);
}
uint
snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
2023-07-26 12:02:23 +00:00
{
ASSUME(snmp_test_varbind(vb));
2023-07-26 12:02:23 +00:00
enum agentx_type type = snmp_get_varbind_type(vb);
int value_size = agentx_type_size(type);
2023-07-26 12:02:23 +00:00
uint vb_header = snmp_varbind_header_size(vb);
2023-07-26 12:02:23 +00:00
if (value_size == 0)
return vb_header;
2023-07-26 12:02:23 +00:00
if (value_size > 0)
return vb_header + value_size;
switch (type)
{
case AGENTX_OBJECT_ID:;
struct oid *oid = snmp_varbind_data(vb);
return vb_header + snmp_oid_size(oid);
case AGENTX_OCTET_STRING:
case AGENTX_IP_ADDRESS:
case AGENTX_OPAQUE:;
struct agentx_octet_str *string = snmp_varbind_data(vb);
return vb_header + snmp_get_octet_size(string);
default:
/* Shouldn't happen */
return 0;
}
2023-07-26 12:02:23 +00:00
}
/**
* snmp_varbind_size - get size of in-buffer VarBind
* @vb: VarBind to measure
* @limit: upper limit of bytes that can be used
*
* This functions assumes valid VarBind type.
* Return 0 for Varbinds longer than limit, Varbind's size otherwise.
*/
uint
snmp_varbind_size(const struct agentx_varbind *vb, uint limit)
{
ASSUME(snmp_test_varbind(vb));
if (limit < sizeof(struct agentx_varbind))
return 0;
enum agentx_type type = agentx_type_size(snmp_get_varbind_type(vb));
int s = agentx_type_size(type);
uint vb_header = snmp_varbind_header_size(vb);
if (limit < vb_header)
return 0;
if (s == 0)
return vb_header;
if (s > 0 && vb_header + s <= limit)
return vb_header + s;
else if (s > 0)
return 0;
switch (type)
{
case AGENTX_OBJECT_ID:;
struct oid *oid = snmp_varbind_data(vb);
return vb_header + snmp_oid_size(oid);
case AGENTX_OCTET_STRING:
case AGENTX_IP_ADDRESS:
case AGENTX_OPAQUE:;
struct agentx_octet_str *os = snmp_varbind_data(vb);
return vb_header + snmp_get_octet_size(os);
default:
/* This should not happen */
return 0;
}
}
/*
* snmp_test_varbind - test validity of VarBind's type
* @vb: VarBind to test
*/
int
snmp_test_varbind(const struct agentx_varbind *vb)
{
ASSUME(vb);
u16 type = snmp_load_varbind_type(vb);
if (type == AGENTX_INTEGER ||
type == AGENTX_OCTET_STRING ||
type == AGENTX_NULL ||
type == AGENTX_OBJECT_ID ||
type == AGENTX_IP_ADDRESS ||
type == AGENTX_COUNTER_32 ||
type == AGENTX_GAUGE_32 ||
type == AGENTX_TIME_TICKS ||
type == AGENTX_OPAQUE ||
type == AGENTX_COUNTER_64 ||
type == AGENTX_NO_SUCH_OBJECT ||
type == AGENTX_NO_SUCH_INSTANCE ||
type == AGENTX_END_OF_MIB_VIEW)
return 1;
else
return 0;
}
/*
* snmp_create_varbind - create a null-typed VarBind in buffer
* @buf: buffer to use
*/
struct agentx_varbind *
snmp_create_varbind_null(byte *buf)
{
struct oid o = { 0 };
struct agentx_varbind *vb = snmp_create_varbind(buf, &o);
snmp_set_varbind_type(vb, AGENTX_NULL);
return vb;
}
/*
* snmp_create_varbind - initialize in-buffer non-typed VarBind
* @buf: pointer to first unused buffer byte
* @oid: OID to use as VarBind name
*/
2022-11-22 13:16:09 +00:00
struct agentx_varbind *
snmp_create_varbind(byte *buf, struct oid *oid)
{
struct agentx_varbind *vb = (void *) buf;
STORE_U16(vb->pad, 0);
snmp_oid_copy(&vb->name, oid);
2022-11-22 13:16:09 +00:00
return vb;
}
#if 0
2023-07-26 12:02:23 +00:00
byte *
snmp_fix_varbind(struct agentx_varbind *vb, struct oid *new)
2022-11-22 13:16:09 +00:00
{
memcpy(&vb->name, new, snmp_oid_size(new));
2023-07-26 12:02:23 +00:00
return (void *) vb + snmp_varbind_header_size(vb);
2022-11-22 13:16:09 +00:00
}
#endif
2022-11-22 13:16:09 +00:00
/**
* snmp_oid_ip4_index - check IPv4 address validity in oid
* @o: object identifier holding ip address
* @start: index of first address id
*/
int
2023-07-26 12:02:23 +00:00
snmp_valid_ip4_index(const struct oid *o, uint start)
2022-11-22 13:16:09 +00:00
{
if (start + 3 < o->n_subid)
return snmp_valid_ip4_index_unsafe(o, start);
else
2023-07-26 12:34:01 +00:00
return 0;
2022-11-22 13:16:09 +00:00
}
/**
* snmp_valid_ip4_index_unsafe - check validity of IPv4 address in oid
* @o: object identifier holding ip address
* @start: index of first address id
*
* This function is unsafe - no checks of object identifier ids
* length sufficiency is done.
*/
int
2023-07-26 12:02:23 +00:00
snmp_valid_ip4_index_unsafe(const struct oid *o, uint start)
2022-11-22 13:16:09 +00:00
{
for (int i = 0; i < 4; i++)
if (o->ids[start + i] >= 256)
2023-07-26 12:34:01 +00:00
return 0;
2023-03-24 14:00:54 +00:00
2023-07-26 12:34:01 +00:00
return 1;
2022-11-22 13:16:09 +00:00
}
/*
* snmp_put_nstr - copy c-string into buffer with limit
* @buf: destination buffer
* @str: string to use
* @len: number of characters to use from string
*/
2023-07-26 12:02:23 +00:00
byte *
snmp_put_nstr(byte *buf, const char *str, uint len)
{
uint alen = BIRD_ALIGN(len, 4);
struct agentx_octet_str *octet = (void *) buf;
STORE_U32(octet->length, len);
memcpy(&octet->data, str, len);
buf += len + sizeof(octet->length);
2023-07-26 12:02:23 +00:00
/* Insert zero padding in the gap at the end */
for (uint i = 0; i < alen - len; i++)
STORE_U8(buf[i], '\0');
2023-07-26 12:02:23 +00:00
return buf + (alen - len);
2023-07-26 12:02:23 +00:00
}
2022-11-22 13:16:09 +00:00
/**
* snmp_put_str - put string into SNMP PDU transcieve buffer
* @buf: pointer to first unoccupied buffer byte
* @str: string to place
*
* Handles all conditions specified by RFC, namely string length annotation
* and padding 4 byte alignment with zeroes. Return NULL if string is too large
* for SNMP message.
*/
byte *
snmp_put_str(byte *buf, const char *str)
{
uint len = strlen(str);
2023-07-26 12:02:23 +00:00
return snmp_put_nstr(buf, str, len);
2022-11-22 13:16:09 +00:00
}
2023-03-24 14:00:54 +00:00
byte *
2023-07-26 12:02:23 +00:00
snmp_put_ip4(byte *buf, ip4_addr addr)
2023-03-24 14:00:54 +00:00
{
/* octet string has size 4 bytes */
STORE_PTR(buf, 4);
/* Always use Network byte order */
2023-07-26 12:02:23 +00:00
put_u32(buf+4, ip4_to_u32(addr));
2023-03-24 14:00:54 +00:00
return buf + 8;
}
2022-11-22 13:16:09 +00:00
byte *
snmp_put_blank(byte *buf)
{
STORE_PTR(buf, 0);
return buf + 4;
}
/**
* snmp_put_oid - put oid into SNMP PDU transcieve buffer
* @buf: pointer to first free buffer byte
* @oid: object identifier to use
*/
byte *
snmp_put_oid(byte *buf, struct oid *oid)
{
struct oid *oid_buf = (void *) buf;
snmp_oid_copy(oid_buf, oid);
return buf + snmp_oid_size(oid);
2022-11-22 13:16:09 +00:00
}
/**
* snmp_put_fbyte - put one padded byte to SNMP PDU transcieve buffer
* @buf: pointer to free buffer byte
* @data: byte to use
*
* Put @data into buffer @buf with 3B zeroed padding.
*/
byte *
snmp_put_fbyte(byte *buf, u8 data)
{
STORE_U8(*buf++, data);
memset(buf, 0, 3); /* we fill the 24bit padding with zeros */
2022-11-22 13:16:09 +00:00
return buf + 3;
}
void
snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
{
u32 temp = ip4_to_u32(addr);
2023-07-26 12:02:23 +00:00
STORE_U32(o->ids[start], temp >> 24);
STORE_U32(o->ids[start + 1], (temp >> 16) & 0xFF);
STORE_U32(o->ids[start + 2], (temp >> 8) & 0xFF);
STORE_U32(o->ids[start + 3], temp & 0xFF);
2022-11-22 13:16:09 +00:00
}
2023-10-18 16:06:24 +00:00
void UNUSED
snmp_oid_dump(const struct oid *oid)
2022-11-22 13:16:09 +00:00
{
log(L_WARN "OID DUMP ========");
if (oid == NULL)
{
log(L_WARN "is eqaul to NULL");
log(L_WARN "OID DUMP END ====");
2023-03-14 13:09:45 +00:00
log(L_WARN ".");
2022-11-22 13:16:09 +00:00
return;
}
else if (snmp_is_oid_empty(oid))
{
log(L_WARN "is empty");
log(L_WARN "OID DUMP END ====");
2023-03-14 13:09:45 +00:00
log(L_WARN ".");
2022-11-22 13:16:09 +00:00
return;
}
log(L_WARN " #ids: %4u prefix %3u include: %5s",
oid->n_subid, oid->prefix, (oid->include)? "true" : "false");
log(L_WARN "IDS -------------");
for (int i = 0; i < oid->n_subid; i++)
log(L_WARN " %2u: %11u ~ 0x%08X", i, oid->ids[i], oid->ids[i]);
log(L_WARN "OID DUMP END ====");
log(L_WARN);
}
2022-11-29 15:30:20 +00:00
/** snmp_oid_compare - find the lexicographical order relation between @left and @right
2023-03-24 14:00:54 +00:00
* both @left and @right has to be non-blank.
2022-11-29 15:30:20 +00:00
* @left: left object id relation operant
* @right: right object id relation operant
*
2023-03-24 14:00:54 +00:00
* function returns 0 if left == right,
* -1 if left < right,
* and 1 otherwise
2022-11-29 15:30:20 +00:00
*/
int
2023-07-26 12:02:23 +00:00
snmp_oid_compare(const struct oid *left, const struct oid *right)
2022-11-29 15:30:20 +00:00
{
if (left->prefix == 0 && right->prefix == 0)
goto test_ids;
if (right->prefix == 0)
2023-03-24 14:00:54 +00:00
return (-1) * snmp_oid_compare(right, left);
2022-11-29 15:30:20 +00:00
if (left->prefix == 0)
{
for (int i = 0; i < 4; i++)
if (left->ids[i] < snmp_internet[i])
2022-11-29 15:30:20 +00:00
return -1;
else if (left->ids[i] > snmp_internet[i])
2022-11-29 15:30:20 +00:00
return 1;
for (int i = 0; i < MIN(left->n_subid - 4, right->n_subid); i++)
if (left->ids[i + 4] < right->ids[i])
return -1;
else if (left->ids[i + 4] > right->ids[i])
return 1;
goto all_same;
}
if (left->prefix < right->prefix)
return -1;
else if (left->prefix > right->prefix)
return 1;
test_ids:
for (int i = 0; i < MIN(left->n_subid, right->n_subid); i++)
if (left->ids[i] < right->ids[i])
return -1;
else if (left->ids[i] > right->ids[i])
return 1;
all_same:
/* shorter sequence is before longer in lexicografical order */
if (left->n_subid < right->n_subid)
return -1;
else if (left->n_subid > right->n_subid)
return 1;
else
return 0;
}
2022-12-10 17:08:00 +00:00
struct snmp_registration *
snmp_registration_create(struct snmp_proto *p, u8 mib_class)
2022-12-10 17:08:00 +00:00
{
struct snmp_registration *r;
r = mb_alloc(p->p.pool, sizeof(struct snmp_registration));
2022-12-10 17:08:00 +00:00
r->n.prev = r->n.next = NULL;
r->session_id = p->session_id;
/* will be incremented by snmp_session() macro during packet assembly */
2022-12-10 17:08:00 +00:00
r->transaction_id = p->transaction_id;
// TODO where is incremented? is this valid?
r->packet_id = p->packet_id + 1;
log(L_INFO "using registration packet_id %u", r->packet_id);
2022-12-10 17:08:00 +00:00
r->mib_class = mib_class;
add_tail(&p->registration_queue, &r->n);
2022-12-10 17:08:00 +00:00
return r;
}
int
snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, u8 class)
2022-12-10 17:08:00 +00:00
{
log(L_INFO "snmp_reg_same() r->packet_id %u p->packet_id %u", r->packet_id, h->packet_id);
2022-12-10 17:08:00 +00:00
return
(r->mib_class == class) &&
(r->session_id == h->session_id) &&
(r->transaction_id == h->transaction_id) &&
(r->packet_id == h->packet_id);
}
2022-12-17 17:16:19 +00:00
2023-10-18 16:06:24 +00:00
void UNUSED
snmp_dump_packet(byte UNUSED *pkt, uint size)
2022-12-17 17:16:19 +00:00
{
DBG("dump");
2023-03-14 13:09:45 +00:00
for (uint i = 0; i < size; i += 4)
DBG("pkt [%d] 0x%02x%02x%02x%02x", i, pkt[i],pkt[i+1],pkt[i+2],pkt[i+3]);
DBG("end dump");
2022-12-10 17:08:00 +00:00
}
2023-07-26 12:02:23 +00:00
/*
* agentx_type_size - get in packet VarBind type size
* @type: VarBind type
*
* Returns length of agentx_type @type in bytes, Variable length types result in
* -1.
2023-07-26 12:02:23 +00:00
*/
int
agentx_type_size(enum agentx_type type)
{
/*
* AGENTX_NULL, AGENTX_NO_SUCH_OBJECT, AGENTX_NO_SUCH_INSTANCE,
* AGENTX_END_OF_MIB_VIEW
*/
if (type >= AGENTX_NO_SUCH_OBJECT || type == AGENTX_NULL)
return 0;
/* AGENTX_INTEGER, AGENTX_COUNTER_32, AGENTX_GAUGE_32, AGENTX_TIME_TICKS */
if (type >= AGENTX_COUNTER_32 && type <= AGENTX_TIME_TICKS ||
type == AGENTX_INTEGER)
return 4;
/* AGENTX_COUNTER_64 */
if (type == AGENTX_COUNTER_64)
return 8;
/* AGENTX_OBJECT_ID, AGENTX_OCTET_STRING, AGENTX_IP_ADDRESS, AGENTX_OPAQUE */
else
return -1;
}
static inline byte *
snmp_varbind_type32(struct agentx_varbind *vb, uint size, enum agentx_type type, u32 val)
{
ASSUME(agentx_type_size(type) == 4); /* type has 4B representation */
if (size < (uint) agentx_type_size(type))
return NULL;
snmp_set_varbind_type(vb, type);
u32 *data = snmp_varbind_data(vb);
STORE_PTR(data, val); /* note that the data has u32 type */
data++;
return (byte *) data;
2023-07-26 12:02:23 +00:00
}
inline byte *
snmp_varbind_int(struct agentx_varbind *vb, uint size, u32 val)
{
return snmp_varbind_type32(vb, size, AGENTX_INTEGER, val);
}
inline byte *
snmp_varbind_counter32(struct agentx_varbind *vb, uint size, u32 val)
{
return snmp_varbind_type32(vb, size, AGENTX_COUNTER_32, val);
}
inline byte *
snmp_varbind_ticks(struct agentx_varbind *vb, uint size, u32 val)
{
return snmp_varbind_type32(vb, size, AGENTX_TIME_TICKS, val);
}
2023-07-26 12:02:23 +00:00
inline byte *
snmp_varbind_gauge32(struct agentx_varbind *vb, uint size, s64 val)
{
return snmp_varbind_type32(vb, size, AGENTX_GAUGE_32,
MAX(0, MIN(val, UINT32_MAX)));
}
inline byte *
snmp_varbind_ip4(struct agentx_varbind *vb, uint size, ip4_addr addr)
{
if (size < snmp_str_size_from_len(4))
return NULL;
snmp_set_varbind_type(vb, AGENTX_IP_ADDRESS);
return snmp_put_ip4(snmp_varbind_data(vb), addr);
2023-07-26 12:02:23 +00:00
}
// TODO doc string, we have already the varbind prepared
2023-07-26 12:02:23 +00:00
inline byte *
snmp_varbind_nstr(struct agentx_varbind *vb, uint size, const char *str, uint len)
{
if (size < snmp_str_size_from_len(len))
return NULL;
snmp_set_varbind_type(vb, AGENTX_OCTET_STRING);
return snmp_put_nstr(snmp_varbind_data(vb), str, len);
2023-07-26 12:02:23 +00:00
}
inline enum agentx_type
snmp_search_res_to_type(enum snmp_search_res r)
{
ASSUME(r != SNMP_SEARCH_OK);
enum agentx_type type_arr[] = {
2023-07-26 12:02:23 +00:00
[SNMP_SEARCH_NO_OBJECT] = AGENTX_NO_SUCH_OBJECT,
[SNMP_SEARCH_NO_INSTANCE] = AGENTX_NO_SUCH_INSTANCE,
[SNMP_SEARCH_END_OF_VIEW] = AGENTX_END_OF_MIB_VIEW,
};
return type_arr[r];
}
inline int
snmp_test_close_reason(byte value)
{
if (value >= (byte) AGENTX_CLOSE_OTHER &&
value <= (byte) AGENTX_CLOSE_BY_MANAGER)
return 1;
else
return 0;
}
inline struct agentx_header *
snmp_create_tx_header(struct snmp_proto *p, byte *tbuf)
{
/* the response is created always in TX-buffer */
p->header_offset = tbuf - p->sock->tbuf;
ASSERT(p->header_offset < p->sock->tbsize);
return (struct agentx_header *) tbuf;
}
/*
* Partial header manipulation functions
*/
/*
* snmp_is_partial - check if we have a partially parted packet in TX-buffer
* @p: SNMP protocol instance
*/
inline int
snmp_is_partial(const struct snmp_proto *p)
{
return p->last_size > 0;
}
/*
* snmp_get_header - restore partial packet's header from TX-buffer
* @p: SNMP protocol instance
*/
inline struct agentx_header *
snmp_get_header(const struct snmp_proto *p)
{
/* Nonzero last size indicates existence of partial packet */
ASSERT(p->last_size && p->header_offset < p->sock->tbsize);
return (struct agentx_header *) (p->sock->tbuf + p->header_offset);
}
/*
* snmp_set_header - store partial packet's header into protocol
* @p: SNMP protocol instance
* @h: header of the currently parsed PDU
* @c: SNMP PDU context
*
* Store the needed values regarding later partial PDU processing.
*/
inline void
snmp_set_header(struct snmp_proto *p, struct agentx_header *h, struct snmp_pdu *c)
{
sock *sk = p->sock;
// TODO agentx_headier in last_size or not?
ASSERT(c->buffer - sk->tpos >= AGENTX_HEADER_SIZE);
p->last_size = c->buffer - sk->tpos + p->last_size;
p->header_offset = (((byte *) h) - sk->tbuf);
p->last_index = c->index;
log(L_INFO "using p->packet_id %u as a p->last_pkt_id %u", p->packet_id, p->last_pkt_id);
p->last_pkt_id = p->packet_id;
log(L_INFO "snmp_set_header() tbuf %p tpos %p buffer %p header %p header2 %p offset %u last_size %u last_index %u last_pkt_id %u",
sk->tbuf, sk->tpos, c->buffer,h,(byte*)h, p->header_offset, p->last_size,
p->last_index, p->last_pkt_id);
}
/*
* snmp_unset_header - clean partial packet's header
* @p: SNMP protocol instance
*
* Clean the partial packet processing fields of protocol when the packet is
* fully processed.
*/
inline void
snmp_unset_header(struct snmp_proto *p)
{
p->last_size = 0;
p->header_offset = 0;
p->last_index = 0;
p->last_pkt_id = 0;
}