summaryrefslogtreecommitdiff
path: root/packages/linux-kernel/patches/kernel/0001-linkstate-ip-device-attribute.patch
blob: 2be1a3c8dca31827eec61dd555112dd4a2f44883 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
From 388b9bc4dc78cbc83c6476d765f6e0c3d3ed1fb4 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 29 Apr 2013 18:50:15 -0700
Subject: [PATCH] VyOS: Add linkstate IP device attribute

Backport of earlier Vyatta patch.

(cherry picked from commit 7c5a851086686be14ae937c80d6cee34814dbefc)

---
 Documentation/networking/ip-sysctl.txt | 13 +++++++++++++
 include/linux/inetdevice.h             |  1 +
 include/linux/ipv6.h                   |  1 +
 include/uapi/linux/ip.h                |  1 +
 include/uapi/linux/ipv6.h              |  1 +
 net/ipv4/devinet.c                     |  2 ++
 net/ipv6/addrconf.c                    |  9 +++++++++
 net/ipv6/route.c                       | 11 +++++++++++
 8 files changed, 39 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 8af3771a3ebf..93408cc52991 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1245,6 +1245,19 @@ rp_filter - INTEGER
 	Default value is 0. Note that some distributions enable it
 	in startup scripts.
 
+link_filter - INTEGER
+        0 - Allow packets to be received for the address on this interface
+	even if interface is disabled or no carrier.
+
+	1 - Ignore packets received if interface associated with the incoming
+	address is down.
+
+	2 - Ignore packets received if interface associated with the incoming
+	address is down or has no carrier.
+
+	Default value is 0. Note that some distributions enable it
+	in startup scripts.
+
 arp_filter - BOOLEAN
 	1 - Allows you to have multiple network interfaces on the same
 	subnet, and have the ARPs for each interface be answered
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 3515ca64e638..dcae58193580 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -133,6 +133,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
 #define IN_DEV_ARP_NOTIFY(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
+#define IN_DEV_LINKFILTER(in_dev)	IN_DEV_MAXCONF((in_dev), LINKFILTER)
 
 struct in_ifaddr {
 	struct hlist_node	hash;
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ea7c7906591e..57f656ea2783 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -76,6 +76,7 @@ struct ipv6_devconf {
 	__s32           ndisc_tclass;
 
 	struct ctl_table_header *sysctl_header;
+	__s32		link_filter;	/* VyOS */
 };
 
 struct ipv6_params {
diff --git a/include/uapi/linux/ip.h b/include/uapi/linux/ip.h
index e42d13b55cf3..baf8e77c201b 100644
--- a/include/uapi/linux/ip.h
+++ b/include/uapi/linux/ip.h
@@ -169,6 +169,7 @@ enum
 	IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
 	IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
 	IPV4_DEVCONF_BC_FORWARDING,
+	IPV4_DEVCONF_LINKFILTER,	/* VyOS only */
 	__IPV4_DEVCONF_MAX
 };
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index 9c0f4a92bcff..619edd130cfd 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -187,6 +187,7 @@ enum {
 	DEVCONF_DISABLE_POLICY,
 	DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
 	DEVCONF_NDISC_TCLASS,
+	DEVCONF_LINK_FILTER,
 	DEVCONF_MAX
 };
 
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a27d034c85cc..b62b62abe907 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2550,6 +2550,8 @@ static struct devinet_sysctl_table {
 					      "route_localnet"),
 		DEVINET_SYSCTL_FLUSHING_ENTRY(DROP_UNICAST_IN_L2_MULTICAST,
 					      "drop_unicast_in_l2_multicast"),
+		/* VyOS */
+		DEVINET_SYSCTL_RW_ENTRY(LINKFILTER, "link_filter"),
 	},
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 635b2482fa20..ce1405ecf6f6 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -5477,6 +5477,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
 	array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
 	array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
 	array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass;
+	array[DEVCONF_LINK_FILTER] = cnf->link_filter;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -6849,6 +6850,14 @@ static const struct ctl_table addrconf_sysctl[] = {
 		.mode           = 0644,
 		.proc_handler   = addrconf_sysctl_disable_policy,
 	},
+	/* VyOS */
+	{
+		.procname	= "link_filter",
+		.data		= &ipv6_devconf.link_filter,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
 	{
 		.procname	= "ndisc_tclass",
 		.data		= &ipv6_devconf.ndisc_tclass,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 46df6345bb99..2b930a2c4fdb 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -686,6 +686,15 @@ static inline void rt6_probe(struct fib6_nh *fib6_nh)
 }
 #endif
 
+static inline int rt6_link_filter(const struct fib6_nh *nh)
+{
+	const struct net_device *dev = nh->fib_nh_dev;
+	int linkf = __in6_dev_get(dev)->cnf.link_filter;
+
+	return (linkf && !netif_running(dev))
+	    || (linkf > 1 && !netif_carrier_ok(dev));
+}
+
 /*
  * Default Router Selection (RFC 2461 6.3.6)
  */
@@ -727,6 +736,8 @@ static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
 
 	if (!m && (strict & RT6_LOOKUP_F_IFACE))
 		return RT6_NUD_FAIL_HARD;
+	if (rt6_link_filter(nh))
+		return -1;
 #ifdef CONFIG_IPV6_ROUTER_PREF
 	m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(fib6_flags)) << 2;
 #endif
-- 
2.20.1