/* Parse PDU header */ static AGENTX_ERR_CODE_E pdu_hdr_parse(struct agentx_datagram *xdg, uint8_t **buffer) { AGENTX_ERR_CODE_E err; uint8_t *buf; err = AGENTX_ERR_OK; buf = *buffer; /* PDU header */ xdg->pdu_hdr.version = *buf++; xdg->pdu_hdr.type = *buf++; xdg->pdu_hdr.flags = *buf++; xdg->pdu_hdr.reserved = *buf++; if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->pdu_hdr.session_id = NTOH32(*(uint32_t *)buf); buf += sizeof(uint32_t); xdg->pdu_hdr.transaction_id = NTOH32(*(uint32_t *)buf); buf += sizeof(uint32_t); xdg->pdu_hdr.packet_id = NTOH32(*(uint32_t *)buf); buf += sizeof(uint32_t); xdg->pdu_hdr.payload_length = NTOH32(*(uint32_t *)buf); buf += sizeof(uint32_t); } else { xdg->pdu_hdr.session_id = *(uint32_t *)buf; buf += sizeof(uint32_t); xdg->pdu_hdr.transaction_id = *(uint32_t *)buf; buf += sizeof(uint32_t); xdg->pdu_hdr.packet_id = *(uint32_t *)buf; buf += sizeof(uint32_t); xdg->pdu_hdr.payload_length = *(uint32_t *)buf; buf += sizeof(uint32_t); } /* Optinal context */ if (xdg->pdu_hdr.flags & NON_DEFAULT_CONTEXT) { if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->ctx_len = NTOH32(*(uint32_t *)buf); } else { xdg->ctx_len = *(uint32_t *)buf; } if (xdg->ctx_len + 1 > sizeof(xdg->context)) { err = AGENTX_ERR_PDU_CTX_LEN; *buffer = buf; return err; } buf += sizeof(uint32_t); memcpy(xdg->context, buf, xdg->ctx_len); buf += uint_sizeof(xdg->ctx_len); xdg->pdu_hdr.payload_length -= 4 + uint_sizeof(xdg->ctx_len); } /* additional data */ switch (xdg->pdu_hdr.type) { case AGENTX_PDU_CLOSE: xdg->u.close.reason = *buf; buf += sizeof(uint32_t); xdg->pdu_hdr.payload_length -= sizeof(uint32_t); break; case AGENTX_PDU_GETBULK: if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->u.getbulk.non_rep = NTOH16(*(uint16_t *)buf); } else { xdg->u.getbulk.non_rep = *(uint16_t *)buf; } buf += sizeof(uint16_t); if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->u.getbulk.max_rep = NTOH16(*(uint16_t *)buf); } else { xdg->u.getbulk.max_rep = *(uint16_t *)buf; } buf += sizeof(uint16_t); xdg->pdu_hdr.payload_length -= 2 * sizeof(uint16_t); break; case AGENTX_PDU_RESPONSE: if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->u.response.sys_up_time = NTOH32(*(uint32_t *)buf); } else { xdg->u.response.sys_up_time = *(uint32_t *)buf; } buf += sizeof(uint32_t); if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->u.response.error = NTOH16(*(uint16_t *)buf); } else { xdg->u.response.error = *(uint16_t *)buf; } buf += sizeof(uint16_t); xdg->u.response.index = *(uint16_t *)buf; if (xdg->pdu_hdr.flags & NETWORD_BYTE_ORDER) { xdg->u.response.index = NTOH16(*(uint16_t *)buf); } else { xdg->u.response.index = *(uint16_t *)buf; } buf += sizeof(uint16_t); xdg->pdu_hdr.payload_length -= sizeof(uint32_t) + 2 * sizeof(uint16_t); default: break; } *buffer = buf; return err; }
/* Input: buffer, flag, value type; * Output: value pointer * Return: number of elements */ uint32_t agentx_value_dec(uint8_t **buffer, uint8_t flag, uint8_t type, void *value) { uint8_t *buf; uint32_t i, ret; uint32_t *oid_src, *oid_dest; uint32_t *inter_src, *inter_dest; uint64_t *long_src, *long_dest; buf = *buffer; switch (type) { case ASN1_TAG_INT: case ASN1_TAG_CNT: case ASN1_TAG_GAU: case ASN1_TAG_TIMETICKS: inter_src = (uint32_t *)buf; inter_dest = (uint32_t *)value; *inter_dest = *inter_src; buf += sizeof(uint32_t); ret = 1; break; case ASN1_TAG_CNT64: long_src = (uint64_t *)buf; long_dest = (uint64_t *)value; *long_dest = *long_src; buf += sizeof(uint64_t); ret = 1; break; case ASN1_TAG_OCTSTR: case ASN1_TAG_IPADDR: ret = *(uint32_t *)buf; buf += 4; memcpy(value, buf, ret); buf += uint_sizeof(ret); break; case ASN1_TAG_OBJID: ret = *buf++; uint8_t prefix = *buf++; buf += 2; if (ret == 0 && prefix == 0) { break; } ret += 5; oid_src = (uint32_t *)buf; oid_dest = (uint32_t *)value; oid_dest[0] = 1; oid_dest[1] = 3; oid_dest[2] = 6; oid_dest[3] = 1; oid_dest[4] = prefix; for (i = 5; i < ret; i++) { oid_dest[i] = oid_src[i - 5]; buf += sizeof(uint32_t); } break; default: ret = 0; break; } *buffer = buf; return ret; }