当前位置:   article > 正文

linux数据包注释,Linux网络子系统安全性模块代码详细分析之文件esp4.c中内部函数和核心代码注释...

linux tfclen是什么

原标题:Linux网络子系统安全性模块代码详细分析之文件esp4.c中内部函数和核心代码注释

2.4.6.5内部函数1. esp_init_state( )

函数原型:static int esp_init_state(struct xfrm_state *x)

函数参数:参数x为安全关联。

函数功能:初始化SA中用于ESP处理的相关字段,主要初始化认证加密算法和协议头的长度,在初始化认证加密算法中。

返回值:返回算法初始化函数的返回值。

2. esp_init_aead( )

函数原型:static int esp_init_aead(struct xfrm_state *x)

函数参数:参数x为安全关联。

函数功能:分配认证加密算法结构,并设置算法密钥和认证向量的长度。

返回值:正确则返回0,否则返回错误码。

3. esp_input( )

函数原型:static int esp_input(struct xfrm_state *x, struct sk_buff *skb)

函数参数:参数x为SA结构,skb为套接字缓冲区。

函数功能:ESP协议封装的数据包的进入链处理,首先进行身份认证,认证通过后则调用解密算法进行数据包的解密,如果经过了UDP封装还要修改端口等字段。

返回值:返回下一头标号。

4. esp_input_done2( )

函数原型:static int esp_input_done2(struct sk_buff *skb, int err)

函数参数:参数skb为套接字缓冲区,err为加密的结果。

函数功能:进入数据包的第二阶段处理,主要是判断是否需要进行UDP封装和重新设置传输层头。

返回值:查找到的SA。

5. esp_output( )

函数原型:static int esp_output(struct xfrm_state *x, struct sk_buff *skb)

函数参数:参数x为SA结构,skb为套接字缓冲区。

函数功能:进行输出链ESP协议处理,主要完成了认证向量的初始化,数据包的加密,以及UDP封装等操作。

返回值:解密的结果。

2.4.6.6 核心代码注释

esp_input( )和esp_output( )函数是本文件的核心函数,分别是数据包进入链和发送链的ESP处理,其执行逻辑参见2.3.2节,由于进入和发送处理正好是相反的操作,此处主要分析esp_output( )函数的代码。

static int esp_output(struct xfrm_state *x, struct sk_buff *skb)

{

int err;

struct ip_esp_hdr *esph;

struct crypto_aead *aead;

struct aead_givcrypt_request *req;

struct scatterlist *sg;

struct scatterlist *asg;

struct esp_data *esp;

struct sk_buff *trailer;

void *tmp;

u8 *iv;

u8 *tail;

int blksize;

int clen;

int alen;

int plen;

int tfclen;

int nfrags;

int assoclen;

int sglists;

int seqhilen;

__be32 *seqhi;

err = -ENOMEM;

//从SA中获取进行esp处理的数据、认证加密算法,并计算认证长度

esp = x->data;

aead = esp->aead;

alen = crypto_aead_authsize(aead);

//填充数据处理

tfclen = 0;

if (x->tfcpad) {

struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);

u32 padto;

padto = min(x->tfcpad, esp4_get_mtu(x, dst->child_mtu_cached));

if (skb->len < padto)

tfclen = padto - skb->len;

}

//加密块的大小、加密长度的获取

blksize = ALIGN(crypto_aead_blocksize(aead), 4);

clen = ALIGN(skb->len + 2 + tfclen, blksize);

if (esp->padlen)

clen = ALIGN(clen, esp->padlen);

plen = clen - skb->len - tfclen;

//让套接字缓冲区可写,并获取分片数存放在nfrags变量中

err = skb_cow_data(skb, tfclen + plen + alen, &trailer);

if (err < 0)

goto error;

nfrags = err;

assoclen = sizeof(*esph);

sglists = 1;

seqhilen = 0;

if (x->props.flags & XFRM_STATE_ESN) {

sglists += 2;

seqhilen += sizeof(__be32);

assoclen += seqhilen;

}

//分配一个用于认证加密的临时结构,该结构中主要存储了认证向量IV和分片链表SG

tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);

if (!tmp)

goto error;

//从临时结构中获取相应的结构

seqhi = esp_tmp_seqhi(tmp);

iv = esp_tmp_iv(aead, tmp, seqhilen);

req = esp_tmp_givreq(aead, iv);

asg = esp_givreq_sg(aead, req);

sg = asg + sglists;

//填充套接字缓冲区尾部

tail = skb_tail_pointer(trailer);

if (tfclen) {

memset(tail, 0, tfclen);

tail += tfclen;

}

do {

int i;

for (i = 0; i < plen - 2; i++)

tail[i] = i + 1;

} while (0);

tail[plen - 2] = plen - 2;

tail[plen - 1] = *skb_mac_header(skb);

//增加缓冲区的头部和尾部

pskb_put(skb, trailer, clen - skb->len + alen);

skb_push(skb, -skb_network_offset(skb));

esph = ip_esp_hdr(skb);

*skb_mac_header(skb) = IPPROTO_ESP;

//如果经过了NAT,则要进行UDP封装,并修改传输层头中的源端口和目的端口

if (x->encap) {

struct xfrm_encap_tmpl *encap = x->encap;

struct udphdr *uh;

__be32 *udpdata32;

__be16 sport, dport;

int encap_type;

spin_lock_bh(&x->lock);

sport = encap->encap_sport;

dport = encap->encap_dport;

encap_type = encap->encap_type;

spin_unlock_bh(&x->lock);

uh = (struct udphdr *)esph;

uh->source = sport;

uh->dest = dport;

uh->len = htons(skb->len - skb_transport_offset(skb));

uh->check = 0;

switch (encap_type) {

default:

case UDP_ENCAP_ESPINUDP:

esph = (struct ip_esp_hdr *)(uh + 1);

break;

case UDP_ENCAP_ESPINUDP_NON_IKE:

udpdata32 = (__be32 *)(uh + 1);

udpdata32[0] = udpdata32[1] = 0;

esph = (struct ip_esp_hdr *)(udpdata32 + 2);

break;

}

*skb_mac_header(skb) = IPPROTO_UDP;

}

//修改esp头中的spi和序列号

esph->spi = x->id.spi;

esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);

//设置分片列表SG

sg_init_table(sg, nfrags);

skb_to_sgvec(skb, sg,

esph->enc_data + crypto_aead_ivsize(aead) - skb->data,

clen + alen);

//设置加密回调函数,设置加密请求结构req,以及IV等信息

aead_givcrypt_set_callback(req, 0, esp_output_done, skb);

aead_givcrypt_set_crypt(req, sg, sg, clen, iv);

aead_givcrypt_set_assoc(req, asg, assoclen);

aead_givcrypt_set_giv(req, esph->enc_data,XFRM_SKB_CB(skb)->seq.output.low);

//加密数据包

err = crypto_aead_givencrypt(req);

kfree(tmp);

error:

return err;

责任编辑:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/814534
推荐阅读
相关标签
  

闽ICP备14008679号