static ofl_err ofl_msg_unpack_flow_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { struct ofp_flow_mod *sm; struct ofl_msg_flow_mod *dm; struct ofp_instruction *inst; ofl_err error; size_t i; if (*len < (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match))) { OFL_LOG_WARN(LOG_MODULE, "Received FLOW_MOD message has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match)); sm = (struct ofp_flow_mod *)src; dm = (struct ofl_msg_flow_mod *)malloc(sizeof(struct ofl_msg_flow_mod)); dm->cookie = ntoh64(sm->cookie); dm->cookie_mask = ntoh64(sm->cookie_mask); dm->table_id = sm->table_id; dm->command = (enum ofp_flow_mod_command)sm->command; dm->idle_timeout = ntohs( sm->idle_timeout); dm->hard_timeout = ntohs( sm->hard_timeout); dm->priority = ntohs( sm->priority); dm->buffer_id = ntohl( sm->buffer_id); dm->out_port = ntohl( sm->out_port); dm->out_group = ntohl( sm->out_group); dm->flags = ntohs( sm->flags); error = ofl_structs_match_unpack(&(sm->match), len, &(dm->match), exp); if (error) { free(dm); return error; } error = ofl_utils_count_ofp_instructions(&(sm->instructions), *len, &dm->instructions_num); if (error) { ofl_structs_free_match(dm->match, exp); free(dm); return error; } dm->instructions = (struct ofl_instruction_header **)malloc(dm->instructions_num * sizeof(struct ofl_instruction_header *)); inst = sm->instructions; for (i = 0; i < dm->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, len, &(dm->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dm->instructions, i, ofl_structs_free_instruction, exp); ofl_structs_free_match(dm->match, exp); free(dm); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } *msg = (struct ofl_msg_header *)dm; 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; }
static ofl_err ofl_structs_table_properties_unpack(struct ofp_table_feature_prop_header * src, size_t *len, struct ofl_table_feature_prop_header **dst, struct ofl_exp *exp){ size_t plen; ofl_err error; struct ofl_table_feature_prop_header * prop = NULL; if (*len < sizeof(struct ofp_table_feature_prop_header)){ OFL_LOG_WARN(LOG_MODULE, "Received feature is too short (%zu).", *len); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } if (*len < ntohs(src->length)) { OFL_LOG_WARN(LOG_MODULE, "Received table property has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } plen = ntohs(src->length); switch(ntohs(src->type)){ case OFPTFPT_INSTRUCTIONS: case OFPTFPT_INSTRUCTIONS_MISS:{ struct ofp_table_feature_prop_instructions *sp = (struct ofp_table_feature_prop_instructions*) src; struct ofl_table_feature_prop_instructions *dp; size_t ilen,i; uint8_t *ptr; if (plen < sizeof(struct ofp_table_feature_prop_instructions)) { OFL_LOG_WARN(LOG_MODULE, "Received INSTRUCTION feature has invalid length (%zu).", *len); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } dp = (struct ofl_table_feature_prop_instructions*) malloc(sizeof(struct ofl_table_feature_prop_instructions)); ilen = plen - sizeof(struct ofp_table_feature_prop_instructions); error = ofl_utils_count_ofp_instructions((uint8_t*) sp->instruction_ids, ilen, &dp->ids_num); if(error){ free(dp); return error; } dp->instruction_ids = (struct ofl_instruction_header*) malloc(sizeof(struct ofl_instruction_header) * dp->ids_num); ptr = (uint8_t*) sp->instruction_ids; for(i = 0; i < dp->ids_num; i++){ dp->instruction_ids[i].type = ntohs(((struct ofp_instruction*) ptr)->type); ptr += ntohs(((struct ofp_instruction*) ptr)->len); } plen -= ntohs(sp->length); prop = (struct ofl_table_feature_prop_header*) dp; break; } case OFPTFPT_NEXT_TABLES: case OFPTFPT_NEXT_TABLES_MISS:{ struct ofp_table_feature_prop_next_tables *sp = (struct ofp_table_feature_prop_next_tables*) src; struct ofl_table_feature_prop_next_tables *dp; if (plen < sizeof(struct ofp_table_feature_prop_next_tables)) { OFL_LOG_WARN(LOG_MODULE, "Received NEXT TABLE feature has invalid length (%zu).", *len); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } dp = (struct ofl_table_feature_prop_next_tables*) malloc(sizeof(struct ofl_table_feature_prop_next_tables)); dp->table_num = ntohs(sp->length) - sizeof(struct ofp_table_feature_prop_next_tables); dp->next_table_ids = (uint8_t*) malloc(sizeof(uint8_t) * dp->table_num); memcpy(dp->next_table_ids, sp->next_table_ids, dp->table_num); plen -= ntohs(sp->length); prop = (struct ofl_table_feature_prop_header*) dp; break; } case OFPTFPT_WRITE_ACTIONS: case OFPTFPT_WRITE_ACTIONS_MISS: case OFPTFPT_APPLY_ACTIONS: case OFPTFPT_APPLY_ACTIONS_MISS:{ struct ofp_table_feature_prop_actions *sp = (struct ofp_table_feature_prop_actions*) src; struct ofl_table_feature_prop_actions *dp; size_t alen, i; uint8_t *ptr; if (plen < sizeof(struct ofp_table_feature_prop_actions)) { OFL_LOG_WARN(LOG_MODULE, "Received ACTION feature has invalid length (%zu).", *len); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } alen = plen - sizeof(struct ofp_table_feature_prop_actions); dp = (struct ofl_table_feature_prop_actions*) malloc(sizeof(struct ofl_table_feature_prop_actions)); error = ofl_utils_count_ofp_actions((uint8_t*)sp->action_ids, alen, &dp->actions_num); if(error){ free(dp); return error; } dp->action_ids = (struct ofl_action_header*) malloc(sizeof(struct ofl_action_header) * dp->actions_num); ptr = (uint8_t*) sp->action_ids; for(i = 0; i < dp->actions_num; i++){ dp->action_ids[i].type = ntohs(((struct ofp_action_header*) ptr)->type); dp->action_ids[i].len = ntohs(((struct ofp_action_header*) ptr)->len); ptr += ntohs(((struct ofp_action_header*) ptr)->len); } plen -= ntohs(sp->length); prop = (struct ofl_table_feature_prop_header*) dp; break; } case OFPTFPT_MATCH: case OFPTFPT_WILDCARDS: case OFPTFPT_WRITE_SETFIELD: case OFPTFPT_WRITE_SETFIELD_MISS: case OFPTFPT_APPLY_SETFIELD: case OFPTFPT_APPLY_SETFIELD_MISS:{ struct ofp_table_feature_prop_oxm *sp = (struct ofp_table_feature_prop_oxm*) src; struct ofl_table_feature_prop_oxm *dp; size_t i; if (plen < sizeof(struct ofp_table_feature_prop_oxm)) { OFL_LOG_WARN(LOG_MODULE, "Received MATCH feature has invalid length (%zu).", *len); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } dp = (struct ofl_table_feature_prop_oxm*) malloc(sizeof(struct ofl_table_feature_prop_oxm)); dp->oxm_num = (ntohs(sp->length) - sizeof(struct ofp_table_feature_prop_oxm))/sizeof(uint32_t); dp->oxm_ids = (uint32_t*) malloc(sizeof(uint32_t) * dp->oxm_num); for(i = 0; i < dp->oxm_num; i++ ){ dp->oxm_ids[i] = ntohl(sp->oxm_ids[i]); } plen -= ntohs(sp->length); prop = (struct ofl_table_feature_prop_header*) dp; break; } } // must set type before check, so free works correctly prop->type = (enum ofp_table_feature_prop_type) ntohs(src->type); /* Make sure it can be reused for packing. Jean II */ prop->length = ntohs(src->length); if (plen != 0){ *len = *len - ntohs(src->length) + plen; OFL_LOG_WARN(LOG_MODULE, "The received property contained extra bytes (%zu).", plen); //ofl_structs_free_property(inst, exp); return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN); } *len -= ntohs(src->length); (*dst) = prop; return 0; }