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;
}
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;
}
Esempio n. 3
0
ofl_err
ofl_structs_bucket_unpack(struct ofp_bucket *src, size_t *len, uint8_t gtype, struct ofl_bucket **dst, struct ofl_exp *exp, char *errbuf) {
    struct ofl_bucket *b;
    struct ofp_action_header *act;
    size_t blen;
    ofl_err error;
    size_t i;

    if (*len < sizeof(struct ofp_bucket)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket is too short (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    if (*len < ntohs(src->len)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    blen = ntohs(src->len) - sizeof(struct ofp_bucket);

    if (gtype == OFPGT_SELECT && ntohs(src->weight) == 0) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket has no weight for SELECT group.");
        }
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP);
    }

    if (gtype != OFPGT_SELECT && ntohs(src->weight) > 0) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket has weight for non-SELECT group.");
        }
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP);
    }

    b = (struct ofl_bucket *)malloc(sizeof(struct ofl_bucket));

    b->weight =      ntohs(src->weight);
    b->watch_port =  ntohl(src->watch_port);
    b->watch_group = ntohl(src->watch_group);

    error = ofl_utils_count_ofp_actions((uint8_t *)src->actions, blen, &b->actions_num, errbuf);
    if (error) {
        free(b);
        return error;
    }
    b->actions = (struct ofl_action_header **)malloc(b->actions_num * sizeof(struct ofl_action_header *));

    act = src->actions;
    for (i = 0; i < b->actions_num; i++) {
        error = ofl_actions_unpack(act, &blen, &(b->actions[i]), exp, errbuf);
        if (error) {
            *len = *len - ntohs(src->len) + blen;
            OFL_UTILS_FREE_ARR_FUN3(b->actions, i,
                                    ofl_actions_free, exp, errbuf);
            //TODO error
            free(b);
            return error;
        }
        act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len));
    }

    if (blen >= 8) {
        *len = *len - ntohs(src->len) + blen;
        ofl_structs_free_bucket(b, exp, errbuf);
        //TODO error
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket has more than 64 bit padding (%zu).", blen);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }
    *len -= ntohs(src->len);

    *dst = b;
    return 0;
}
Esempio n. 4
0
static ofl_err
ofl_msg_unpack_packet_out(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp, char *errbuf) {
    struct ofp_packet_out *sp;
    struct ofl_msg_packet_out *dp;
    struct ofp_action_header *act;
    uint8_t *data;
    ofl_err error;
    size_t i, actions_num;

    if (*len < sizeof(struct ofp_packet_out)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_OUT message has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }

    sp = (struct ofp_packet_out *)src;

    if (ntohl(sp->in_port) == 0 ||
        (ntohl(sp->in_port) > OFPP_MAX && ntohl(sp->in_port) != OFPP_CONTROLLER)) {
        if (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(sp->in_port));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_OUT message with invalid in_port (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
    }

    if (ntohl(sp->buffer_id) != 0xffffffff &&
        *len != sizeof(struct ofp_packet_out) + ntohs(sp->actions_len)) {
        if (errbuf != NULL) {
            char *bs = ofl_buffer_to_string(ntohl(sp->buffer_id));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_OUT message with data and buffer_id (%s).", bs);
            free(bs);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_packet_out);

    dp = (struct ofl_msg_packet_out *)malloc(sizeof(struct ofl_msg_packet_out));

    dp->buffer_id = ntohl(sp->buffer_id);
    dp->in_port = ntohl(sp->in_port);

    if (*len < ntohs(sp->actions_len)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_OUT message has invalid action length (%zu).", *len);
        }
        free(dp);
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }

    error = ofl_utils_count_ofp_actions(&(sp->actions), ntohs(sp->actions_len), &actions_num, errbuf);
    if (error) {
        free(dp);
        return error;
    }
    dp->actions_num = actions_num;
    dp->actions = (struct ofl_action_header **)malloc(dp->actions_num * sizeof(struct ofp_action_header *));

    // TODO Zoltan: Output actions can contain OFPP_TABLE
    act = sp->actions;
    for (i = 0; i < dp->actions_num; i++) {
        error = ofl_actions_unpack(act, len, &(dp->actions[i]), exp, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(dp->actions, i,
                                    ofl_actions_free, exp, errbuf);
            free(dp);
        }
        act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len));
    }

    data = ((uint8_t *)sp->actions) + ntohs(sp->actions_len);
    dp->data_length = *len;
    dp->data = *len > 0 ? (uint8_t *)memcpy(malloc(*len), data, *len) : NULL;
    *len = 0;

    *msg = (struct ofl_msg_header *)dp;
    return 0;
}