diff options
| author | itojun <itojun@NetBSD.org> | 2000-06-30 16:44:33 +0000 |
|---|---|---|
| committer | itojun <itojun@NetBSD.org> | 2000-06-30 16:44:33 +0000 |
| commit | 23f6a4f4e8109fc71bcbe7e2df1acad3f910af04 (patch) | |
| tree | 226fa620e4cea52e2b7fc74b369f756b26f771e1 /sys/netinet | |
| parent | 5f9b72f44c25b72f6eea70f98e8eb8bb5d8ce26e (diff) | |
remove old mbuf assumption (ip header and tcp header are on the same mbuf).
this is for m_pulldown use. (sync with kame)
Diffstat (limited to 'sys/netinet')
| -rw-r--r-- | sys/netinet/tcp_input.c | 47 | ||||
| -rw-r--r-- | sys/netinet/tcp_output.c | 4 | ||||
| -rw-r--r-- | sys/netinet/tcp_subr.c | 75 |
3 files changed, 100 insertions, 26 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 6d31f7fe990..16b9c293d40 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_input.c,v 1.108 2000/05/05 15:05:29 matt Exp $ */ +/* $NetBSD: tcp_input.c,v 1.109 2000/06/30 16:44:33 itojun Exp $ */ /* %%% portions-copyright-nrl-95 @@ -1026,14 +1026,31 @@ findpcb: if (so->so_options & SO_DEBUG) { ostate = tp->t_state; - tcp_saveti = m_copym(m, 0, iphlen, M_DONTWAIT); + + tcp_saveti = NULL; + if (iphlen + sizeof(struct tcphdr) > MHLEN) + goto nosave; + + if (m->m_len > iphlen && (m->m_flags & M_EXT) == 0) { + tcp_saveti = m_copym(m, 0, iphlen, M_DONTWAIT); + if (!tcp_saveti) + goto nosave; + } else { + MGETHDR(tcp_saveti, M_DONTWAIT, MT_HEADER); + if (!tcp_saveti) + goto nosave; + tcp_saveti->m_len = iphlen; + m_copydata(m, 0, iphlen, + mtod(tcp_saveti, caddr_t)); + } + if (M_TRAILINGSPACE(tcp_saveti) < sizeof(struct tcphdr)) { m_freem(tcp_saveti); tcp_saveti = NULL; } else { tcp_saveti->m_len += sizeof(struct tcphdr); bcopy(th, mtod(tcp_saveti, caddr_t) + iphlen, - sizeof(struct tcphdr)); + sizeof(struct tcphdr)); } if (tcp_saveti) { /* @@ -1053,6 +1070,7 @@ findpcb: #endif } } + nosave:; } if (so->so_options & SO_ACCEPTCONN) { if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) { @@ -3346,18 +3364,20 @@ syn_cache_respond(sc, m) tlen = hlen + sizeof(struct tcphdr) + optlen; /* - * Create the IP+TCP header from scratch. Reuse the received mbuf - * if possible. + * Create the IP+TCP header from scratch. */ - if (m != NULL) { - m_freem(m->m_next); - m->m_next = NULL; - MRESETDATA(m); - } else { - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - return (ENOBUFS); + if (m) + m_freem(m); + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m && tlen > MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == NULL) { + m_freem(m); + m = NULL; + } } + if (m == NULL) + return (ENOBUFS); /* Fixup the mbuf. */ m->m_data += max_linkhdr; @@ -3380,6 +3400,7 @@ syn_cache_respond(sc, m) ipsec_setsocket(m, so); } #endif + m->m_pkthdr.rcvif = NULL; memset(mtod(m, u_char *), 0, tlen); switch (sc->sc_src.sa.sa_family) { diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index e9d670eda02..0875874f0ab 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_output.c,v 1.56 2000/03/30 13:25:06 augustss Exp $ */ +/* $NetBSD: tcp_output.c,v 1.57 2000/06/30 16:44:33 itojun Exp $ */ /* %%% portions-copyright-nrl-95 @@ -703,7 +703,7 @@ send: m->m_len += len; } else { m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); - if (m->m_next == 0) { + if (m->m_next == NULL) { m_freem(m); error = ENOBUFS; goto out; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 388b7dfb91d..47a1916bec1 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_subr.c,v 1.91 2000/03/30 13:25:07 augustss Exp $ */ +/* $NetBSD: tcp_subr.c,v 1.92 2000/06/30 16:44:34 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -449,39 +449,85 @@ tcp_respond(tp, template, m, th0, ack, seq, flags) } flags = TH_ACK; } else { + + if ((m->m_flags & M_PKTHDR) == 0) { +#if 0 + printf("non PKTHDR to tcp_respond\n"); +#endif + m_freem(m); + return EINVAL; + } +#ifdef DIAGNOSTIC + if (!th0) + panic("th0 == NULL in tcp_respond"); +#endif + /* get family information from m */ switch (mtod(m, struct ip *)->ip_v) { case 4: family = AF_INET; hlen = sizeof(struct ip); + ip = mtod(m, struct ip *); break; #ifdef INET6 case 6: family = AF_INET6; hlen = sizeof(struct ip6_hdr); + ip6 = mtod(m, struct ip6_hdr *); break; #endif default: m_freem(m); return EAFNOSUPPORT; } + if ((flags & TH_SYN) == 0 || sizeof(*th0) > (th0->th_off << 2)) + tlen = sizeof(*th0); + else + tlen = th0->th_off << 2; + + if (m->m_len > hlen + tlen && (m->m_flags & M_EXT) == 0 && + mtod(m, caddr_t) + hlen == (caddr_t)th0) { + m->m_len = hlen + tlen; + m_freem(m->m_next); + m->m_next = NULL; + } else { + struct mbuf *n; + +#ifdef DIAGNOSTIC + if (max_linkhdr + hlen + tlen > MCLBYTES) { + m_freem(m); + return EMSGSIZE; + } +#endif + MGETHDR(n, M_DONTWAIT, MT_HEADER); + if (n && max_linkhdr + hlen + tlen > MHLEN) { + MCLGET(n, M_DONTWAIT); + if ((n->m_flags & M_EXT) == 0) { + m_freem(n); + n = NULL; + } + } + if (!n) { + m_freem(m); + return ENOBUFS; + } + + n->m_data += max_linkhdr; + n->m_len = hlen + tlen; + m_copyback(n, 0, hlen, mtod(m, caddr_t)); + m_copyback(n, hlen, tlen, (caddr_t)th0); - /* template pointer almost has no meaning */ - m_freem(m->m_next); - m->m_next = 0; - m->m_len = hlen + sizeof(struct tcphdr); - if ((m->m_flags & M_PKTHDR) == 0) { - printf("non PKTHDR to tcp_respond\n"); m_freem(m); - return EINVAL; + m = n; + n = NULL; } - tlen = 0; #define xchg(a,b,type) { type t; t=a; a=b; b=t; } switch (family) { case AF_INET: ip = mtod(m, struct ip *); th = (struct tcphdr *)(ip + 1); + ip->ip_p = IPPROTO_TCP; xchg(ip->ip_dst, ip->ip_src, struct in_addr); ip->ip_p = IPPROTO_TCP; break; @@ -489,14 +535,21 @@ tcp_respond(tp, template, m, th0, ack, seq, flags) case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); th = (struct tcphdr *)(ip6 + 1); + ip6->ip6_nxt = IPPROTO_TCP; xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); ip6->ip6_nxt = IPPROTO_TCP; break; #endif +#if 0 + default: + /* noone will visit here */ + m_freem(m); + return EAFNOSUPPORT; +#endif } - *th = *th0; xchg(th->th_dport, th->th_sport, u_int16_t); #undef xchg + tlen = 0; /*be friendly with the following code*/ } th->th_seq = htonl(seq); th->th_ack = htonl(ack); @@ -508,7 +561,7 @@ tcp_respond(tp, template, m, th0, ack, seq, flags) win = TCP_MAXWIN; th->th_win = htons((u_int16_t)win); th->th_off = sizeof (struct tcphdr) >> 2; - tlen += sizeof (struct tcphdr); + tlen += sizeof(*th); } else tlen += th->th_off << 2; m->m_len = hlen + tlen; |
