static int ipcomp4_init_state(struct xfrm_state *x) { int err = -EINVAL; x->props.header_len = 0; switch (x->props.mode) { case XFRM_MODE_TRANSPORT: break; case XFRM_MODE_TUNNEL: x->props.header_len += sizeof(struct iphdr); break; default: goto out; } err = ipcomp_init_state(x); if (err) goto out; if (x->props.mode == XFRM_MODE_TUNNEL) { err = ipcomp_tunnel_attach(x); if (err) goto out; } err = 0; out: return err; }
static int ipcomp_init_state(struct xfrm_state *x, void *args) { int err = -ENOMEM; struct ipcomp_data *ipcd; struct xfrm_algo_desc *calg_desc; ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL); if (!ipcd) goto error; memset(ipcd, 0, sizeof(*ipcd)); x->props.header_len = sizeof(struct ip_comp_hdr); if (x->props.mode) x->props.header_len += sizeof(struct iphdr); ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL); if (!ipcd->scratch) goto error; ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0); if (!ipcd->tfm) goto error; if (x->props.mode) { err = ipcomp_tunnel_attach(x); if (err) goto error; } calg_desc = xfrm_calg_get_byname(x->calg->alg_name); BUG_ON(!calg_desc); ipcd->threshold = calg_desc->uinfo.comp.threshold; x->data = ipcd; err = 0; out: return err; error: if (ipcd) { ipcomp_free_data(ipcd); kfree(ipcd); } goto out; }