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;
}
Esempio n. 2
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;
}