*
* Version: $Id: ip_output.c,v 1.100 2002/02/01 22:01:03 davem Exp $
*
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
* Alan Cox, <Alan.Cox@linux.org>
#ifdef CONFIG_NETFILTER_DEBUG
nf_debug_ip_loopback_xmit(newskb);
#endif
+ nf_reset(newskb);
netif_rx(newskb);
return 0;
}
-static inline int ip_select_ttl(struct inet_opt *inet, struct dst_entry *dst)
+static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
{
int ttl = inet->uc_ttl;
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
u32 saddr, u32 daddr, struct ip_options *opt)
{
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct rtable *rt = (struct rtable *)skb->dst;
struct iphdr *iph;
nf_debug_ip_finish_output2(skb);
#endif /*CONFIG_NETFILTER_DEBUG*/
+#ifdef CONFIG_BRIDGE_NETFILTER
+ /* bridge-netfilter defers calling some IP hooks to the bridge layer
+ * and still needs the conntrack reference.
+ */
+ if (skb->nf_bridge == NULL)
+#endif
+ nf_reset(skb);
+
if (hh) {
int hh_alen;
newskb->dev, ip_dev_loopback_xmit);
}
- if (skb->len > dst_pmtu(&rt->u.dst))
+ if (skb->len > dst_mtu(&rt->u.dst))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_pmtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
{
struct sock *sk = skb->sk;
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct ip_options *opt = inet->opt;
struct rtable *rt;
struct iphdr *iph;
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(dst_pmtu(&rt->u.dst)));
+ htonl(dst_mtu(&rt->u.dst)));
kfree_skb(skb);
return -EMSGSIZE;
}
*/
hlen = iph->ihl * 4;
- mtu = dst_pmtu(&rt->u.dst) - hlen; /* Size of data space */
+ mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */
/* When frag_list is given, use it. First, check its validity:
* some transformers could create wrong frag_list or break existing
/* Partially cloned skb? */
if (skb_shared(frag))
goto slow_path;
+
+ BUG_ON(frag->sk);
+ if (skb->sk) {
+ sock_hold(skb->sk);
+ frag->sk = skb->sk;
+ frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
+ }
}
/* Everything is OK. Generate! */
skb->data_len = first_len - skb_headlen(skb);
skb->len = first_len;
iph->tot_len = htons(first_len);
- iph->frag_off |= htons(IP_MF);
+ iph->frag_off = htons(IP_MF);
ip_send_check(iph);
for (;;) {
/* Prepare header of the next frame,
* before previous one went down. */
if (frag) {
+ frag->ip_summed = CHECKSUM_NONE;
frag->h.raw = frag->data;
frag->nh.raw = __skb_push(frag, hlen);
memcpy(frag->nh.raw, iph, hlen);
struct ipcm_cookie *ipc, struct rtable *rt,
unsigned int flags)
{
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
struct ip_options *opt = NULL;
inet->cork.addr = ipc->addr;
}
dst_hold(&rt->u.dst);
- inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+ inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
inet->cork.rt = rt;
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
ssize_t ip_append_page(struct sock *sk, struct page *page,
int offset, size_t size, int flags)
{
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
struct rtable *rt;
struct ip_options *opt = NULL;
{
struct sk_buff *skb, *tmp_skb;
struct sk_buff **tail_skb;
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct ip_options *opt = NULL;
struct rtable *rt = inet->cork.rt;
struct iphdr *iph;
* If local_df is set too, we still allow to fragment this frame
* locally. */
if (inet->pmtudisc == IP_PMTUDISC_DO ||
- (!skb_shinfo(skb)->frag_list && ip_dont_fragment(sk, &rt->u.dst)))
+ (skb->len <= dst_mtu(&rt->u.dst) &&
+ ip_dont_fragment(sk, &rt->u.dst)))
df = htons(IP_DF);
if (inet->cork.flags & IPCORK_OPT)
*/
void ip_flush_pending_frames(struct sock *sk)
{
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
unsigned int len)
{
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct {
struct ip_options opt;
char data[40];