19void ber_enc_init(BerEnc *e, uint8_t *buf,
size_t cap)
24 e->ok = (buf !=
nullptr && cap > 0);
27static void enc_byte(BerEnc *e, uint8_t b)
39static void enc_bytes(BerEnc *e,
const uint8_t *p,
size_t n)
41 for (
size_t i = 0; i < n; i++)
46static void enc_len(BerEnc *e,
size_t length)
50 enc_byte(e, (uint8_t)length);
58 tmp[k++] = (uint8_t)(v & 0xFF);
61 enc_byte(e, (uint8_t)(0x80 | k));
62 for (
int i = k - 1; i >= 0; i--)
66bool ber_put_tlv(BerEnc *e, uint8_t tag,
const uint8_t *val,
size_t n)
74bool ber_put_raw(BerEnc *e,
const uint8_t *bytes,
size_t n)
76 enc_bytes(e, bytes, n);
80bool ber_put_integer(BerEnc *e,
long v)
90 tmp[k++] = (uint8_t)(val & 0xFF);
92 }
while (!((val == 0 && !(tmp[k - 1] & 0x80)) || (val == -1 && (tmp[k - 1] & 0x80))) && k < (int)
sizeof(tmp));
94 enc_byte(e, (uint8_t)SnmpTag::BER_INTEGER);
95 enc_len(e, (
size_t)k);
96 for (
int i = k - 1; i >= 0; i--)
101bool ber_put_uint(BerEnc *e, uint8_t tag, uint32_t v)
110 tmp[k++] = (uint8_t)(val & 0xFF);
112 }
while (val && k < 4);
113 if (tmp[k - 1] & 0x80)
117 enc_len(e, (
size_t)k);
118 for (
int i = k - 1; i >= 0; i--)
123bool ber_put_octet_string(BerEnc *e, uint8_t tag,
const uint8_t *d,
size_t n)
125 return ber_put_tlv(e, tag, d, n);
128bool ber_put_null(BerEnc *e)
130 enc_byte(e, (uint8_t)SnmpTag::BER_NULL);
136static void oid_emit_arc(uint8_t *tmp,
size_t cap,
size_t *t, uint32_t v, BerEnc *e)
142 b[k++] = (uint8_t)(v & 0x7F);
145 for (
int i = k - 1; i >= 0; i--)
157bool ber_put_oid(BerEnc *e,
const uint32_t *arcs,
size_t n)
167 uint32_t first = 40u * arcs[0] + arcs[1];
168 oid_emit_arc(tmp,
sizeof(tmp), &t, first, e);
169 for (
size_t i = 2; i < n; i++)
170 oid_emit_arc(tmp,
sizeof(tmp), &t, arcs[i], e);
171 return ber_put_tlv(e, (uint8_t)SnmpTag::BER_OID, tmp, t);
174size_t ber_seq_begin(BerEnc *e, uint8_t tag)
177 size_t token = e->len;
184void ber_seq_end(BerEnc *e,
size_t token)
188 size_t content = e->len - (token + 3);
189 if (content > 0xFFFF)
194 e->buf[token] = 0x82;
195 e->buf[token + 1] = (uint8_t)((content >> 8) & 0xFF);
196 e->buf[token + 2] = (uint8_t)(content & 0xFF);
203void ber_dec_init(BerDec *d,
const uint8_t *buf,
size_t len)
208 d->ok = (buf !=
nullptr);
211bool ber_read_header(BerDec *d, uint8_t *tag,
size_t *length)
213 if (!d->ok || d->pos >= d->len)
218 *tag = d->buf[d->pos++];
220 if (d->pos >= d->len)
225 uint8_t l0 = d->buf[d->pos++];
234 if (k == 0 || k > 4 || d->pos + (
size_t)k > d->len)
240 for (
int i = 0; i < k; i++)
241 length_val = (length_val << 8) | d->buf[d->pos++];
247 if (length_val > d->len - d->pos)
252 *length = length_val;
256bool ber_read_integer(BerDec *d,
long *out)
260 if (!ber_read_header(d, &tag, &len) || tag != (uint8_t)SnmpTag::BER_INTEGER || len == 0 || len > 8)
267 uint64_t uv = (d->buf[d->pos] & 0x80) ? ~(uint64_t)0 : 0;
268 for (
size_t i = 0; i < len; i++)
269 uv = (uv << 8) | d->buf[d->pos + i];
275bool ber_read_oid(BerDec *d, uint32_t *arcs,
size_t max,
size_t *n)
279 if (!ber_read_header(d, &tag, &len) || tag != (uint8_t)SnmpTag::BER_OID || len == 0 || max < 2)
284 const uint8_t *p = d->buf + d->pos;
287 bool first_done =
false;
290 for (
size_t i = 0; i < len; i++)
292 acc = (acc << 7) | (uint32_t)(p[i] & 0x7F);
297 uint32_t arc0 = acc / 40u;
300 arcs[count++] = arc0;
301 arcs[count++] = acc - 40u * arc0;
320bool ber_skip(BerDec *d,
size_t length)
322 if (!d->ok || d->pos > d->len || length > d->len - d->pos)
#define SNMP_MAX_OID_LEN
Maximum sub-identifiers (arcs) in an SNMP object identifier.
Zero-heap ASN.1 BER encoder/decoder for the SNMP agent (DETWS_ENABLE_SNMP).