On Thu, Oct 20, 2005 at 05:22:03PM +0400, Alexey I. Froloff wrote: > * Alexey I. Froloff [051020 11:59]: > > Пару месяцев назад писал сюда про свой Oops. На IRC vsu@ мне > > посоветовал пересобрать ядро с DEBUG_STACKOVERFLOW, лог в аттаче. Похоже, совет был всё-таки правильным (а DEBUG_STACKOVERFLOW, возможно, стоит включать по умолчанию - при этом добавляется только одна проверка в do_IRQ()). > dmesg | ksymoops тоже в аттаче. Оказывается, функция ipsec_tunnel_start_xmit() использует для локальных переменных 1212 байт в стеке. Безобразие. Следующим патчем удалось сократить запросы этой функции до 420 байт (хотя это тоже слишком много). Патч не тестировался ничем, кроме компилятора. --- kernel-source-2.4.26/net/ipsec/ipsec_tunnel.c.ipsec_tunnel-stack 2005-09-08 18:25:59 +0400 +++ kernel-source-2.4.26/net/ipsec/ipsec_tunnel.c 2005-10-20 20:19:08 +0400 @@ -592,10 +592,8 @@ ipsec_tunnel_start_xmit(struct sk_buff * int i; unsigned short sport,dport; - struct sockaddr_encap matcher; /* eroute search key */ struct eroute *er; struct ipsec_sa *tdbp, *tdbq; /* Tunnel Descriptor Block pointers */ - char sa[SATOA_BUF]; size_t sa_len; int hard_header_stripped = 0; /* has the hard header been removed yet? */ int hard_header_len = 0; @@ -613,7 +611,6 @@ ipsec_tunnel_start_xmit(struct sk_buff * #endif /* NET_21 */ int error = 0; uint32_t eroute_pid = 0; - struct ipsec_sa tdb; #ifdef CONFIG_IPSEC_ALG struct ipsec_alg_enc *ixt_e = NULL; struct ipsec_alg_auth *ixt_a = NULL; @@ -623,11 +620,30 @@ ipsec_tunnel_start_xmit(struct sk_buff * uint8_t natt_type = 0, natt_head = 0; uint16_t natt_sport = 0, natt_dport = 0; #endif + struct { + struct sockaddr_encap matcher; /* eroute search key */ + char sa[SATOA_BUF]; + struct ipsec_sa tdb; + struct sockaddr_in src, dst; +#ifdef CONFIG_IPSEC_DEBUG + char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; +#endif /* CONFIG_IPSEC_DEBUG */ + struct iphdr ipo; +#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) + union { +#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 + MD5_CTX md5; +#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ +#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 + SHA1_CTX sha1; +#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ + } tctx; + __u8 hash[AH_AMAX]; +#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */ + } *locals = 0; /* local variables too big for stack */ dport=sport=0; - memset((char*)&tdb, 0, sizeof(struct ipsec_sa)); - /* * Return if there is nothing to do. (Does this ever happen?) XXX */ @@ -664,6 +680,18 @@ ipsec_tunnel_start_xmit(struct sk_buff * stats = (struct net_device_stats *) &(prv->mystats); + locals = kmalloc(sizeof(*locals), GFP_ATOMIC); + if (!locals) { + if (net_ratelimit()) + printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: " + "Failed, tried to allocate %ld bytes for local variables.\n", + (long)sizeof(*locals)); + stats->tx_dropped++; + goto cleanup; + } + + memset((char*)&locals->tdb, 0, sizeof(struct ipsec_sa)); + #ifdef NET_21 /* if skb was cloned (most likely due to a packet sniffer such as tcpdump being momentarily attached to the interface), make @@ -780,13 +808,13 @@ ipsec_tunnel_start_xmit(struct sk_buff * /* * First things first -- look us up in the erouting tables. */ - matcher.sen_len = sizeof (struct sockaddr_encap); - matcher.sen_family = AF_ENCAP; - matcher.sen_type = SENT_IP4; - matcher.sen_ip_src.s_addr = iph->saddr; - matcher.sen_ip_dst.s_addr = iph->daddr; - matcher.sen_proto = iph->protocol; - extract_ports(iph, &matcher); + locals->matcher.sen_len = sizeof (struct sockaddr_encap); + locals->matcher.sen_family = AF_ENCAP; + locals->matcher.sen_type = SENT_IP4; + locals->matcher.sen_ip_src.s_addr = iph->saddr; + locals->matcher.sen_ip_dst.s_addr = iph->daddr; + locals->matcher.sen_proto = iph->protocol; + extract_ports(iph, &locals->matcher); /* * The spinlock is to prevent any other process from accessing or deleting @@ -794,7 +822,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * */ spin_lock(&eroute_lock); - er = ipsec_findroute(&matcher); + er = ipsec_findroute(&locals->matcher); if(iph->protocol == IPPROTO_UDP) { if(skb->sk) { @@ -877,12 +905,12 @@ ipsec_tunnel_start_xmit(struct sk_buff * || (outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) { int len; - tdb.tdb_ident_s.type = er->er_ident_s.type; - tdb.tdb_ident_s.id = er->er_ident_s.id; - tdb.tdb_ident_s.len = er->er_ident_s.len; - if (tdb.tdb_ident_s.len) { - len = tdb.tdb_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); - if ((tdb.tdb_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { + locals->tdb.tdb_ident_s.type = er->er_ident_s.type; + locals->tdb.tdb_ident_s.id = er->er_ident_s.id; + locals->tdb.tdb_ident_s.len = er->er_ident_s.len; + if (locals->tdb.tdb_ident_s.len) { + len = locals->tdb.tdb_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); + if ((locals->tdb.tdb_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: " "Failed, tried to allocate %d bytes for source ident.\n", len); @@ -890,14 +918,14 @@ ipsec_tunnel_start_xmit(struct sk_buff * spin_unlock(&eroute_lock); goto cleanup; } - memcpy(tdb.tdb_ident_s.data, er->er_ident_s.data, len); + memcpy(locals->tdb.tdb_ident_s.data, er->er_ident_s.data, len); } - tdb.tdb_ident_d.type = er->er_ident_d.type; - tdb.tdb_ident_d.id = er->er_ident_d.id; - tdb.tdb_ident_d.len = er->er_ident_d.len; - if (tdb.tdb_ident_d.len) { - len = tdb.tdb_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); - if ((tdb.tdb_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { + locals->tdb.tdb_ident_d.type = er->er_ident_d.type; + locals->tdb.tdb_ident_d.id = er->er_ident_d.id; + locals->tdb.tdb_ident_d.len = er->er_ident_d.len; + if (locals->tdb.tdb_ident_d.len) { + len = locals->tdb.tdb_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); + if ((locals->tdb.tdb_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: " "Failed, tried to allocate %d bytes for dest ident.\n", len); @@ -905,7 +933,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * spin_unlock(&eroute_lock); goto cleanup; } - memcpy(tdb.tdb_ident_d.data, er->er_ident_d.data, len); + memcpy(locals->tdb.tdb_ident_d.data, er->er_ident_d.data, len); } } } @@ -970,24 +998,19 @@ ipsec_tunnel_start_xmit(struct sk_buff * case SPI_TRAP: case SPI_TRAPSUBNET: { - struct sockaddr_in src, dst; -#ifdef CONFIG_IPSEC_DEBUG - char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; -#endif /* CONFIG_IPSEC_DEBUG */ - /* Signal all listening KMds with a PF_KEY ACQUIRE */ - tdb.tdb_said.proto = iph->protocol; - src.sin_family = AF_INET; - dst.sin_family = AF_INET; - src.sin_addr.s_addr = iph->saddr; - dst.sin_addr.s_addr = iph->daddr; - src.sin_port = + locals->tdb.tdb_said.proto = iph->protocol; + locals->src.sin_family = AF_INET; + locals->dst.sin_family = AF_INET; + locals->src.sin_addr.s_addr = iph->saddr; + locals->dst.sin_addr.s_addr = iph->daddr; + locals->src.sin_port = (iph->protocol == IPPROTO_UDP ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source : (iph->protocol == IPPROTO_TCP ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source : 0)); - dst.sin_port = + locals->dst.sin_port = (iph->protocol == IPPROTO_UDP ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest : (iph->protocol == IPPROTO_TCP @@ -997,22 +1020,22 @@ ipsec_tunnel_start_xmit(struct sk_buff * i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) { - src.sin_zero[i] = 0; - dst.sin_zero[i] = 0; + locals->src.sin_zero[i] = 0; + locals->dst.sin_zero[i] = 0; } - tdb.tdb_addr_s = (struct sockaddr*)(&src); - tdb.tdb_addr_d = (struct sockaddr*)(&dst); + locals->tdb.tdb_addr_s = (struct sockaddr*)(&locals->src); + locals->tdb.tdb_addr_d = (struct sockaddr*)(&locals->dst); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", - addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", - ntohs(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_port), - addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", - ntohs(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port), - tdb.tdb_said.proto); + addrtoa(((struct sockaddr_in*)(locals->tdb.tdb_addr_s))->sin_addr, 0, locals->bufsrc, sizeof(locals->bufsrc)) <= ADDRTOA_BUF ? locals->bufsrc : "BAD_ADDR", + ntohs(((struct sockaddr_in*)(locals->tdb.tdb_addr_s))->sin_port), + addrtoa(((struct sockaddr_in*)(locals->tdb.tdb_addr_d))->sin_addr, 0, locals->bufdst, sizeof(locals->bufdst)) <= ADDRTOA_BUF ? locals->bufdst : "BAD_ADDR", + ntohs(((struct sockaddr_in*)(locals->tdb.tdb_addr_d))->sin_port), + locals->tdb.tdb_said.proto); - if (pfkey_acquire(&tdb) == 0) { + if (pfkey_acquire(&locals->tdb) == 0) { if (outgoing_said.spi==htonl(SPI_TRAPSUBNET)) { /* @@ -1022,7 +1045,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * * updating it. */ spin_lock(&eroute_lock); - er = ipsec_findroute(&matcher); + er = ipsec_findroute(&locals->matcher); if(er) { er->er_said.spi = htonl(SPI_HOLD); er->er_first = skb; @@ -1056,14 +1079,14 @@ ipsec_tunnel_start_xmit(struct sk_buff * spin_lock(&tdb_lock); tdbp = ipsec_sa_getbyid(&outgoing_said); - sa_len = satoa(outgoing_said, 0, sa, SATOA_BUF); + sa_len = satoa(outgoing_said, 0, locals->sa, SATOA_BUF); if (tdbp == NULL) { spin_unlock(&tdb_lock); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "no Tunnel Descriptor Block for SA%s: outgoing packet with no SA, dropped.\n", - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); stats->tx_dropped++; goto cleanup; } @@ -1072,7 +1095,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "found Tunnel Descriptor Block -- SA:<%s%s%s> %s\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); /* * How much headroom do we need to be able to apply @@ -1080,9 +1103,9 @@ ipsec_tunnel_start_xmit(struct sk_buff * */ tdbq = tdbp; /* save the head of the tdb chain */ while (tdbp) { - sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF); + sa_len = satoa(tdbp->tdb_said, 0, locals->sa, SATOA_BUF); if(sa_len == 0) { - strcpy(sa, "(error)"); + strcpy(locals->sa, "(error)"); } /* If it is in larval state, drop the packet, we cannot process yet. */ @@ -1091,7 +1114,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "TDB in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; @@ -1102,7 +1125,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "TDB in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; @@ -1115,7 +1138,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); ipsec_sa_delchain(tdbp); spin_unlock(&tdb_lock); stats->tx_errors++; @@ -1135,13 +1158,13 @@ ipsec_tunnel_start_xmit(struct sk_buff * #endif - if(ipsec_lifetime_check(&tdbp->ips_life.ipl_bytes, "bytes", sa, + if(ipsec_lifetime_check(&tdbp->ips_life.ipl_bytes, "bytes", locals->sa, ipsec_life_countbased, ipsec_outgoing, tdbp) == ipsec_life_harddied || - ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "addtime",sa, + ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "addtime",locals->sa, ipsec_life_timebased, ipsec_outgoing, tdbp) == ipsec_life_harddied || - ipsec_lifetime_check(&tdbp->ips_life.ipl_usetime, "usetime",sa, + ipsec_lifetime_check(&tdbp->ips_life.ipl_usetime, "usetime",locals->sa, ipsec_life_timebased, ipsec_outgoing, tdbp) == ipsec_life_harddied || - ipsec_lifetime_check(&tdbp->ips_life.ipl_packets, "packets",sa, + ipsec_lifetime_check(&tdbp->ips_life.ipl_packets, "packets",locals->sa, ipsec_life_countbased, ipsec_outgoing, tdbp) == ipsec_life_harddied) { ipsec_sa_delchain(tdbp); @@ -1156,7 +1179,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "calling room for <%s%s%s>, SA:%s\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); switch(tdbp->tdb_said.proto) { #ifdef CONFIG_IPSEC_AH case IPPROTO_AH: @@ -1552,31 +1575,19 @@ ipsec_tunnel_start_xmit(struct sk_buff * int authlen = 0, padlen = 0, i; #endif /* !CONFIG_IPSEC_ESP */ #ifdef CONFIG_IPSEC_AH - struct iphdr ipo; struct ah *ahp; #endif /* CONFIG_IPSEC_AH */ -#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) - union { -#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 - MD5_CTX md5; -#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 - SHA1_CTX sha1; -#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ - } tctx; - __u8 hash[AH_AMAX]; -#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */ int headroom = 0, tailroom = 0, ilen = 0, len = 0; unsigned char *dat; iphlen = iph->ihl << 2; pyldsz = ntohs(iph->tot_len) - iphlen; - sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF); + sa_len = satoa(tdbp->tdb_said, 0, locals->sa, SATOA_BUF); KLIPS_PRINT(debug_tunnel & DB_TN_OXFS, "klips_debug:ipsec_tunnel_start_xmit: " "calling output for <%s%s%s>, SA:%s\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); switch(tdbp->tdb_said.proto) { #ifdef CONFIG_IPSEC_AH @@ -1799,38 +1810,38 @@ ipsec_tunnel_start_xmit(struct sk_buff * #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: dmp("espp", (char*)espp, len - iphlen - authlen); - tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; - dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, (caddr_t)espp, len - iphlen - authlen); - dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Final(hash, &tctx.md5); - dmp("ictx hash", (char*)&hash, sizeof(hash)); - tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; - dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, hash, AHMD596_ALEN); - dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Final(hash, &tctx.md5); - dmp("octx hash", (char*)&hash, sizeof(hash)); - memcpy(&(dat[len - authlen]), hash, authlen); + locals->tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; + dmp("ictx", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, (caddr_t)espp, len - iphlen - authlen); + dmp("ictx+dat", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Final(locals->hash, &locals->tctx.md5); + dmp("ictx hash", (char*)&locals->hash, sizeof(locals->hash)); + locals->tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; + dmp("octx", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, locals->hash, AHMD596_ALEN); + dmp("octx+hash", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Final(locals->hash, &locals->tctx.md5); + dmp("octx hash", (char*)&locals->hash, sizeof(locals->hash)); + memcpy(&(dat[len - authlen]), locals->hash, authlen); /* paranoid */ - memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); - memset((caddr_t)hash, 0, sizeof(*hash)); + memset((caddr_t)&locals->tctx.md5, 0, sizeof(locals->tctx.md5)); + memset((caddr_t)locals->hash, 0, sizeof(*locals->hash)); break; #endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ #ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: - tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; - SHA1Update(&tctx.sha1, (caddr_t)espp, len - iphlen - authlen); - SHA1Final(hash, &tctx.sha1); - tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; - SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); - SHA1Final(hash, &tctx.sha1); - memcpy(&(dat[len - authlen]), hash, authlen); + locals->tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; + SHA1Update(&locals->tctx.sha1, (caddr_t)espp, len - iphlen - authlen); + SHA1Final(locals->hash, &locals->tctx.sha1); + locals->tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; + SHA1Update(&locals->tctx.sha1, locals->hash, AHSHA196_ALEN); + SHA1Final(locals->hash, &locals->tctx.sha1); + memcpy(&(dat[len - authlen]), locals->hash, authlen); /* paranoid */ - memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); - memset((caddr_t)hash, 0, sizeof(*hash)); + memset((caddr_t)&locals->tctx.sha1, 0, sizeof(locals->tctx.sha1)); + memset((caddr_t)locals->hash, 0, sizeof(*locals->hash)); break; #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ case AH_NONE: @@ -1856,59 +1867,59 @@ ipsec_tunnel_start_xmit(struct sk_buff * iph->protocol = IPPROTO_AH; dmp("ahp", (char*)ahp, sizeof(*ahp)); - ipo = *iph; - ipo.tos = 0; - ipo.frag_off = 0; - ipo.ttl = 0; - ipo.check = 0; - dmp("ipo", (char*)&ipo, sizeof(ipo)); + locals->ipo = *iph; + locals->ipo.tos = 0; + locals->ipo.frag_off = 0; + locals->ipo.ttl = 0; + locals->ipo.check = 0; + dmp("ipo", (char*)&locals->ipo, sizeof(locals->ipo)); switch(tdbp->tdb_authalg) { #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: - tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; - dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); - dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); - dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); - dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, dat + iphlen + headroom, len - iphlen - headroom); - dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Final(hash, &tctx.md5); - dmp("ictx hash", (char*)&hash, sizeof(hash)); - tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; - dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Update(&tctx.md5, hash, AHMD596_ALEN); - dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); - MD5Final(hash, &tctx.md5); - dmp("octx hash", (char*)&hash, sizeof(hash)); + locals->tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; + dmp("ictx", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, (unsigned char *)&locals->ipo, sizeof (struct iphdr)); + dmp("ictx+ipo", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); + dmp("ictx+ahp", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); + dmp("ictx+zeroes", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, dat + iphlen + headroom, len - iphlen - headroom); + dmp("ictx+dat", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Final(locals->hash, &locals->tctx.md5); + dmp("ictx hash", (char*)&locals->hash, sizeof(locals->hash)); + locals->tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; + dmp("octx", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Update(&locals->tctx.md5, locals->hash, AHMD596_ALEN); + dmp("octx+hash", (char*)&locals->tctx.md5, sizeof(locals->tctx.md5)); + MD5Final(locals->hash, &locals->tctx.md5); + dmp("octx hash", (char*)&locals->hash, sizeof(locals->hash)); - memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); + memcpy(ahp->ah_data, locals->hash, AHHMAC_HASHLEN); /* paranoid */ - memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); - memset((caddr_t)hash, 0, sizeof(hash)); + memset((caddr_t)&locals->tctx.md5, 0, sizeof(locals->tctx.md5)); + memset((caddr_t)locals->hash, 0, sizeof(locals->hash)); break; #endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ #ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: - tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; - SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); - SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); - SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); - SHA1Update(&tctx.sha1, dat + iphlen + headroom, len - iphlen - headroom); - SHA1Final(hash, &tctx.sha1); - tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; - SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); - SHA1Final(hash, &tctx.sha1); + locals->tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; + SHA1Update(&locals->tctx.sha1, (unsigned char *)&locals->ipo, sizeof (struct iphdr)); + SHA1Update(&locals->tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); + SHA1Update(&locals->tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); + SHA1Update(&locals->tctx.sha1, dat + iphlen + headroom, len - iphlen - headroom); + SHA1Final(locals->hash, &locals->tctx.sha1); + locals->tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; + SHA1Update(&locals->tctx.sha1, locals->hash, AHSHA196_ALEN); + SHA1Final(locals->hash, &locals->tctx.sha1); - memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); + memcpy(ahp->ah_data, locals->hash, AHHMAC_HASHLEN); /* paranoid */ - memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); - memset((caddr_t)hash, 0, sizeof(hash)); + memset((caddr_t)&locals->tctx.sha1, 0, sizeof(locals->tctx.sha1)); + memset((caddr_t)locals->hash, 0, sizeof(locals->hash)); break; #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ default: @@ -2030,7 +2041,7 @@ ipsec_tunnel_start_xmit(struct sk_buff * "klips_debug:ipsec_tunnel_start_xmit: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(tdbp), - sa_len ? sa : " (error)"); + sa_len ? locals->sa : " (error)"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph); tdbp->ips_life.ipl_bytes.ipl_count += len; @@ -2054,13 +2065,13 @@ ipsec_tunnel_start_xmit(struct sk_buff * spin_unlock(&tdb_lock); - matcher.sen_ip_src.s_addr = iph->saddr; - matcher.sen_ip_dst.s_addr = iph->daddr; - matcher.sen_proto = iph->protocol; - extract_ports(iph, &matcher); + locals->matcher.sen_ip_src.s_addr = iph->saddr; + locals->matcher.sen_ip_dst.s_addr = iph->daddr; + locals->matcher.sen_proto = iph->protocol; + extract_ports(iph, &locals->matcher); spin_lock(&eroute_lock); - er = ipsec_findroute(&matcher); + er = ipsec_findroute(&locals->matcher); if(er) { outgoing_said = er->er_said; eroute_pid = er->er_pid; @@ -2243,12 +2254,13 @@ ipsec_tunnel_start_xmit(struct sk_buff * if(oskb) { dev_kfree_skb(oskb, FREE_WRITE); } - if (tdb.tdb_ident_s.data) { - kfree(tdb.tdb_ident_s.data); + if (locals && locals->tdb.tdb_ident_s.data) { + kfree(locals->tdb.tdb_ident_s.data); } - if (tdb.tdb_ident_d.data) { - kfree(tdb.tdb_ident_d.data); + if (locals && locals->tdb.tdb_ident_d.data) { + kfree(locals->tdb.tdb_ident_d.data); } + kfree(locals); return 0; }