ofl_err ofl_structs_table_stats_unpack(struct ofp_table_stats *src, size_t *len, struct ofl_table_stats **dst) { struct ofl_table_stats *p; if (*len < sizeof(struct ofp_table_stats)) { OFL_LOG_WARN(LOG_MODULE, "Received table stats has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } if (src->table_id == 0xff) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(src->table_id); OFL_LOG_WARN(LOG_MODULE, "Received table stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= sizeof(struct ofp_table_stats); p = (struct ofl_table_stats *)malloc(sizeof(struct ofl_table_stats)); p->table_id = src->table_id; p->active_count = ntohl(src->active_count); p->lookup_count = ntoh64(src->lookup_count); p->matched_count = ntoh64(src->matched_count); *dst = p; return 0; }
static ofl_err ofl_msg_unpack_flow_removed(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp, char *errbuf) { struct ofp_flow_removed *sr; struct ofl_msg_flow_removed *dr; ofl_err error; if (*len < (sizeof(struct ofp_flow_removed) - sizeof(struct ofp_match))) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received FLOW_REMOVED message has invalid length (%zu).", *len); } return OFL_ERROR; } sr = (struct ofp_flow_removed *)src; if (sr->table_id == 0xff) { if (errbuf != NULL) { char *ts = ofl_table_to_string(sr->table_id); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received FLOW_REMOVED message has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } *len -= (sizeof(struct ofp_flow_removed) - sizeof(struct ofp_match)); dr = (struct ofl_msg_flow_removed *)malloc(sizeof(struct ofl_msg_flow_removed)); dr->reason = (enum ofp_flow_removed_reason)sr->reason; dr->stats = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); dr->stats->table_id = sr->table_id; dr->stats->duration_sec = ntohl( sr->duration_sec); dr->stats->duration_nsec = ntohl( sr->duration_nsec); dr->stats->priority = ntoh64(sr->priority); dr->stats->idle_timeout = ntohs( sr->idle_timeout); dr->stats->hard_timeout = 0; dr->stats->cookie = ntoh64(sr->cookie); dr->stats->packet_count = ntoh64(sr->packet_count); dr->stats->byte_count = ntoh64(sr->byte_count); dr->stats->instructions_num = 0; dr->stats->instructions = NULL; error = ofl_structs_match_unpack(&(sr->match), len, &(dr->stats->match), exp, errbuf); if (error) { free(dr->stats); free(dr); return error; } *msg = (struct ofl_msg_header *)dr; return 0; }
static ofl_err ofl_msg_unpack_packet_in(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, char *errbuf) { struct ofp_packet_in *sp; struct ofl_msg_packet_in *dp; if (*len < sizeof(struct ofp_packet_in)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN message has invalid length (%zu).", *len); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } sp = (struct ofp_packet_in *)src; if (ntohl(sp->in_port) == 0 || (ntohl(sp->in_port) > OFPP_MAX && ntohl(sp->in_port) != OFPP_LOCAL)) { if (errbuf != NULL) { char *ps = ofl_port_to_string(ntohl(sp->in_port)); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN message has invalid in_port (%s).", ps); free(ps); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } if (sp->table_id == 0xff) { if (errbuf != NULL) { char *ts = ofl_table_to_string(sp->table_id); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } *len -= sizeof(struct ofp_packet_in); dp = (struct ofl_msg_packet_in *)malloc(sizeof(struct ofl_msg_packet_in)); dp->buffer_id = ntohl(sp->buffer_id); dp->in_port = ntohl(sp->in_port); dp->in_phy_port = ntohl(sp->in_phy_port); dp->total_len = ntohs(sp->total_len); dp->reason = (enum ofp_packet_in_reason)sp->reason; dp->table_id = sp->table_id; dp->data_length = *len; dp->data = *len > 0 ? (uint8_t *)memcpy(malloc(*len), sp->data, *len) : NULL; *len = 0; *msg = (struct ofl_msg_header *)dp; return 0; }
ofl_err ofl_structs_table_stats_unpack(struct ofp_table_stats *src, size_t *len, struct ofl_table_stats **dst, char *errbuf) { struct ofl_table_stats *p; if (*len < sizeof(struct ofp_table_stats)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received table stats has invalid length (%zu).", *len); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } if (src->table_id == 0xff) { if (errbuf != NULL) { char *ts = ofl_table_to_string(src->table_id); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received table stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= sizeof(struct ofp_table_stats); p = (struct ofl_table_stats *)malloc(sizeof(struct ofl_table_stats)); p->table_id = src->table_id; p->name = strcpy((char *)malloc(strlen(src->name) + 1), src->name); p->wildcards = ntohl(src->wildcards); p->match = ntohl(src->match); p->instructions = ntohl(src->instructions); p->write_actions = ntohl(src->write_actions); p->apply_actions = ntohl(src->apply_actions); p->config = ntohl(src->config); p->max_entries = ntohl(src->max_entries); p->active_count = ntohl(src->active_count); p->lookup_count = ntoh64(src->lookup_count); p->matched_count = ntoh64(src->matched_count); *dst = p; return 0; }
ofl_err ofl_structs_instructions_unpack(struct ofp_instruction *src, size_t *len, struct ofl_instruction_header **dst, struct ofl_exp *exp) { size_t ilen; struct ofl_instruction_header *inst = NULL; if (*len < sizeof(struct ofp_instruction)) { OFL_LOG_WARN(LOG_MODULE, "Received instruction is too short (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if (*len < ntohs(src->len)) { OFL_LOG_WARN(LOG_MODULE, "Received instruction has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } ilen = ntohs(src->len); switch (ntohs(src->type)) { case OFPIT_GOTO_TABLE: { struct ofp_instruction_goto_table *si; struct ofl_instruction_goto_table *di; if (ilen < sizeof(struct ofp_instruction_goto_table)) { OFL_LOG_WARN(LOG_MODULE, "Received GOTO_TABLE instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_goto_table *)src; if (si->table_id >= PIPELINE_TABLES) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(si->table_id); OFL_LOG_WARN(LOG_MODULE, "Received GOTO_TABLE instruction has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_BAD_TABLE_ID); } di = (struct ofl_instruction_goto_table *)malloc(sizeof(struct ofl_instruction_goto_table)); di->table_id = si->table_id; inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_goto_table); break; } case OFPIT_WRITE_METADATA: { struct ofp_instruction_write_metadata *si; struct ofl_instruction_write_metadata *di; if (ilen < sizeof(struct ofp_instruction_write_metadata)) { OFL_LOG_WARN(LOG_MODULE, "Received WRITE_METADATA instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_write_metadata *)src; di = (struct ofl_instruction_write_metadata *)malloc(sizeof(struct ofl_instruction_write_metadata)); di->metadata = ntoh64(si->metadata); di->metadata_mask = ntoh64(si->metadata_mask); inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_write_metadata); break; } case OFPIT_WRITE_ACTIONS: case OFPIT_APPLY_ACTIONS: { struct ofp_instruction_actions *si; struct ofl_instruction_actions *di; struct ofp_action_header *act; ofl_err error; size_t i; if (ilen < sizeof(struct ofp_instruction_actions)) { OFL_LOG_WARN(LOG_MODULE, "Received *_ACTIONS instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } ilen -= sizeof(struct ofp_instruction_actions); si = (struct ofp_instruction_actions *)src; di = (struct ofl_instruction_actions *)malloc(sizeof(struct ofl_instruction_actions)); error = ofl_utils_count_ofp_actions((uint8_t *)si->actions, ilen, &di->actions_num); if (error) { free(di); return error; } di->actions = (struct ofl_action_header **)malloc(di->actions_num * sizeof(struct ofl_action_header *)); act = si->actions; for (i = 0; i < di->actions_num; i++) { error = ofl_actions_unpack(act, &ilen, &(di->actions[i]), exp); if (error) { *len = *len - ntohs(src->len) + ilen; OFL_UTILS_FREE_ARR_FUN2(di->actions, i, ofl_actions_free, exp); free(di); return error; } act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len)); } inst = (struct ofl_instruction_header *)di; break; } case OFPIT_CLEAR_ACTIONS: { if (ilen < sizeof(struct ofp_instruction_actions)) { OFL_LOG_WARN(LOG_MODULE, "Received CLEAR_ACTIONS instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } inst = (struct ofl_instruction_header *)malloc(sizeof(struct ofl_instruction_header)); inst->type = (enum ofp_instruction_type)ntohs(src->type); ilen -= sizeof(struct ofp_instruction_actions); break; } case OFPIT_METER: { struct ofp_instruction_meter *si; struct ofl_instruction_meter *di; if (ilen < sizeof(struct ofp_instruction_meter)) { OFL_LOG_WARN(LOG_MODULE, "Received METER instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_meter*)src; di = (struct ofl_instruction_meter *)malloc(sizeof(struct ofl_instruction_meter)); di->meter_id = ntohl(si->meter_id); inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_meter); break; } case OFPIT_EXPERIMENTER: { ofl_err error; if (exp == NULL || exp->inst == NULL || exp->inst->unpack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER instruction, but no callback was given."); return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_UNSUP_INST); } error = exp->inst->unpack(src, &ilen, &inst); if (error) { return error; } break; } default: OFL_LOG_WARN(LOG_MODULE, "The received instruction type (%u) is invalid.", ntohs(src->type)); return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_UNKNOWN_INST); } // must set type before check, so free works correctly inst->type = (enum ofp_instruction_type)ntohs(src->type); if (ilen != 0) { *len = *len - ntohs(src->len) + ilen; OFL_LOG_WARN(LOG_MODULE, "The received instruction contained extra bytes (%zu).", ilen); ofl_structs_free_instruction(inst, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->len); (*dst) = inst; return 0; }
ofl_err ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp, char *errbuf) { struct ofl_flow_stats *s; struct ofp_instruction *inst; ofl_err error; size_t slen; size_t i; if (*len < (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match))) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid length (%zu).", *len); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (src->table_id == 0xff) { if (errbuf != NULL) { char *ts = ofl_table_to_string(src->table_id); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } slen = ntohs(src->length) - (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)); s = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); s->table_id = src->table_id; s->duration_sec = ntohl( src->duration_sec); s->duration_nsec = ntohl( src->duration_nsec); s->priority = ntohs( src->priority); s->idle_timeout = ntohs( src->idle_timeout); s->hard_timeout = ntohs( src->hard_timeout); s->cookie = ntoh64(src->cookie); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); error = ofl_structs_match_unpack(&(src->match), &slen, &(s->match), exp, errbuf); if (error) { free(s); return error; } error = ofl_utils_count_ofp_instructions(src->instructions, slen, &s->instructions_num, errbuf); if (error) { ofl_structs_free_match(s->match, exp, NULL); free(s); return error; } s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *)); inst = src->instructions; for (i = 0; i < s->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp, errbuf); if (error) { OFL_UTILS_FREE_ARR_FUN3(s->instructions, i, ofl_structs_free_instruction, exp, errbuf); free(s); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "The received flow stats contained extra bytes (%zu).", slen); } ofl_structs_free_flow_stats(s, exp, errbuf); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
ofl_err ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, uint8_t *buf, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp) { struct ofl_flow_stats *s; struct ofp_instruction *inst; ofl_err error; size_t slen; size_t i; int match_pos; if (*len < ( (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)) + ROUND_UP(ntohs(src->match.length),8))) { OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { OFL_LOG_WARN(LOG_MODULE, "Received flow stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (src->table_id >= PIPELINE_TABLES) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(src->table_id); OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_TABLE_ID); } slen = ntohs(src->length) - (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)); s = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); s->table_id = src->table_id; s->duration_sec = ntohl( src->duration_sec); s->duration_nsec = ntohl( src->duration_nsec); s->priority = ntohs( src->priority); s->idle_timeout = ntohs( src->idle_timeout); s->hard_timeout = ntohs( src->hard_timeout); s->cookie = ntoh64(src->cookie); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); match_pos = sizeof(struct ofp_flow_stats) - 4; error = ofl_structs_match_unpack(&(src->match),buf + match_pos , &slen, &(s->match), exp); if (error) { free(s); return error; } error = ofl_utils_count_ofp_instructions((struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)), slen, &s->instructions_num); if (error) { ofl_structs_free_match(s->match, exp); free(s); return error; } s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *)); inst = (struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)); for (i = 0; i < s->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(s->instructions, i, ofl_structs_free_instruction, exp); free(s); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; OFL_LOG_WARN(LOG_MODULE, "The received flow stats contained extra bytes (%zu).", slen); ofl_structs_free_flow_stats(s, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }