Several changes, mostly cosmetic:
* Add a KASSERT in ip_output(), we expect (at least) the IP header to be here. * In ip_fragment(), declare two variables instead of recomputing the values each time. Add an XXX for ipoff, it seems to me we should also remove IP_RF. * Rename the arguments of ip_optcopy(). * Style: use NULL for pointers, remove ()s for return statements, and add whitespaces for clarity. No real functional change.
This commit is contained in:
parent
64a90adb69
commit
ca56b5b05a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_output.c,v 1.292 2018/01/10 18:51:31 christos Exp $ */
|
||||
/* $NetBSD: ip_output.c,v 1.293 2018/02/06 17:08:18 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -29,7 +29,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.292 2018/01/10 18:51:31 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.293 2018/02/06 17:08:18 maxv Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -156,7 +156,7 @@ static int ip_ifaddrvalid(const struct in_ifaddr *);
|
|||
|
||||
extern pfil_head_t *inet_pfil_hook; /* XXX */
|
||||
|
||||
int ip_do_loopback_cksum = 0;
|
||||
int ip_do_loopback_cksum = 0;
|
||||
|
||||
static int
|
||||
ip_mark_mpls(struct ifnet * const ifp, struct mbuf * const m,
|
||||
|
@ -232,8 +232,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
struct ip *ip;
|
||||
struct ifnet *ifp, *mifp = NULL;
|
||||
struct mbuf *m = m0;
|
||||
int hlen = sizeof (struct ip);
|
||||
int len, error = 0;
|
||||
int len, hlen, error = 0;
|
||||
struct route iproute;
|
||||
const struct sockaddr_in *dst;
|
||||
struct in_ifaddr *ia = NULL;
|
||||
|
@ -262,11 +261,12 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) == 0);
|
||||
KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) !=
|
||||
(M_CSUM_TCPv4|M_CSUM_UDPv4));
|
||||
KASSERT(m->m_len >= sizeof(struct ip));
|
||||
|
||||
hlen = sizeof(struct ip);
|
||||
if (opt) {
|
||||
m = ip_insertoptions(m, opt, &len);
|
||||
if (len >= sizeof(struct ip))
|
||||
hlen = len;
|
||||
hlen = len;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
|
||||
|
@ -538,8 +538,8 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
}
|
||||
|
||||
/*
|
||||
* packets with Class-D address as source are not valid per
|
||||
* RFC 1112
|
||||
* Packets with Class-D address as source are not valid per
|
||||
* RFC1112.
|
||||
*/
|
||||
if (IN_MULTICAST(ip->ip_src.s_addr)) {
|
||||
IP_STATINC(IP_STAT_ODROPPED);
|
||||
|
@ -576,7 +576,6 @@ sendit:
|
|||
} else if ((m->m_pkthdr.csum_flags & M_CSUM_TSOv4) == 0) {
|
||||
ip->ip_id = ip_newid(ia);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TSO capable interfaces (typically?) increment
|
||||
* ip_id for each segment.
|
||||
|
@ -673,6 +672,7 @@ sendit:
|
|||
m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
|
||||
}
|
||||
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
|
||||
|
||||
/*
|
||||
* If small enough for mtu of path, or if using TCP segmentation
|
||||
* offload, can just send directly.
|
||||
|
@ -726,8 +726,7 @@ sendit:
|
|||
}
|
||||
|
||||
/*
|
||||
* We can't use HW checksumming if we're about to
|
||||
* fragment the packet.
|
||||
* We can't use HW checksumming if we're about to fragment the packet.
|
||||
*
|
||||
* XXX Some hardware can do this.
|
||||
*/
|
||||
|
@ -791,6 +790,7 @@ sendit:
|
|||
if (error == 0) {
|
||||
IP_STATINC(IP_STAT_FRAGMENTED);
|
||||
}
|
||||
|
||||
done:
|
||||
ia4_release(ia, &psref_ia);
|
||||
rtcache_unref(rt, ro);
|
||||
|
@ -803,6 +803,7 @@ done:
|
|||
if (bind_need_restore)
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
|
||||
bad:
|
||||
m_freem(m);
|
||||
goto done;
|
||||
|
@ -819,16 +820,24 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
|
|||
int sw_csum = m->m_pkthdr.csum_flags;
|
||||
int fragments = 0;
|
||||
int error = 0;
|
||||
int ipoff;
|
||||
bool mff;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
hlen = ip->ip_hl << 2;
|
||||
|
||||
/* XXX: Why don't we remove IP_RF? */
|
||||
ipoff = ntohs(ip->ip_off) & ~IP_MF;
|
||||
|
||||
mff = (ip->ip_off & htons(IP_MF)) != 0;
|
||||
|
||||
if (ifp != NULL)
|
||||
sw_csum &= ~ifp->if_csum_flags_tx;
|
||||
|
||||
len = (mtu - hlen) &~ 7;
|
||||
if (len < 8) {
|
||||
m_freem(m);
|
||||
return (EMSGSIZE);
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
firstlen = len;
|
||||
|
@ -839,45 +848,52 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
|
|||
* make new header and copy data of each part and link onto chain.
|
||||
*/
|
||||
m0 = m;
|
||||
mhlen = sizeof (struct ip);
|
||||
mhlen = sizeof(struct ip);
|
||||
for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
|
||||
MGETHDR(m, M_DONTWAIT, MT_HEADER);
|
||||
if (m == 0) {
|
||||
if (m == NULL) {
|
||||
error = ENOBUFS;
|
||||
IP_STATINC(IP_STAT_ODROPPED);
|
||||
goto sendorfree;
|
||||
}
|
||||
MCLAIM(m, m0->m_owner);
|
||||
|
||||
*mnext = m;
|
||||
mnext = &m->m_nextpkt;
|
||||
|
||||
m->m_data += max_linkhdr;
|
||||
mhip = mtod(m, struct ip *);
|
||||
*mhip = *ip;
|
||||
|
||||
/* we must inherit MCAST and BCAST flags */
|
||||
m->m_flags |= m0->m_flags & (M_MCAST|M_BCAST);
|
||||
if (hlen > sizeof (struct ip)) {
|
||||
mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
||||
|
||||
if (hlen > sizeof(struct ip)) {
|
||||
mhlen = ip_optcopy(ip, mhip) + sizeof(struct ip);
|
||||
mhip->ip_hl = mhlen >> 2;
|
||||
}
|
||||
m->m_len = mhlen;
|
||||
mhip->ip_off = ((off - hlen) >> 3) +
|
||||
(ntohs(ip->ip_off) & ~IP_MF);
|
||||
if (ip->ip_off & htons(IP_MF))
|
||||
|
||||
mhip->ip_off = ((off - hlen) >> 3) + ipoff;
|
||||
if (mff)
|
||||
mhip->ip_off |= IP_MF;
|
||||
if (off + len >= ntohs(ip->ip_len))
|
||||
len = ntohs(ip->ip_len) - off;
|
||||
else
|
||||
mhip->ip_off |= IP_MF;
|
||||
HTONS(mhip->ip_off);
|
||||
|
||||
mhip->ip_len = htons((u_int16_t)(len + mhlen));
|
||||
m->m_next = m_copym(m0, off, len, M_DONTWAIT);
|
||||
if (m->m_next == 0) {
|
||||
error = ENOBUFS; /* ??? */
|
||||
if (m->m_next == NULL) {
|
||||
error = ENOBUFS;
|
||||
IP_STATINC(IP_STAT_ODROPPED);
|
||||
goto sendorfree;
|
||||
}
|
||||
|
||||
m->m_pkthdr.len = mhlen + len;
|
||||
m_reset_rcvif(m);
|
||||
|
||||
mhip->ip_sum = 0;
|
||||
KASSERT((m->m_pkthdr.csum_flags & M_CSUM_IPv4) == 0);
|
||||
if (sw_csum & M_CSUM_IPv4) {
|
||||
|
@ -896,6 +912,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
|
|||
IP_STATINC(IP_STAT_OFRAGMENTS);
|
||||
fragments++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update first fragment by trimming what's been copied out
|
||||
* and updating header, then send each fragment (in order).
|
||||
|
@ -918,6 +935,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
|
|||
KASSERT(M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data) >=
|
||||
sizeof(struct ip));
|
||||
}
|
||||
|
||||
sendorfree:
|
||||
/*
|
||||
* If there is no room for all the fragments, don't queue
|
||||
|
@ -940,7 +958,8 @@ sendorfree:
|
|||
m_freem(m);
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -974,7 +993,6 @@ in_delayed_cksum(struct mbuf *m)
|
|||
* Determine the maximum length of the options to be inserted;
|
||||
* we would far rather allocate too much space rather than too little.
|
||||
*/
|
||||
|
||||
u_int
|
||||
ip_optlen(struct inpcb *inp)
|
||||
{
|
||||
|
@ -1001,13 +1019,13 @@ ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen)
|
|||
|
||||
optlen = opt->m_len - sizeof(p->ipopt_dst);
|
||||
if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET)
|
||||
return (m); /* XXX should fail */
|
||||
return m; /* XXX should fail */
|
||||
if (!in_nullhost(p->ipopt_dst))
|
||||
ip->ip_dst = p->ipopt_dst;
|
||||
if (M_READONLY(m) || M_LEADINGSPACE(m) < optlen) {
|
||||
MGETHDR(n, M_DONTWAIT, MT_HEADER);
|
||||
if (n == 0)
|
||||
return (m);
|
||||
if (n == NULL)
|
||||
return m;
|
||||
MCLAIM(n, m->m_owner);
|
||||
M_MOVE_PKTHDR(n, m);
|
||||
m->m_len -= sizeof(struct ip);
|
||||
|
@ -1027,22 +1045,22 @@ ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen)
|
|||
bcopy((void *)p->ipopt_list, (void *)(ip + 1), (unsigned)optlen);
|
||||
*phlen = sizeof(struct ip) + optlen;
|
||||
ip->ip_len = htons(ntohs(ip->ip_len) + optlen);
|
||||
return (m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy options from ip to jp,
|
||||
* omitting those not copied during fragmentation.
|
||||
* Copy options from ipsrc to ipdst, omitting those not copied during
|
||||
* fragmentation.
|
||||
*/
|
||||
int
|
||||
ip_optcopy(struct ip *ip, struct ip *jp)
|
||||
ip_optcopy(struct ip *ipsrc, struct ip *ipdst)
|
||||
{
|
||||
u_char *cp, *dp;
|
||||
int opt, optlen, cnt;
|
||||
|
||||
cp = (u_char *)(ip + 1);
|
||||
dp = (u_char *)(jp + 1);
|
||||
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
|
||||
cp = (u_char *)(ipsrc + 1);
|
||||
dp = (u_char *)(ipdst + 1);
|
||||
cnt = (ipsrc->ip_hl << 2) - sizeof(struct ip);
|
||||
for (; cnt > 0; cnt -= optlen, cp += optlen) {
|
||||
opt = cp[0];
|
||||
if (opt == IPOPT_EOL)
|
||||
|
@ -1066,9 +1084,12 @@ ip_optcopy(struct ip *ip, struct ip *jp)
|
|||
dp += optlen;
|
||||
}
|
||||
}
|
||||
for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
|
||||
|
||||
for (optlen = dp - (u_char *)(ipdst+1); optlen & 0x3; optlen++) {
|
||||
*dp++ = IPOPT_EOL;
|
||||
return (optlen);
|
||||
}
|
||||
|
||||
return optlen;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1560,12 +1581,12 @@ ip_pcbopts(struct inpcb *inp, const struct sockopt *sopt)
|
|||
|
||||
#ifndef __vax__
|
||||
if (cnt % sizeof(int32_t))
|
||||
return (EINVAL);
|
||||
return EINVAL;
|
||||
#endif
|
||||
|
||||
m = m_get(M_DONTWAIT, MT_SOOPTS);
|
||||
if (m == NULL)
|
||||
return (ENOBUFS);
|
||||
return ENOBUFS;
|
||||
|
||||
dp = mtod(m, u_char *);
|
||||
memset(dp, 0, sizeof(struct in_addr));
|
||||
|
@ -1645,6 +1666,7 @@ ip_pcbopts(struct inpcb *inp, const struct sockopt *sopt)
|
|||
|
||||
inp->inp_options = m;
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
(void)m_free(m);
|
||||
return EINVAL;
|
||||
|
|
Loading…
Reference in New Issue