Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet PR/25622: IPV6 return RST and through cloned int...
details: https://anonhg.NetBSD.org/src/rev/9f15065e121b
branches: trunk
changeset: 566768:9f15065e121b
user: christos <christos%NetBSD.org@localhost>
date: Thu May 20 13:55:31 2004 +0000
description:
PR/25622: IPV6 return RST and through cloned interfaces was broken.
- checksum was computed incorrectly.
- ipv6 packet was not initialized properly.
- fixed code to be more similar to the v4 counterpart.
diffstat:
sys/netinet/fil.c | 7 +-
sys/netinet/ip_fil_netbsd.c | 142 ++++++++++++++++++++++++++-----------------
2 files changed, 89 insertions(+), 60 deletions(-)
diffs (truncated from 376 to 300 lines):
diff -r dd0680196d65 -r 9f15065e121b sys/netinet/fil.c
--- a/sys/netinet/fil.c Thu May 20 13:54:19 2004 +0000
+++ b/sys/netinet/fil.c Thu May 20 13:55:31 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fil.c,v 1.64 2004/05/10 01:34:59 christos Exp $ */
+/* $NetBSD: fil.c,v 1.65 2004/05/20 13:55:31 christos Exp $ */
/*
* Copyright (C) 1993-2003 by Darren Reed.
@@ -135,7 +135,7 @@
#if !defined(lint)
#if defined(__NetBSD__)
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.64 2004/05/10 01:34:59 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.65 2004/05/20 13:55:31 christos Exp $");
#else
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.7 2004/03/23 12:06:56 darrenr Exp";
@@ -2657,7 +2657,7 @@
ip6 = (ip6_t *)ip;
hlen = sizeof(*ip6);
slen = ntohs(ip6->ip6_plen);
- sum = htons((u_short)ip6->ip6_nxt);
+ sum = htons((u_short)l4proto);
sum += htons(slen);
sp = (u_short *)&ip6->ip6_src;
sum += *sp++; /* ip6_src */
@@ -2675,6 +2675,7 @@
sum += *sp++;
sum += *sp++;
sum += *sp++;
+ sum += *sp++;
}
#endif
diff -r dd0680196d65 -r 9f15065e121b sys/netinet/ip_fil_netbsd.c
--- a/sys/netinet/ip_fil_netbsd.c Thu May 20 13:54:19 2004 +0000
+++ b/sys/netinet/ip_fil_netbsd.c Thu May 20 13:55:31 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_fil_netbsd.c,v 1.9 2004/05/18 21:47:45 christos Exp $ */
+/* $NetBSD: ip_fil_netbsd.c,v 1.10 2004/05/20 13:55:32 christos Exp $ */
/*
* Copyright (C) 1993-2003 by Darren Reed.
@@ -693,8 +693,6 @@
m = m_gethdr(M_DONTWAIT, MT_HEADER);
if (m == NULL)
- return ENOBUFS;
- if (m == NULL)
return -1;
tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
@@ -716,23 +714,32 @@
#endif
bzero((char *)ip, sizeof(*tcp2) + hlen);
tcp2 = (struct tcphdr *)((char *)ip + hlen);
-
tcp2->th_sport = tcp->th_dport;
tcp2->th_dport = tcp->th_sport;
+
if (tcp->th_flags & TH_ACK) {
tcp2->th_seq = tcp->th_ack;
tcp2->th_flags = TH_RST;
+ tcp2->th_ack = 0;
} else {
+ tcp2->th_seq = 0;
tcp2->th_ack = ntohl(tcp->th_seq);
tcp2->th_ack += tlen;
tcp2->th_ack = htonl(tcp2->th_ack);
tcp2->th_flags = TH_RST|TH_ACK;
}
+ tcp2->th_x2 = 0;
TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
+ tcp2->th_win = tcp->th_win;
+ tcp2->th_sum = 0;
+ tcp2->th_urp = 0;
+
#ifdef USE_INET6
if (fin->fin_v == 6) {
+ ip6->ip6_flow = 0;
ip6->ip6_plen = htons(sizeof(struct tcphdr));
ip6->ip6_nxt = IPPROTO_TCP;
+ ip6->ip6_hlim = 0;
ip6->ip6_src = fin->fin_dst6;
ip6->ip6_dst = fin->fin_src6;
tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
@@ -750,6 +757,26 @@
}
+/* ------------------------------------------------------------------------ */
+/* Function: fr_nextipid */
+/* Returns: int - 0 == success, -1 == error (packet should be droppped) */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* Returns the next IPv4 ID to use for this packet. */
+/* ------------------------------------------------------------------------ */
+INLINE u_short fr_nextipid(fin)
+fr_info_t *fin;
+{
+ static u_short ipid = 0;
+ u_short id;
+
+ MUTEX_ENTER(&ipf_rw);
+ id = ipid++;
+ MUTEX_EXIT(&ipf_rw);
+
+ return id;
+}
+
static int fr_send_ip(fin, m, mpp)
fr_info_t *fin;
mb_t *m, **mpp;
@@ -765,7 +792,7 @@
oip = fin->fin_ip;
IP_HL_A(ip, sizeof(*oip) >> 2);
ip->ip_tos = oip->ip_tos;
- ip->ip_id = fin->fin_ip->ip_id;
+ ip->ip_id = fr_nextipid(fin);
ip->ip_off = ip_mtudisc ? IP_DF : 0;
ip->ip_ttl = ip_defttl;
ip->ip_sum = 0;
@@ -775,7 +802,10 @@
{
ip6_t *ip6 = (ip6_t *)ip;
+ ip6->ip6_vfc = 0x60;
ip6->ip6_hlim = IPDEFTTL;
+
+ break;
}
#endif
default :
@@ -793,7 +823,7 @@
fr_info_t *fin;
int dst;
{
- int err, hlen, xtra, ohlen, iclen, avail, code;
+ int err, hlen, xtra, iclen, ohlen, avail, code;
struct in_addr dst4;
struct icmp *icmp;
struct mbuf *m;
@@ -841,7 +871,7 @@
avail = MHLEN;
m = m_gethdr(M_DONTWAIT, MT_HEADER);
if (m == NULL)
- return ENOBUFS;
+ return -1;
if (dst == 0) {
if (fr_ifpaddr(4, FRI_NORMAL, ifp,
@@ -853,6 +883,7 @@
dst4.s_addr = fin->fin_daddr;
hlen = sizeof(ip_t);
+ ohlen = fin->fin_hlen;
if (fin->fin_hlen < fin->fin_plen)
xtra = MIN(fin->fin_dlen, 8);
else
@@ -869,13 +900,13 @@
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == NULL)
- return ENOBUFS;
+ return -1;
MCLGET(m, M_DONTWAIT);
if (m == NULL)
- return ENOBUFS;
+ return -1;
avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
- xtra = MIN(fin->fin_plen + sizeof(ip6_t),
+ xtra = MIN(fin->fin_plen,
avail - hlen - sizeof(*icmp) - max_linkhdr);
if (dst == 0) {
if (fr_ifpaddr(6, FRI_NORMAL, ifp,
@@ -887,6 +918,8 @@
dst6 = fin->fin_dst6;
}
#endif
+ else
+ return -1;
iclen = hlen + sizeof(*icmp) + xtra;
avail -= (max_linkhdr + iclen);
@@ -898,13 +931,12 @@
m->m_pkthdr.len = iclen;
if (avail < 0) {
m_freem(m);
- return ENOBUFS;
+ return -1;
}
m->m_len = iclen;
ip = mtod(m, ip_t *);
icmp = (struct icmp *)((char *)ip + hlen);
ip2 = (ip_t *)&icmp->icmp_ip;
- bzero((char *)ip, iclen);
icmp->icmp_type = type;
icmp->icmp_code = fin->fin_icode;
@@ -915,7 +947,7 @@
icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
#endif
- bcopy((char *)fin->fin_ip, (char *)ip2, fin->fin_hlen);
+ bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
#if defined(M_CSUM_IPv4)
/*
@@ -928,7 +960,6 @@
ip6 = (ip6_t *)ip;
if (fin->fin_v == 6) {
ip62 = (ip6_t *)ip2;
- ip62->ip6_plen = htons(ip62->ip6_plen);
ip6->ip6_flow = 0;
ip6->ip6_plen = htons(iclen - hlen);
@@ -944,15 +975,13 @@
} else
#endif
{
- ip2->ip_len = htons(ip2->ip_len);
-
ip->ip_p = IPPROTO_ICMP;
ip->ip_src.s_addr = dst4.s_addr;
ip->ip_dst.s_addr = fin->fin_saddr;
if (xtra > 0)
- bcopy(fin->fin_dp,
- (char *)&icmp->icmp_ip + fin->fin_hlen, xtra);
+ bcopy((char *)fin->fin_ip + ohlen,
+ (char *)&icmp->icmp_ip + ohlen, xtra);
icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
sizeof(*icmp) + 8);
ip->ip_len = iclen;
@@ -1026,7 +1055,7 @@
dst->sin_addr = ip->ip_dst;
fr = fin->fin_fr;
- if (fdp)
+ if (fdp != NULL)
ifp = fdp->fd_ifp;
else
ifp = fin->fin_ifp;
@@ -1082,8 +1111,22 @@
(void) fr_checkstate(fin, &pass);
}
- (void) fr_checknatout(fin, NULL);
+
+ switch (fr_checknatout(fin, NULL))
+ {
+ case 0 :
+ break;
+ case 1 :
+ ip->ip_sum = 0;
+ break;
+ case -1 :
+ error = -1;
+ goto done;
+ break;
+ }
+
fin->fin_ifp = sifp;
+ fin->fin_out = 0;
} else
ip->ip_sum = 0;
/*
@@ -1238,7 +1281,7 @@
dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(struct sockaddr_in6);
- dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
+ dst6->sin6_addr = fin->fin_fi.fi_src.in6;
if (fdp != NULL)
ifp = fdp->fd_ifp;
@@ -1252,43 +1295,44 @@
if (IP6_NOTZERO(&fdp->fd_ip6))
dst6->sin6_addr = fdp->fd_ip6.in6;
}
- if (ifp == NULL)
- return EHOSTUNREACH;
- /* KAME */
- if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
- dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
rtalloc((struct route *)ro);
if ((ifp == NULL) && (ro->ro_rt != NULL))
ifp = ro->ro_rt->rt_ifp;
- if ((ro->ro_rt == NULL) || (ifp == NULL) ||
- (ifp != ro->ro_rt->rt_ifp)) {
+ if ((ro->ro_rt == NULL) || (ifp == NULL)) {
error = EHOSTUNREACH;
- } else {
+ goto bad;
+ }
Home |
Main Index |
Thread Index |
Old Index