Пример #1
0
static struct pdu * pdu_deserialize_gfp(gfp_t                 flags,
                                        const struct serdes * instance,
                                        struct pdu_ser *      pdu)
{
        struct pdu *          new_pdu;
        struct dt_cons *      dt_cons;
        const struct buffer * tmp_buff;
        struct buffer *       new_buff;
        struct pci *          new_pci;
        const uint8_t *       ptr;
        int                   offset;
        ssize_t               pdu_len;
        seq_num_t             seq;

        if (!pdu_ser_is_ok(pdu))
                return NULL;

        if (!instance)
                return NULL;

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        tmp_buff = pdu_ser_buffer(pdu);
        ASSERT(tmp_buff);

        if (buffer_length(tmp_buff) < base_pci_size(dt_cons))
                return NULL;

        ptr = (const uint8_t *) buffer_data_ro(tmp_buff);
        ASSERT(ptr);

        new_pdu = pdu_create_gfp(flags);
        if (!new_pdu) {
                LOG_ERR("Failed to create new pdu");
                return NULL;
        }

        new_pci = pci_create_gfp(flags);
        if (!new_pci) {
                LOG_ERR("Failed to create new pci");
                pdu_destroy(new_pdu);
                return NULL;
        }

        pdu_len = 0;
        if (deserialize_base_pci(instance, new_pci, &offset, ptr, &pdu_len)) {
                LOG_ERR("Could not deser base PCI");
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        switch (pci_type(new_pci)) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                /* Create buffer with rest of PDU if it is a DT or MGMT PDU*/
                memcpy(&seq,
                       ptr + offset,
                       dt_cons->seq_num_length);
                offset += dt_cons->seq_num_length;
                if (pci_sequence_number_set(new_pci, seq)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_from_gfp(flags,
                                                  ptr + offset,
                                                  pdu_len - offset);
                if (!new_buff) {
                        LOG_ERR("Could not create new_buff");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                /*
                 * FIXME: It would be better if a PDU consisted of
                 * Base PCI + Data | Control PDU stuff
                 * e.g.
                 * struct pdu {
                 *    struct pci base_pci;
                 *    union {
                 *       struct buffer * data;
                 *       struct pci_ctrl * ctrl;
                 *     }
                 * }
                 */
                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_CC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_cc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pci_type(new_pci));
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_pci_set(new_pdu, new_pci)) {
                LOG_ERR("Failed to set PCI in PDU");
                buffer_destroy(new_buff);
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_buffer_set(new_pdu, new_buff)) {
                LOG_ERR("Failed to set buffer in PDU");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ASSERT(pdu_is_ok(new_pdu));

        pdu_ser_destroy(pdu);

        return new_pdu;
}
Пример #2
0
static struct pdu * pdu_deserialize_gfp(gfp_t                 flags,
                                        const struct serdes * instance,
                                        struct pdu_ser *      pdu,
                                        struct dup_config_entry * dup_conf,
                                        struct crypto_blkcipher * blkcipher)
{
        struct pdu *          new_pdu;
        struct dt_cons *      dt_cons;
        struct buffer *       tmp_buff;
        struct buffer *       new_buff;
        struct pci *          new_pci;
        const uint8_t *       ptr;
        int                   offset;
        ssize_t               pdu_len;
        seq_num_t             seq;
        ssize_t               ttl;
        uint8_t               pad_len;
        const char *          data;

        if (!instance)
                return NULL;

        if (!pdu_ser_is_ok(pdu))
                return NULL;

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->error_check_policy != NULL){
            if (!dup_chksum_is_ok(pdu)) {
                    LOG_ERR("Bad CRC, PDU has been corrupted");
                    return NULL;
            }

            /* Assuming CRC32 */
            if (pdu_ser_head_shrink_gfp(flags, pdu, sizeof(u32))) {
                    LOG_ERR("Failed to shrink ser PDU");
                    return NULL;
            }
        }

        /* FIXME: this should be moved to specific policy code */
        if (blkcipher != NULL && dup_conf != NULL &&
        		dup_conf->enable_decryption){
        	if (!dup_decrypt_data(pdu, blkcipher)) {
        		LOG_ERR("Failed to decrypt PDU");
        		return NULL;
        	}

                tmp_buff = pdu_ser_buffer(pdu);
                data = buffer_data_ro(tmp_buff);
                pad_len = data[buffer_length(tmp_buff)-1];

                //remove padding
                if (pdu_ser_tail_shrink_gfp(pdu, pad_len)){
                        LOG_ERR("Failed to shrink ser PDU");
                        return NULL;
                }
        }

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        tmp_buff = pdu_ser_buffer(pdu);
        ASSERT(tmp_buff);

        if (buffer_length(tmp_buff) < base_pci_size(dt_cons))
                return NULL;

        new_pdu = pdu_create_gfp(flags);
        if (!new_pdu) {
                LOG_ERR("Failed to create new pdu");
                return NULL;
        }

        new_pci = pci_create_gfp(flags);
        if (!new_pci) {
                LOG_ERR("Failed to create new pci");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ttl = 0;

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->ttl_policy != NULL){
                ttl = dup_ttl_decrement(pdu);
                if (ttl < 0) {
                        LOG_ERR("Could not decrement TTL");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                if (pci_ttl_set(new_pci, ttl)) {
                        LOG_ERR("Could not set TTL");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                if (pdu_ser_head_shrink_gfp(flags, pdu, sizeof(u8))) {
                        LOG_ERR("Failed to shrink ser PDU");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
        }

        ptr = (const uint8_t *) buffer_data_ro(tmp_buff);
        ASSERT(ptr);

        pdu_len = 0;
        if (deserialize_base_pci(instance, new_pci, &offset, ptr, &pdu_len)) {
                LOG_ERR("Could not deser base PCI");
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        switch (pci_type(new_pci)) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                /* Create buffer with rest of PDU if it is a DT or MGMT PDU*/
                memcpy(&seq,
                       ptr + offset,
                       dt_cons->seq_num_length);
                offset += dt_cons->seq_num_length;
                if (pci_sequence_number_set(new_pci, seq)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_from_gfp(flags,
                                                  ptr + offset,
                                                  pdu_len - offset);

                if (!new_buff) {
                        LOG_ERR("Could not create new_buff");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                /*
                 * FIXME: It would be better if a PDU consisted of
                 * Base PCI + Data | Control PDU stuff
                 * e.g.
                 * struct pdu {
                 *    struct pci base_pci;
                 *    union {
                 *       struct buffer * data;
                 *       struct pci_ctrl * ctrl;
                 *     }
                 * }
                 */
                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_CACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_cc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pci_type(new_pci));
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_pci_set(new_pdu, new_pci)) {
                LOG_ERR("Failed to set PCI in PDU");
                buffer_destroy(new_buff);
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_buffer_set(new_pdu, new_buff)) {
                LOG_ERR("Failed to set buffer in PDU");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ASSERT(pdu_is_ok(new_pdu));

        pdu_ser_destroy(pdu);

        return new_pdu;
}