aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/esp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/esp6.c')
-rw-r--r--net/ipv6/esp6.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index ee9b93bdd6a2..1b5c9825743b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -49,6 +49,8 @@ struct esp_skb_cb {
49 49
50#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) 50#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
51 51
52static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);
53
52/* 54/*
53 * Allocate an AEAD request structure with extra space for SG and IV. 55 * Allocate an AEAD request structure with extra space for SG and IV.
54 * 56 *
@@ -140,6 +142,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
140 int blksize; 142 int blksize;
141 int clen; 143 int clen;
142 int alen; 144 int alen;
145 int plen;
146 int tfclen;
143 int nfrags; 147 int nfrags;
144 u8 *iv; 148 u8 *iv;
145 u8 *tail; 149 u8 *tail;
@@ -148,18 +152,26 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
148 /* skb is pure payload to encrypt */ 152 /* skb is pure payload to encrypt */
149 err = -ENOMEM; 153 err = -ENOMEM;
150 154
151 /* Round to block size */
152 clen = skb->len;
153
154 aead = esp->aead; 155 aead = esp->aead;
155 alen = crypto_aead_authsize(aead); 156 alen = crypto_aead_authsize(aead);
156 157
158 tfclen = 0;
159 if (x->tfcpad) {
160 struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
161 u32 padto;
162
163 padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached));
164 if (skb->len < padto)
165 tfclen = padto - skb->len;
166 }
157 blksize = ALIGN(crypto_aead_blocksize(aead), 4); 167 blksize = ALIGN(crypto_aead_blocksize(aead), 4);
158 clen = ALIGN(clen + 2, blksize); 168 clen = ALIGN(skb->len + 2 + tfclen, blksize);
159 if (esp->padlen) 169 if (esp->padlen)
160 clen = ALIGN(clen, esp->padlen); 170 clen = ALIGN(clen, esp->padlen);
171 plen = clen - skb->len - tfclen;
161 172
162 if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0) 173 err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
174 if (err < 0)
163 goto error; 175 goto error;
164 nfrags = err; 176 nfrags = err;
165 177
@@ -174,13 +186,17 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
174 186
175 /* Fill padding... */ 187 /* Fill padding... */
176 tail = skb_tail_pointer(trailer); 188 tail = skb_tail_pointer(trailer);
189 if (tfclen) {
190 memset(tail, 0, tfclen);
191 tail += tfclen;
192 }
177 do { 193 do {
178 int i; 194 int i;
179 for (i=0; i<clen-skb->len - 2; i++) 195 for (i = 0; i < plen - 2; i++)
180 tail[i] = i + 1; 196 tail[i] = i + 1;
181 } while (0); 197 } while (0);
182 tail[clen-skb->len - 2] = (clen - skb->len) - 2; 198 tail[plen - 2] = plen - 2;
183 tail[clen - skb->len - 1] = *skb_mac_header(skb); 199 tail[plen - 1] = *skb_mac_header(skb);
184 pskb_put(skb, trailer, clen - skb->len + alen); 200 pskb_put(skb, trailer, clen - skb->len + alen);
185 201
186 skb_push(skb, -skb_network_offset(skb)); 202 skb_push(skb, -skb_network_offset(skb));