patch-2.1.68 linux/net/ipv4/ip_output.c
Next file: linux/net/ipv4/ip_sockglue.c
Previous file: linux/net/ipv4/ip_options.c
Back to the patch index
Back to the overall index
- Lines: 276
- Date:
Sun Nov 30 14:00:39 1997
- Orig file:
v2.1.67/linux/net/ipv4/ip_output.c
- Orig date:
Thu Sep 4 17:07:32 1997
diff -u --recursive --new-file v2.1.67/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
@@ -5,7 +5,7 @@
*
* The Internet Protocol (IP) output module.
*
- * Version: @(#)ip.c 1.0.16b 9/1/93
+ * Version: $Id: ip_output.c,v 1.40 1997/10/12 17:01:48 kuznet Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -67,7 +67,7 @@
#include <linux/ip_fw.h>
#include <linux/firewall.h>
#include <linux/mroute.h>
-#include <net/netlink.h>
+#include <linux/netlink.h>
#include <linux/ipsec.h>
static void __inline__ ip_ll_header_reserve(struct sk_buff *skb)
@@ -92,7 +92,7 @@
daddr = opt->faddr;
err = ip_route_output(&rt, daddr, saddr, RT_TOS(sk->ip_tos) |
- (sk->localroute||0), NULL);
+ (sk->localroute||0), sk->bound_dev_if);
if (err)
{
ip_statistics.IpOutNoRoutes++;
@@ -130,7 +130,7 @@
iph->tos = sk->ip_tos;
iph->frag_off = 0;
if (sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
- !(rt->rt_flags & RTF_NOPMTUDISC))
+ !(rt->rt_flags & RTCF_NOPMTUDISC))
iph->frag_off |= htons(IP_DF);
iph->ttl = sk->ip_ttl;
iph->daddr = rt->rt_dst;
@@ -143,8 +143,7 @@
{
iph->ihl += opt->optlen>>2;
skb->h.raw += opt->optlen;
- ip_options_build(skb, opt, final_daddr,
- rt->u.dst.dev->pa_addr, 0);
+ ip_options_build(skb, opt, final_daddr, rt, 0);
}
ip_rt_put(rt);
@@ -170,9 +169,10 @@
rt = (struct rtable*)sk->dst_cache;
if (!rt || rt->u.dst.obsolete) {
+ sk->dst_cache = NULL;
ip_rt_put(rt);
err = ip_route_output(&rt, daddr, sk->saddr, RT_TOS(sk->ip_tos) |
- (sk->localroute||0), NULL);
+ (sk->localroute||0), sk->bound_dev_if);
if (err)
return err;
sk->dst_cache = &rt->u.dst;
@@ -210,7 +210,7 @@
iph->tos = sk->ip_tos;
iph->frag_off = 0;
if (sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
- !(rt->rt_flags & RTF_NOPMTUDISC))
+ !(rt->rt_flags & RTCF_NOPMTUDISC))
iph->frag_off |= htons(IP_DF);
iph->ttl = sk->ip_ttl;
iph->daddr = rt->rt_dst;
@@ -223,7 +223,7 @@
return 0;
iph->ihl += opt->optlen>>2;
skb->h.raw += opt->optlen;
- ip_options_build(skb, opt, final_daddr, rt->u.dst.dev->pa_addr, 0);
+ ip_options_build(skb, opt, final_daddr, rt, 0);
return 0;
}
@@ -242,17 +242,35 @@
#ifdef CONFIG_IP_ACCT
ip_fw_chk(skb->nh.iph, skb->dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
#endif
-
+#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags & RTCF_NAT)
ip_do_nat(skb);
+#endif
/*
* Multicasts are looped back for other local users
*/
-
- if (rt->rt_flags&RTF_MULTICAST && !(dev->flags&IFF_LOOPBACK)) {
- if (sk==NULL || sk->ip_mc_loop)
- dev_loopback_xmit(skb);
+
+ if (rt->rt_flags&RTCF_MULTICAST && (!sk || sk->ip_mc_loop)) {
+#ifndef CONFIG_IP_MROUTE
+#if 1
+ /* It should never occur. Delete it eventually. --ANK */
+ if (!(rt->rt_flags&RTCF_LOCAL) || (dev->flags&IFF_LOOPBACK))
+ printk(KERN_DEBUG "ip_mc_output (mc): it should never occur\n");
+ else
+#endif
+#else
+ /* Small optimization: do not loopback not local frames,
+ which returned after forwarding; they will be dropped
+ by ip_mr_input in any case.
+ Note, that local frames are looped back to be delivered
+ to local recipients.
+
+ This check is duplicated in ip_mr_input at the moment.
+ */
+ if ((rt->rt_flags&RTCF_LOCAL) || !(IPCB(skb)->flags&IPSKB_FORWARDED))
+#endif
+ dev_loopback_xmit(skb);
/* Multicasts with ttl 0 must not go beyond the host */
@@ -262,9 +280,15 @@
}
}
- if ((rt->rt_flags&(RTF_LOCAL|RTF_BROADCAST)) == (RTF_LOCAL|RTF_BROADCAST) &&
- !(dev->flags&IFF_LOOPBACK))
+ if (rt->rt_flags&RTCF_BROADCAST) {
+#if 1
+ /* It should never occur. Delete it eventually. --ANK */
+ if (!(rt->rt_flags&RTCF_LOCAL) || (dev->flags&IFF_LOOPBACK))
+ printk(KERN_DEBUG "ip_mc_output (brd): it should never occur!\n");
+ else
+#endif
dev_loopback_xmit(skb);
+ }
if (dev->flags & IFF_UP) {
dev_queue_xmit(skb);
@@ -291,8 +315,10 @@
ip_fw_chk(skb->nh.iph, skb->dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
#endif
+#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags&RTCF_NAT)
ip_do_nat(skb);
+#endif
if (dev->flags & IFF_UP) {
dev_queue_xmit(skb);
@@ -431,8 +457,7 @@
*/
{
struct rtable *nrt;
- if (ip_route_output(&nrt, rt->key.dst, rt->key.src,
- rt->key.tos, NULL)) {
+ if (ip_route_output(&nrt, rt->key.dst, rt->key.src, rt->key.tos, sk?sk->bound_dev_if:0)) {
kfree_skb(skb, 0);
return;
}
@@ -500,14 +525,13 @@
int hh_len = rt->u.dst.dev->hard_header_len;
int nfrags=0;
struct ip_options *opt = ipc->opt;
- struct device *dev = rt->u.dst.dev;
int df = htons(IP_DF);
#ifdef CONFIG_NET_SECURITY
int fw_res;
#endif
if (sk->ip_pmtudisc == IP_PMTUDISC_DONT ||
- rt->rt_flags&RTF_NOPMTUDISC)
+ rt->rt_flags&RTCF_NOPMTUDISC)
df = 0;
@@ -546,7 +570,7 @@
iph->id=htons(ip_id_count++);
iph->frag_off = df;
iph->ttl=sk->ip_mc_ttl;
- if (!(rt->rt_flags&RTF_MULTICAST))
+ if (rt->rt_type != RTN_MULTICAST)
iph->ttl=sk->ip_ttl;
iph->protocol=sk->protocol;
iph->saddr=rt->rt_src;
@@ -695,14 +719,14 @@
if (opt) {
iph->ihl += opt->optlen>>2;
ip_options_build(skb, opt,
- ipc->addr, dev->pa_addr, offset);
+ ipc->addr, rt, offset);
}
iph->tos = sk->ip_tos;
iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4);
iph->id = id;
iph->frag_off = htons(offset>>3);
iph->frag_off |= mf|df;
- if (rt->rt_flags&RTF_MULTICAST)
+ if (rt->rt_type == RTN_MULTICAST)
iph->ttl = sk->ip_mc_ttl;
else
iph->ttl = sk->ip_ttl;
@@ -966,7 +990,7 @@
if (ipc.opt->srr)
daddr = replyopts.opt.faddr;
- if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), NULL))
+ if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
return NULL;
iphlen = sizeof(struct iphdr) + replyopts.opt.optlen;
@@ -1000,7 +1024,7 @@
iph->saddr = rt->rt_src;
iph->protocol = skb->nh.iph->protocol;
- ip_options_build(reply, &replyopts.opt, daddr, rt->u.dst.dev->pa_addr, 0);
+ ip_options_build(reply, &replyopts.opt, daddr, rt, 0);
return reply;
}
@@ -1019,43 +1043,16 @@
};
-/*
- * Device notifier
- */
-
-static int ip_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
- struct device *dev=ptr;
-
- if (dev->family != AF_INET)
- return NOTIFY_DONE;
-
- if(event==NETDEV_UP)
- {
- /*
- * Join the initial group if multicast.
- */
- ip_mc_allhost(dev);
- }
- if(event==NETDEV_DOWN)
- ip_mc_drop_device(dev);
-
- return ip_rt_event(event, dev);
-}
-
-struct notifier_block ip_netdev_notifier={
- ip_netdev_event,
- NULL,
- 0
-};
#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_MULTICAST
static struct proc_dir_entry proc_net_igmp = {
PROC_NET_IGMP, 4, "igmp",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
ip_mc_procinfo
};
+#endif
#endif
/*
@@ -1068,11 +1065,10 @@
ip_rt_init();
- /* So we flush routes and multicast lists when a device is downed */
- register_netdevice_notifier(&ip_netdev_notifier);
-
#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_MULTICAST
proc_net_register(&proc_net_igmp);
+#endif
#endif
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov