sa.c
来自「xen 3.2.2 源码」· C语言 代码 · 共 757 行 · 第 1/2 页
C
757 行
SAState * sa_table_lookup_spi(u32 spi, u32 protocol, u32 addr){ SAState *state = NULL; Hashcode h; SAIdent id = { .spi = spi, .protocol = protocol, .addr = addr }; TableArg arg = { .ptr = &id }; HTEntry *entry = NULL; h = sa_table_hash_spi(spi, protocol, addr); entry = HashTable_find_entry(sa_table, h, sa_table_spi_fn, arg); if(entry){ state = entry->value; SAState_incref(state); } return state;}/** Find an SA by unique id. * Increments the SA refcount on success. * * @param id id * @return SA or NULL */SAState * sa_table_lookup_id(u32 id){ Hashcode h; TableArg arg = { .ul = id }; HTEntry *entry = NULL; SAState *state = NULL; dprintf("> id=%u\n", id); h = sa_table_hash_id(id); entry = HashTable_find_entry(sa_table, h, sa_table_id_fn, arg); if(entry){ state = entry->value; SAState_incref(state); } dprintf("< state=%p\n", state); return state;}/** Replace an existing SA by another in the table. * The existing SA is not removed if the new one cannot be added. * * @param existing SA to replace * @param state new SA * @return 0 on success, error code otherwise */static int sa_table_replace(SAState *existing, SAState *state){ int err = 0; // Need check for in-use? dprintf(">\n"); if(existing->keying.state != SA_STATE_ACQUIRE){ err = -EINVAL; goto exit; } // replace it. err = sa_table_add(state); if(err) goto exit; sa_table_delete(existing); exit: dprintf("< err=%d\n", err); return err;}/** Allocate an SA. * * @return SA or NULL */SAState *SAState_alloc(void){ SAState *state; dprintf(">\n"); state = kmalloc(sizeof(SAState), GFP_ATOMIC); if(!state) goto exit; *state = (SAState){}; atomic_set(&state->refcount, 1); state->lock = SPIN_LOCK_UNLOCKED; exit: dprintf("< state=%p\n", state); return state;}/** Create an SA in initial state. * It has no spi and its keying state is acquire. * It must have a unique id, protocol and address. * At some point it should get updated with a complete SA. * * @param ident SA identifier * @param statep return parameter for new SA * @return 0 on success, error code otherwise */int SAState_init(SAIdent *ident, SAState **statep){ int err = 0; SAState *state = NULL; if(ident->spi || !ident->id){ err = -EINVAL; goto exit; } state = SAState_alloc(); if (!state){ err = -ENOMEM; goto exit; } state->ident = *ident; state->keying.state = SA_STATE_ACQUIRE; exit: return err;}/** Create a complete SA, with spi and cipher suite. * * @param info SA parameters * @param statep return parameter for new SA * @return 0 on success, error code otherwise */int SAState_create(SAInfo *info, SAState **statep){ int err = 0; SAState *state = NULL; dprintf(">\n"); state = SAState_alloc(); if (!state){ err = -ENOMEM; goto exit; } state->ident = info->ident; state->limits = info->limits; state->digest = info->digest; state->cipher = info->cipher; state->compress = info->compress; state->security = info->security; err = SAType_get(state->ident.protocol, &state->type); if (err) goto exit; err = state->type->init(state, NULL); if (err) goto exit; state->keying.state = SA_STATE_VALID; exit: if(err){ SAState_decref(state); state = NULL; } *statep = state; dprintf("< err=%d\n", err); return err;}/** Create an SA for the given spi etc. * For now we fix the cipher suite and the keys. * Digest is SHA1 HMAC with a 128-bit key. * Cipher is AES (Rijndael) in CBC mode with a 128-bit key. * * The cipher suite and keys should really come from policy, with the * possibility of negotiating them with the peer (using IKE). * Negotiation creates difficulties though - because the SA cannot * be created immediately we have to be able to queue packets * while the SA is being negotiated. * * @param spi spi * @param protocol protocol * @param addr address * @param sa return parameter for SA * @return 0 on success, error code otherwise */int sa_create(int security, u32 spi, u32 protocol, u32 addr, SAState **sa){ int err = 0; SAInfo info = {}; char *digest_name = "sha1"; char *digest_key = "0123456789abcdef"; int digest_key_n = strlen(digest_key); char *cipher_name= "aes"; char *cipher_key = "0123456789ABCDEF"; int cipher_key_n = strlen(cipher_key); dprintf("> security=%d spi=%u protocol=%u addr=" IPFMT "\n", security, spi, protocol, NIPQUAD(addr)); if(!spi){ spi = generate_spi(0, 0, protocol, addr); } dprintf("> info...\n"); info.ident.id = sa_id++; info.ident.spi = spi; info.ident.protocol = protocol; info.ident.addr = addr; info.security = security; //sa_algorithm_probe_all(); dprintf("> digest name=%s key_n=%d\n", digest_name, digest_key_n); strcpy(info.digest.name, digest_name); info.digest.bits = digest_key_n * 8; memcpy(info.digest.key, digest_key, digest_key_n); if(security & SA_CONF){ dprintf("> cipher name=%s key_n=%d\n", cipher_name, cipher_key_n); strcpy(info.cipher.name, cipher_name); info.cipher.bits = cipher_key_n * 8; memcpy(info.cipher.key, cipher_key, cipher_key_n); } else { dprintf("> cipher name=%s key_n=%d\n", "cipher_null", 0); strcpy(info.cipher.name, "cipher_null"); info.cipher.bits = 0; memset(info.cipher.key, 0, sizeof(info.cipher.key)); } err = sa_set(&info, 0, sa); dprintf("< err=%d\n", err); return err;}/** Create or update an SA. * The SA is added to the table. * * @param info SA parameters * @param update create if zero, update otherwise * @return 0 on success, error code otherwise */int sa_set(SAInfo *info, int update, SAState **val){ int err = 0; SAState *state = NULL; SAState *existing = NULL; dprintf("> info=%p update=%d val=%p\n", info, update, val); existing = sa_table_lookup_id(info->ident.id); if(update && !existing){ err = -ENOENT; } else if(!update && existing){ err = -EINVAL; } if(err) goto exit; err = SAState_create(info, &state); if (err) goto exit; if(existing){ err = sa_table_replace(existing, state); } else { err = sa_table_add(state); } exit: if(existing) SAState_decref(existing); if(val && !err){ *val = state; } else { SAState_decref(state); } dprintf("< err=%d\n", err); return err;}/** Delete an SA. Removes it from the SA table. * It is an error if no SA with the given id exists. * * @param id SA id * @return 0 on success, error code otherwise */int sa_delete(int id){ int err = 0; SAState *state; state = sa_table_lookup_id(id); if (!state){ err = -ENOENT; goto exit; } sa_table_delete(state); SAState_decref(state); exit: return err;}/** Determine ESP security mode for a new SA. * * @param spi incoming spi * @param protocol incoming protocol * @param addr source address * @return security level or negative error code * * @todo Need to check spi, and do some lookup for security params. */int vnet_sa_security(u32 spi, int protocol, u32 addr){ extern int vnet_security_default; int security = vnet_security_default; dprintf("< security=%x\n", security); return security;}/** Create a new SA for incoming traffic. * * @param spi incoming spi * @param protocol incoming protocol * @param addr source address * @param sa return parameter for SA * @return 0 on success, error code otherwise */int vnet_sa_create(u32 spi, int protocol, u32 addr, SAState **sa){ int err = 0; int security = vnet_sa_security(spi, protocol, addr); if(security < 0){ err = security; goto exit; } err = sa_create(security, spi, protocol, addr, sa); exit: return err;}/** Open function for SA tunnels. * * @param tunnel to open * @return 0 on success, error code otherwise */static int sa_tunnel_open(Tunnel *tunnel){ int err = 0; //dprintf(">\n"); //dprintf("< err=%d\n", err); return err;}/** Close function for SA tunnels. * * @param tunnel to close (OK if null) */static void sa_tunnel_close(Tunnel *tunnel){ SAState *sa; if(!tunnel) return; sa = tunnel->data; if(!sa) return; SAState_decref(sa); tunnel->data = NULL;}/** Packet send function for SA tunnels. * * @param tunnel to send on * @param skb packet to send * @return 0 on success, negative error code on error */static int sa_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){ int err = -EINVAL; SAState *sa; if(!tunnel){ wprintf("> Null tunnel!\n"); goto exit; } sa = tunnel->data; if(!sa){ wprintf("> Null SA!\n"); goto exit; } err = SAState_send(sa, skb, tunnel->base); exit: return err;}/** Functions used by SA tunnels. */static TunnelType _sa_tunnel_type = { .name = "SA", .open = sa_tunnel_open, .close = sa_tunnel_close, .send = sa_tunnel_send};/** Functions used by SA tunnels. */TunnelType *sa_tunnel_type = &_sa_tunnel_type;int sa_tunnel_create(Vnet *info, VarpAddr *addr, Tunnel *base, Tunnel **tunnel){ int err = 0; SAState *sa = NULL; //FIXME: Assuming IPv4 for now. u32 ipaddr = addr->u.ip4.s_addr; err = Tunnel_create(sa_tunnel_type, &info->vnet, addr, base, tunnel); if(err) goto exit; err = sa_create(info->security, 0, IPPROTO_ESP, ipaddr, &sa); if(err) goto exit; (*tunnel)->data = sa; exit: return err;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?