struct net_device * ipsec_mast_get_device(int vifnum) { int ovifnum = vifnum; if(vifnum > IPSECDEV_OFFSET) { return ipsec_tunnel_get_device(vifnum-IPSECDEV_OFFSET); } else { struct net_device *nd; if(vifnum >= MASTTRANSPORT_OFFSET) { vifnum -= MASTTRANSPORT_OFFSET; } if(vifnum <= mastdevices_max) { nd = mastdevices[vifnum]; if(nd) ipsec_dev_hold(nd); return nd; } else { KLIPS_ERROR(debug_tunnel, "no such vif %d (ovif=%d)\n", vifnum, ovifnum); return NULL; } } }
/* * main encrypt service entry point * called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and * ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT */ int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, __u8 * iv, int encrypt) { int ret; struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; int debug_flag = (encrypt==IPSEC_ALG_ENCRYPT ? debug_tunnel : debug_rcv); KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "entering with encalg=%d, ixt_e=%p\n", sa_p->ips_encalg, ixt_e); if (ixt_e == NULL) { KLIPS_ERROR(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "NULL ipsec_alg_enc object\n"); return -1; } KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "calling cbc_encrypt encalg=%d " "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n", sa_p->ips_encalg, sa_p->ips_key_e, idat, ilen, iv, encrypt); ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt); KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "returned ret=%d\n", ret); return ret; }
static IPsecSAref_t ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ { IPsecSAref_t SAref; KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", ipsec_sadb.refFreeListHead, ipsec_sadb.refFreeListCont, ipsec_sadb.refFreeListTail, IPSEC_SA_REF_FREELIST_NUM_ENTRIES); if(ipsec_sadb.refFreeListHead == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "FreeList empty, recycling...\n"); *error = ipsec_SAref_recycle(); if(*error) { return IPSEC_SAREF_NULL; } } SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; if(SAref == IPSEC_SAREF_NULL) { KLIPS_ERROR(debug_xform, "ipsec_SAref_alloc: " "unexpected error, refFreeListHead = %d points to invalid entry.\n", ipsec_sadb.refFreeListHead); *error = -ESPIPE; return IPSEC_SAREF_NULL; } KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "allocating SAref=%d, table=%u, entry=%u of %u.\n", SAref, IPsecSAref2table(SAref), IPsecSAref2entry(SAref), IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListHead++; if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "last FreeList entry allocated, resetting list head to empty.\n"); ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; } return SAref; }
int pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) { int error = 0; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: .\n"); if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } if(extr->ips2 == NULL) { extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ } if(extr->ips2 == NULL) { SENDERR(-error); } if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { KLIPS_ERROR(debug_pfkey, "pfkey_x_satype_process: " "proto lookup from satype=%d failed.\n", pfkey_x_satype->sadb_x_satype_satype); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: " "protocol==%d decoded from satype==%d(%s).\n", extr->ips2->ips_said.proto, pfkey_x_satype->sadb_x_satype_satype, satype2name(pfkey_x_satype->sadb_x_satype_satype)); errlab: return error; }
/* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ int ipsec_mast_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipsec_xmit_state *ixs; IPsecSAref_t SAref; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: skb=%p\n", skb); if(skb == NULL) { printk("ipsec_mast_start_xmit: " "passed NULL\n"); return 0; } ixs = ipsec_xmit_state_new(dev); if(ixs == NULL) return NETDEV_TX_BUSY; ixs->dev = dev; ixs->skb = skb; SAref = 0; #ifdef NETDEV_25 #if defined(CONFIG_NETFILTER) if(skb->nfmark & IPSEC_NFMARK_IS_SAREF_BIT) { SAref = NFmark2IPsecSAref(skb->nfmark); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "getting SAref=%d from nfmark\n", SAref); } #endif #endif #ifdef CONFIG_INET_IPSEC_SAREF if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { SAref = skb->sp->ref; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "getting SAref=%d from sec_path\n", SAref); } #endif if (ipsec_xmit_sanity_check_skb(ixs) != IPSEC_XMIT_OK) { ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } ixs->ipsp = ipsec_sa_getbyref(SAref, IPSEC_REFOTHER); if(ixs->ipsp == NULL) { KLIPS_ERROR(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "%s: no SA for saref=%d\n", dev->name, SAref); ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } /* make sure this packet can go out on this SA */ if (ipsec_mast_check_outbound_policy(ixs)) { ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } /* fill in outgoing_said using the ipsp we have */ ixs->outgoing_said = ixs->ipsp->ips_said; #ifdef NETDEV_25 #if defined(CONFIG_NETFILTER) /* prevent recursion through the saref route */ if(skb->nfmark & 0x80000000) { skb->nfmark = 0; } #endif #endif #if 0 /* TODO: do we have to also have to do this? */ if(skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { secpath_put(skb->sp); skb->sp = NULL; } #endif /* * we should be calculating the MTU by looking up a route * based upon the destination in the SA, and then cache * it into the SA, but we don't do that right now. */ ixs->cur_mtu = 1460; ixs->physmtu = 1460; ixs->mast_mode = 1; ixs->xsm_complete = ipsec_mast_xsm_complete; ixs->state = IPSEC_XSM_INIT2; /* we start later in the process */ ixs->prv = netdev_priv(ixs->dev); ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats); ipsec_xsm(ixs); return 0; }
/* * The ipsec_sa table better be locked before it is handed in, * or races might happen. * * this routine assumes the SA has a refcount==0, and we free it. * we also assume that the pointers are already cleaned up. */ static int ipsec_sa_del(struct ipsec_sa *ips) { unsigned int hashval; struct ipsec_sa *ipstp; char sa[SATOT_BUF]; size_t sa_len; if (ips == NULL) { KLIPS_ERROR(debug_xform, "klips_error:ipsec_sa_del: " "null pointer passed in!\n"); return -ENODATA; } if (ips->ips_next) { struct ipsec_sa *in = ips->ips_next; ips->ips_next = NULL; ipsec_sa_put(in); } sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); hashval = IPS_HASH(&ips->ips_said); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "deleting SA:%s (ref=%u), hashval=%d.\n", sa_len ? sa : " (error)", ips->ips_ref, hashval); if (ipsec_sadb_hash[hashval] == NULL) { /* if this is NULL, then we can be sure that the SA was never * added to the SADB, so we just free it. */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in ipsec_sa table for hash=%d (ref=%u) of SA:%s.\n", hashval, ips->ips_ref, sa_len ? sa : " (error)"); return -ENOENT; } if (ips == ipsec_sadb_hash[hashval]) { ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted first ipsec_sa in chain.\n"); return 0; } else { for (ipstp = ipsec_sadb_hash[hashval]; ipstp; ipstp = ipstp->ips_hnext) { if (ipstp->ips_hnext == ips) { ipstp->ips_hnext = ips->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted link in ipsec_sa chain.\n"); return 0; } } } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return -ENOENT; }
/* * encryption key context creation function * called from pfkey_v2_parser.c:pfkey_ips_init() */ int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { int ret = 0; int keyminbits, keymaxbits; caddr_t ekp = NULL; struct ipsec_alg_enc *ixt_e = (struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "entering with encalg=%d ixt_e=%p\n", sa_p->ips_encalg, ixt_e); if (!ixt_e) { KLIPS_ERROR(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "NULL ipsec_alg_enc object\n"); return -EPROTO; } /* * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo */ switch(ixt_e->ixt_common.ixt_support.ias_id) { case ESP_3DES: keyminbits=keymaxbits=192;break; case ESP_DES: keyminbits=keymaxbits=64;break; default: keyminbits=ixt_e->ixt_common.ixt_support.ias_keyminbits; keymaxbits=ixt_e->ixt_common.ixt_support.ias_keymaxbits; } if (sa_p->ips_key_bits_e<keyminbits || sa_p->ips_key_bits_e>keymaxbits) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "incorrect encryption key size for id=%d: %d bits -- " "must be between %d,%d bits\n" /*octets (bytes)\n"*/, ixt_e->ixt_common.ixt_support.ias_id, sa_p->ips_key_bits_e, keyminbits, keymaxbits); ret=-EINVAL; goto ixt_out; } if (ixt_e->ixt_e_new_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_new_key to generate key\n"); if ((ekp = ixt_e->ixt_e_new_key(ixt_e, sa_p->ips_key_e, sa_p->ips_key_bits_e/8)) == NULL) { ret = -EINVAL; goto ixt_out; } } else if (ixt_e->ixt_e_set_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_set_key to generate key context\n"); if ((ekp = (caddr_t)kmalloc(ixt_e->ixt_e_ctx_size, GFP_ATOMIC)) == NULL) { ret = -ENOMEM; goto ixt_out; } /* zero-out key_e */ memset(ekp, 0, ixt_e->ixt_e_ctx_size); /* I cast here to allow more decoupling in alg module */ KLIPS_PRINT(debug_pfkey, "set_key(key_ctx=%p, key=%p, key_size=%d)\n", ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e/8); ret = ixt_e->ixt_e_set_key(ixt_e, ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e/8); if (ret < 0) { kfree(ekp); goto ixt_out; } } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "no function available to generate a key!\n"); ret = -EPROTO; goto ixt_out; } if (sa_p->ips_key_e) { memset(sa_p->ips_key_e, 0, sa_p->ips_key_bits_e/8); kfree(sa_p->ips_key_e); } sa_p->ips_key_e = ekp; sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size; sa_p->ips_alg_enc = ixt_e; ixt_e = NULL; ixt_out: if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); return ret; }