19void pc_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)
41static void enc_bytes(BerEnc *e,
const uint8_t *p,
size_t n)
43 for (
size_t i = 0; i < n; i++)
50static void enc_len(BerEnc *e,
size_t length)
54 enc_byte(e, (uint8_t)length);
62 tmp[k++] = (uint8_t)(v & 0xFF);
65 enc_byte(e, (uint8_t)(0x80 | k));
66 for (
int i = k - 1; i >= 0; i--)
72bool pc_ber_put_tlv(BerEnc *e, uint8_t tag,
const uint8_t *val,
size_t n)
80bool pc_ber_put_raw(BerEnc *e,
const uint8_t *bytes,
size_t n)
82 enc_bytes(e, bytes, n);
86bool pc_ber_put_integer(BerEnc *e,
long v)
96 tmp[k++] = (uint8_t)(val & 0xFF);
101 }
while (!((val == 0 && !(tmp[k - 1] & 0x80)) || (val == -1 && (tmp[k - 1] & 0x80))) && k < (int)
sizeof(tmp));
104 enc_byte(e, (uint8_t)SnmpTag::BER_INTEGER);
105 enc_len(e, (
size_t)k);
106 for (
int i = k - 1; i >= 0; i--)
113bool pc_ber_put_uint(BerEnc *e, uint8_t tag, uint32_t v)
122 tmp[k++] = (uint8_t)(val & 0xFF);
126 }
while (val && k < 4);
127 if (tmp[k - 1] & 0x80)
133 enc_len(e, (
size_t)k);
134 for (
int i = k - 1; i >= 0; i--)
141bool pc_ber_put_octet_string(BerEnc *e, uint8_t tag,
const uint8_t *d,
size_t n)
143 return pc_ber_put_tlv(e, tag, d, n);
146bool pc_ber_put_null(BerEnc *e)
148 enc_byte(e, (uint8_t)SnmpTag::BER_NULL);
154static void oid_emit_arc(uint8_t *tmp,
size_t cap,
size_t *t, uint32_t v, BerEnc *e)
160 b[k++] = (uint8_t)(v & 0x7F);
163 for (
int i = k - 1; i >= 0; i--)
181bool pc_ber_put_oid(BerEnc *e,
const uint32_t *arcs,
size_t n)
191 uint32_t first = 40u * arcs[0] + arcs[1];
192 oid_emit_arc(tmp,
sizeof(tmp), &t, first, e);
193 for (
size_t i = 2; i < n; i++)
195 oid_emit_arc(tmp,
sizeof(tmp), &t, arcs[i], e);
197 return pc_ber_put_tlv(e, (uint8_t)SnmpTag::BER_OID, tmp, t);
200size_t pc_ber_seq_begin(BerEnc *e, uint8_t tag)
203 size_t token = e->len;
210void pc_ber_seq_end(BerEnc *e,
size_t token)
216 size_t content = e->len - (token + 3);
217 if (content > 0xFFFF)
222 e->buf[token] = 0x82;
223 e->buf[token + 1] = (uint8_t)((content >> 8) & 0xFF);
224 e->buf[token + 2] = (uint8_t)(content & 0xFF);
231void pc_ber_dec_init(BerDec *d,
const uint8_t *buf,
size_t len)
236 d->ok = (buf !=
nullptr);
239bool pc_ber_read_header(BerDec *d, uint8_t *tag,
size_t *length)
241 if (!d->ok || d->pos >= d->len)
246 *tag = d->buf[d->pos++];
248 if (d->pos >= d->len)
253 uint8_t l0 = d->buf[d->pos++];
262 if (k == 0 || k > 4 || d->pos + (
size_t)k > d->len)
268 for (
int i = 0; i < k; i++)
270 length_val = (length_val << 8) | d->buf[d->pos++];
277 if (length_val > d->len - d->pos)
282 *length = length_val;
286bool pc_ber_read_integer(BerDec *d,
long *out)
290 if (!pc_ber_read_header(d, &tag, &len) || tag != (uint8_t)SnmpTag::BER_INTEGER || len == 0 || len > 8)
297 uint64_t uv = (d->buf[d->pos] & 0x80) ? ~(uint64_t)0 : 0;
298 for (
size_t i = 0; i < len; i++)
300 uv = (uv << 8) | d->buf[d->pos + i];
307bool pc_ber_read_oid(BerDec *d, uint32_t *arcs,
size_t max,
size_t *n)
311 if (!pc_ber_read_header(d, &tag, &len) || tag != (uint8_t)SnmpTag::BER_OID || len == 0 || max < 2)
316 const uint8_t *p = d->buf + d->pos;
319 bool first_done =
false;
322 for (
size_t i = 0; i < len; i++)
324 acc = (acc << 7) | (uint32_t)(p[i] & 0x7F);
331 uint32_t arc0 = acc / 40u;
336 arcs[count++] = arc0;
337 arcs[count++] = acc - 40u * arc0;
356bool pc_ber_skip(BerDec *d,
size_t length)
358 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.