struct pci * pci_create_from_gfp(gfp_t flags, const void * data) { struct pci * tmp; if (!data) return NULL; tmp = rkmalloc(sizeof(*tmp), flags); if (!tmp) return NULL; if (!memcpy(tmp, data, sizeof(*tmp))) { rkfree(tmp); return NULL; } if (!pci_is_ok(tmp)) { LOG_ERR("Cannot create PCI from bad data"); rkfree(tmp); return NULL; } return tmp; }
static inline void *_rt_shm_alloc(unsigned long name, int size, int suprt) { void *adr; // suprt = USE_GFP_ATOMIC; // to force some testing if (!(adr = rt_get_adr_cnt(name)) && size > 0 && suprt >= 0 && RT_SHM_OP_PERM()) { size = ((size - 1) & PAGE_MASK) + PAGE_SIZE; if ((adr = suprt ? rkmalloc(&size, SUPRT[suprt]) : rvmalloc(size))) { if (!rt_register(name, adr, suprt ? -size : size, 0)) { if (suprt) { rkfree(adr, size); } else { rvfree(adr, size); } return 0; } memset(ALIGN2PAGE(adr), 0, size); } } return ALIGN2PAGE(adr); }
char * get_zero_length_string(void) { char * buf; buf = rkmalloc(1, GFP_KERNEL); if (buf) buf[0] = '\0'; return buf; }
struct connection * connection_dup_from_user(const struct connection __user * conn) { struct connection * tmp; tmp = rkmalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) return NULL; if (copy_from_user(tmp, conn, sizeof(*tmp))) return NULL; return tmp; }
char * rkstrdup_gfp(const char * s, gfp_t flags) { size_t len; char * buf; if (!s) return NULL; len = strlen(s) + 1; buf = rkmalloc(len, flags); if (buf) memcpy(buf, s, len); return buf; }
struct dt_cons * dt_cons_dup_gfp(gfp_t flags, const struct dt_cons * dt_cons) { struct dt_cons * tmp; if (!dt_cons) return NULL; tmp = rkmalloc(sizeof(*tmp), flags); if (!tmp) return NULL; memcpy(tmp, dt_cons, sizeof(*tmp)); return tmp; }
struct pci * pci_dup_gfp(gfp_t flags, const struct pci * pci) { struct pci * tmp; if (!pci_is_ok(pci)) return NULL; tmp = rkmalloc(sizeof(*tmp), flags); if (!tmp) return NULL; if (!memcpy(tmp, pci, sizeof(*tmp))) { rkfree(tmp); return NULL; } ASSERT(pci_is_ok(tmp)); return tmp; }
static struct pdu * pdu_dup_gfp(gfp_t flags, const struct pdu * pdu) { struct pdu * tmp; if (!pdu_is_ok(pdu)) return NULL; tmp = rkmalloc(sizeof(*tmp), flags); if (!tmp) return NULL; tmp->pci = pci_dup_gfp(flags, pdu->pci); tmp->buffer = buffer_dup_gfp(flags, pdu->buffer); if (!pdu_is_ok(tmp)) { pdu_destroy(tmp); return NULL; } return tmp; }
static struct pdu_ser * pdu_serialize_gfp(gfp_t flags, const const struct serdes * instance, struct pdu * pdu) { struct pdu_ser * tmp; struct dt_cons * dt_cons; const void * buffer_data; const struct buffer * buffer; const struct pci * pci; size_t size; ssize_t buffer_size; ssize_t pci_size; char * data; pdu_type_t pdu_type; seq_num_t seq; struct buffer * buf; if (!pdu_is_ok(pdu)) return NULL; if (!instance) return NULL; dt_cons = instance->dt_cons; ASSERT(dt_cons); buffer = pdu_buffer_get_ro(pdu); if (!buffer) return NULL; buffer_data = buffer_data_ro(buffer); if (!buffer_data) return NULL; buffer_size = buffer_length(buffer); if (buffer_size <= 0) return NULL; pci = pdu_pci_get_ro(pdu); if (!pci) return NULL; pdu_type = pci_type(pci); if (!pdu_type_is_ok(pdu_type)) { LOG_ERR("Wrong PDU type"); return NULL; } /* Base PCI size, fields present in all PDUs */ pci_size = base_pci_size(dt_cons); /* * These are available in the stack at this point in time * Extend if necessary (e.g.) NACKs, SACKs, ... * Set size in first switch/case */ switch (pdu_type) { case PDU_TYPE_MGMT: case PDU_TYPE_DT: size = pci_size + dt_cons->seq_num_length + buffer_size; if (size <= 0) return NULL; break; case PDU_TYPE_FC: size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons); if (size <= 0) return NULL; break; case PDU_TYPE_ACK: size = pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length; if (size <= 0) return NULL; break; case PDU_TYPE_ACK_AND_FC: size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons) + dt_cons->seq_num_length; if (size <= 0) return NULL; break; case PDU_TYPE_CC: size = pci_size + 2 * CTRL_SEQ_NR + 4 * dt_cons->seq_num_length + RATE_LEN; if (size <= 0) return NULL; break; default: LOG_ERR("Unknown PDU type %02X", pdu_type); return NULL; } data = rkmalloc(size, flags); if (!data) return NULL; /* Needed for all PDUs */ if (serialize_base_pci(instance, data, pci, size)) { LOG_ERR("Failed to serialize base PCI"); rkfree(data); return NULL; } /* Do actual serializing in the second switch case */ switch (pdu_type) { case PDU_TYPE_MGMT: case PDU_TYPE_DT: seq = pci_sequence_number_get(pci); memcpy(data + pci_size, &seq, dt_cons->seq_num_length); memcpy(data + pci_size + dt_cons->seq_num_length, buffer_data, buffer_size); break; case PDU_TYPE_FC: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_fc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; case PDU_TYPE_ACK: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_ack_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; case PDU_TYPE_ACK_AND_FC: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_ack_pci(instance, data, pci, pci_size + CTRL_SEQ_NR) || serialize_fc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length)) { rkfree(data); return NULL; } break; case PDU_TYPE_CC: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_cc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; default: LOG_ERR("Unknown PDU type %02X", pdu_type); return NULL; } buf = buffer_create_with_gfp(flags, data, size); if (!buf) { rkfree(data); return NULL; } tmp = pdu_ser_create_buffer_with_gfp(flags, buf); if (!tmp) { rkfree(buf); return NULL; } pdu_destroy(pdu); return tmp; }
static struct pdu_ser * pdu_serialize_gfp(gfp_t flags, const const struct serdes * instance, struct pdu * pdu, struct dup_config_entry * dup_conf, struct crypto_blkcipher * blkcipher) { struct pdu_ser * tmp; struct dt_cons * dt_cons; const void * buffer_data; const struct buffer * buffer; const struct pci * pci; size_t size; ssize_t buffer_size; ssize_t blk_size; ssize_t encrypted_size; ssize_t pci_size; char * data; pdu_type_t pdu_type; seq_num_t seq; struct buffer * buf; int i; if (!pdu_is_ok(pdu)) return NULL; if (!instance) return NULL; dt_cons = instance->dt_cons; ASSERT(dt_cons); buffer = pdu_buffer_get_ro(pdu); if (!buffer) return NULL; buffer_data = buffer_data_ro(buffer); if (!buffer_data) return NULL; buffer_size = buffer_length(buffer); if (buffer_size <= 0) return NULL; pci = pdu_pci_get_ro(pdu); if (!pci) return NULL; pdu_type = pci_type(pci); if (!pdu_type_is_ok(pdu_type)) { LOG_ERR("Wrong PDU type"); return NULL; } /* Base PCI size, fields present in all PDUs */ pci_size = base_pci_size(dt_cons); /* * These are available in the stack at this point in time * Extend if necessary (e.g.) NACKs, SACKs, ... * Set size in first switch/case */ switch (pdu_type) { case PDU_TYPE_MGMT: case PDU_TYPE_DT: size = pci_size + dt_cons->seq_num_length + buffer_size; if (size <= 0) return NULL; break; case PDU_TYPE_FC: size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons); if (size <= 0) return NULL; break; case PDU_TYPE_ACK: size = pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length; if (size <= 0) return NULL; break; case PDU_TYPE_ACK_AND_FC: size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons) + dt_cons->seq_num_length; if (size <= 0) return NULL; break; case PDU_TYPE_CACK: size = pci_size + 2 * CTRL_SEQ_NR + 4 * dt_cons->seq_num_length + RATE_LEN; if (size <= 0) return NULL; break; default: LOG_ERR("Unknown PDU type %02X", pdu_type); return NULL; } data = rkmalloc(size, flags); if (!data) return NULL; /* Needed for all PDUs */ if (serialize_base_pci(instance, data, pci, size)) { LOG_ERR("Failed to serialize base PCI"); rkfree(data); return NULL; } /* Do actual serializing in the second switch case */ switch (pdu_type) { case PDU_TYPE_MGMT: case PDU_TYPE_DT: seq = pci_sequence_number_get(pci); memcpy(data + pci_size, &seq, dt_cons->seq_num_length); memcpy(data + pci_size + dt_cons->seq_num_length, buffer_data, buffer_size); break; case PDU_TYPE_FC: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_fc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; case PDU_TYPE_ACK: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_ack_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; case PDU_TYPE_ACK_AND_FC: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_ack_pci(instance, data, pci, pci_size + CTRL_SEQ_NR) || serialize_fc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length)) { rkfree(data); return NULL; } break; case PDU_TYPE_CACK: if (serialize_ctrl_seq(instance, data, pci, pci_size) || serialize_cc_pci(instance, data, pci, pci_size + CTRL_SEQ_NR)) { rkfree(data); return NULL; } break; default: LOG_ERR("Unknown PDU type %02X", pdu_type); return NULL; } buf = buffer_create_with_gfp(flags, data, size); if (!buf) { rkfree(data); return NULL; } tmp = pdu_ser_create_buffer_with_gfp(flags, buf); if (!tmp) { rkfree(buf); return NULL; } /* FIXME: this should be moved to specific policy code */ if (dup_conf != NULL && dup_conf->ttl_policy != NULL){ if (pdu_ser_head_grow_gfp(flags, tmp, sizeof(u8))) { LOG_ERR("Failed to grow ser PDU"); pdu_ser_destroy(tmp); return NULL; } if (!dup_ttl_set(tmp, pci_ttl(pci))) { LOG_ERR("Could not set TTL"); pdu_ser_destroy(tmp); return NULL; } if (dup_ttl_is_expired(tmp)) { LOG_DBG("TTL is expired, dropping PDU"); pdu_ser_destroy(tmp); return NULL; } } /* FIXME: this should be moved to specific policy code */ if (blkcipher != NULL && dup_conf != NULL && dup_conf->enable_encryption){ buf = pdu_ser_buffer(tmp); blk_size = crypto_blkcipher_blocksize(blkcipher); buffer_size = buffer_length(buf); encrypted_size = (buffer_size/blk_size + 1) * blk_size; if (pdu_ser_tail_grow_gfp(tmp, encrypted_size - buffer_size)){ LOG_ERR("Failed to grow ser PDU"); pdu_ser_destroy(tmp); return NULL; } /* PADDING */ data = buffer_data_rw(buf); for (i=encrypted_size-1; i>buffer_size; i--){ data[i] = encrypted_size - buffer_size; } /* Encrypt */ if (!dup_encrypt_data(tmp, blkcipher)) { LOG_ERR("Failed to encrypt PDU"); pdu_ser_destroy(tmp); return NULL; } } /* FIXME: this should be moved to specific policy code */ if (dup_conf != NULL && dup_conf->error_check_policy != NULL){ /* Assuming CRC32 */ if (pdu_ser_head_grow_gfp(flags, tmp, sizeof(u32))) { LOG_ERR("Failed to grow ser PDU"); pdu_ser_destroy(tmp); return NULL; } if (!dup_chksum_set(tmp)) { LOG_ERR("Failed to add CRC"); pdu_ser_destroy(tmp); return NULL; } ASSERT(dup_chksum_is_ok(tmp)); } return tmp; }