Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4d99775f
Commit
4d99775f
authored
Feb 17, 2004
by
Julian Anastasov
Committed by
David S. Miller
Feb 17, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl.
parent
b654ac17
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
151 additions
and
3 deletions
+151
-3
Documentation/networking/ip-sysctl.txt
Documentation/networking/ip-sysctl.txt
+18
-0
include/linux/inetdevice.h
include/linux/inetdevice.h
+3
-0
include/linux/sysctl.h
include/linux/sysctl.h
+1
-0
net/ipv4/arp.c
net/ipv4/arp.c
+42
-2
net/ipv4/devinet.c
net/ipv4/devinet.c
+87
-1
No files found.
Documentation/networking/ip-sysctl.txt
View file @
4d99775f
...
@@ -530,6 +530,24 @@ arp_announce - INTEGER
...
@@ -530,6 +530,24 @@ arp_announce - INTEGER
receiving answer from the resolved target while decreasing
receiving answer from the resolved target while decreasing
the level announces more valid sender's information.
the level announces more valid sender's information.
arp_ignore - INTEGER
Define different modes for sending replies in response to
received ARP requests that resolve local target IP addresses:
0 - (default): reply for any local target IP address, configured
on any interface
1 - reply only if the target IP address is local address
configured on the incoming interface
2 - reply only if the target IP address is local address
configured on the incoming interface and both with the
sender's IP address are part from same subnet on this interface
3 - do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied
4-7 - reserved
8 - do not reply for all local addresses
The max value from conf/{all,interface}/arp_ignore is used
when ARP request is received on the {interface}
tag - INTEGER
tag - INTEGER
Allows you to write a number, which can be used as required.
Allows you to write a number, which can be used as required.
Default value is 0.
Default value is 0.
...
...
include/linux/inetdevice.h
View file @
4d99775f
...
@@ -19,6 +19,7 @@ struct ipv4_devconf
...
@@ -19,6 +19,7 @@ struct ipv4_devconf
int
tag
;
int
tag
;
int
arp_filter
;
int
arp_filter
;
int
arp_announce
;
int
arp_announce
;
int
arp_ignore
;
int
medium_id
;
int
medium_id
;
int
no_xfrm
;
int
no_xfrm
;
int
no_policy
;
int
no_policy
;
...
@@ -73,6 +74,7 @@ struct in_device
...
@@ -73,6 +74,7 @@ struct in_device
#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
#define IN_DEV_ARP_IGNORE(in_dev) (max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
struct
in_ifaddr
struct
in_ifaddr
{
{
...
@@ -99,6 +101,7 @@ extern void devinet_init(void);
...
@@ -99,6 +101,7 @@ extern void devinet_init(void);
extern
struct
in_device
*
inetdev_init
(
struct
net_device
*
dev
);
extern
struct
in_device
*
inetdev_init
(
struct
net_device
*
dev
);
extern
struct
in_device
*
inetdev_by_index
(
int
);
extern
struct
in_device
*
inetdev_by_index
(
int
);
extern
u32
inet_select_addr
(
const
struct
net_device
*
dev
,
u32
dst
,
int
scope
);
extern
u32
inet_select_addr
(
const
struct
net_device
*
dev
,
u32
dst
,
int
scope
);
extern
u32
inet_confirm_addr
(
const
struct
net_device
*
dev
,
u32
dst
,
u32
local
,
int
scope
);
extern
struct
in_ifaddr
*
inet_ifa_byprefix
(
struct
in_device
*
in_dev
,
u32
prefix
,
u32
mask
);
extern
struct
in_ifaddr
*
inet_ifa_byprefix
(
struct
in_device
*
in_dev
,
u32
prefix
,
u32
mask
);
extern
void
inet_forward_change
(
void
);
extern
void
inet_forward_change
(
void
);
...
...
include/linux/sysctl.h
View file @
4d99775f
...
@@ -363,6 +363,7 @@ enum
...
@@ -363,6 +363,7 @@ enum
NET_IPV4_CONF_NOPOLICY
=
16
,
NET_IPV4_CONF_NOPOLICY
=
16
,
NET_IPV4_CONF_FORCE_IGMP_VERSION
=
17
,
NET_IPV4_CONF_FORCE_IGMP_VERSION
=
17
,
NET_IPV4_CONF_ARP_ANNOUNCE
=
18
,
NET_IPV4_CONF_ARP_ANNOUNCE
=
18
,
NET_IPV4_CONF_ARP_IGNORE
=
19
,
};
};
/* /proc/sys/net/ipv4/netfilter */
/* /proc/sys/net/ipv4/netfilter */
...
...
net/ipv4/arp.c
View file @
4d99775f
...
@@ -379,6 +379,42 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
...
@@ -379,6 +379,42 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
read_unlock_bh
(
&
neigh
->
lock
);
read_unlock_bh
(
&
neigh
->
lock
);
}
}
static
int
arp_ignore
(
struct
in_device
*
in_dev
,
struct
net_device
*
dev
,
u32
sip
,
u32
tip
)
{
int
scope
;
switch
(
IN_DEV_ARP_IGNORE
(
in_dev
))
{
case
0
:
/* Reply, the tip is already validated */
return
0
;
case
1
:
/* Reply only if tip is configured on the incoming interface */
sip
=
0
;
scope
=
RT_SCOPE_HOST
;
break
;
case
2
:
/*
* Reply only if tip is configured on the incoming interface
* and is in same subnet as sip
*/
scope
=
RT_SCOPE_HOST
;
break
;
case
3
:
/* Do not reply for scope host addresses */
sip
=
0
;
scope
=
RT_SCOPE_LINK
;
dev
=
NULL
;
break
;
case
4
:
/* Reserved */
case
5
:
case
6
:
case
7
:
return
0
;
case
8
:
/* Do not reply */
return
1
;
default:
return
0
;
}
return
!
inet_confirm_addr
(
dev
,
sip
,
tip
,
scope
);
}
static
int
arp_filter
(
__u32
sip
,
__u32
tip
,
struct
net_device
*
dev
)
static
int
arp_filter
(
__u32
sip
,
__u32
tip
,
struct
net_device
*
dev
)
{
{
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
sip
,
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
sip
,
...
@@ -789,7 +825,8 @@ int arp_process(struct sk_buff *skb)
...
@@ -789,7 +825,8 @@ int arp_process(struct sk_buff *skb)
/* Special case: IPv4 duplicate address detection packet (RFC2131) */
/* Special case: IPv4 duplicate address detection packet (RFC2131) */
if
(
sip
==
0
)
{
if
(
sip
==
0
)
{
if
(
arp
->
ar_op
==
htons
(
ARPOP_REQUEST
)
&&
if
(
arp
->
ar_op
==
htons
(
ARPOP_REQUEST
)
&&
inet_addr_type
(
tip
)
==
RTN_LOCAL
)
inet_addr_type
(
tip
)
==
RTN_LOCAL
&&
!
arp_ignore
(
in_dev
,
dev
,
sip
,
tip
))
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
tip
,
dev
,
tip
,
sha
,
dev
->
dev_addr
,
dev
->
dev_addr
);
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
tip
,
dev
,
tip
,
sha
,
dev
->
dev_addr
,
dev
->
dev_addr
);
goto
out
;
goto
out
;
}
}
...
@@ -804,7 +841,10 @@ int arp_process(struct sk_buff *skb)
...
@@ -804,7 +841,10 @@ int arp_process(struct sk_buff *skb)
n
=
neigh_event_ns
(
&
arp_tbl
,
sha
,
&
sip
,
dev
);
n
=
neigh_event_ns
(
&
arp_tbl
,
sha
,
&
sip
,
dev
);
if
(
n
)
{
if
(
n
)
{
int
dont_send
=
0
;
int
dont_send
=
0
;
if
(
IN_DEV_ARPFILTER
(
in_dev
))
if
(
!
dont_send
)
dont_send
|=
arp_ignore
(
in_dev
,
dev
,
sip
,
tip
);
if
(
!
dont_send
&&
IN_DEV_ARPFILTER
(
in_dev
))
dont_send
|=
arp_filter
(
sip
,
tip
,
dev
);
dont_send
|=
arp_filter
(
sip
,
tip
,
dev
);
if
(
!
dont_send
)
if
(
!
dont_send
)
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
sip
,
dev
,
tip
,
sha
,
dev
->
dev_addr
,
sha
);
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
sip
,
dev
,
tip
,
sha
,
dev
->
dev_addr
,
sha
);
...
...
net/ipv4/devinet.c
View file @
4d99775f
...
@@ -809,6 +809,84 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
...
@@ -809,6 +809,84 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
goto
out
;
goto
out
;
}
}
static
u32
confirm_addr_indev
(
struct
in_device
*
in_dev
,
u32
dst
,
u32
local
,
int
scope
)
{
int
same
=
0
;
u32
addr
=
0
;
for_ifa
(
in_dev
)
{
if
(
!
addr
&&
(
local
==
ifa
->
ifa_local
||
!
local
)
&&
ifa
->
ifa_scope
<=
scope
)
{
addr
=
ifa
->
ifa_local
;
if
(
same
)
break
;
}
if
(
!
same
)
{
same
=
(
!
local
||
inet_ifa_match
(
local
,
ifa
))
&&
(
!
dst
||
inet_ifa_match
(
dst
,
ifa
));
if
(
same
&&
addr
)
{
if
(
local
||
!
dst
)
break
;
/* Is the selected addr into dst subnet? */
if
(
inet_ifa_match
(
addr
,
ifa
))
break
;
/* No, then can we use new local src? */
if
(
ifa
->
ifa_scope
<=
scope
)
{
addr
=
ifa
->
ifa_local
;
break
;
}
/* search for large dst subnet for addr */
same
=
0
;
}
}
}
endfor_ifa
(
in_dev
);
return
same
?
addr
:
0
;
}
/*
* Confirm that local IP address exists using wildcards:
* - dev: only on this interface, 0=any interface
* - dst: only in the same subnet as dst, 0=any dst
* - local: address, 0=autoselect the local address
* - scope: maximum allowed scope value for the local address
*/
u32
inet_confirm_addr
(
const
struct
net_device
*
dev
,
u32
dst
,
u32
local
,
int
scope
)
{
u32
addr
=
0
;
struct
in_device
*
in_dev
;
if
(
dev
)
{
read_lock
(
&
inetdev_lock
);
if
((
in_dev
=
__in_dev_get
(
dev
)))
{
read_lock
(
&
in_dev
->
lock
);
addr
=
confirm_addr_indev
(
in_dev
,
dst
,
local
,
scope
);
read_unlock
(
&
in_dev
->
lock
);
}
read_unlock
(
&
inetdev_lock
);
return
addr
;
}
read_lock
(
&
dev_base_lock
);
read_lock
(
&
inetdev_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
if
((
in_dev
=
__in_dev_get
(
dev
)))
{
read_lock
(
&
in_dev
->
lock
);
addr
=
confirm_addr_indev
(
in_dev
,
dst
,
local
,
scope
);
read_unlock
(
&
in_dev
->
lock
);
if
(
addr
)
break
;
}
}
read_unlock
(
&
inetdev_lock
);
read_unlock
(
&
dev_base_lock
);
return
addr
;
}
/*
/*
* Device notifier
* Device notifier
*/
*/
...
@@ -1132,7 +1210,7 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen,
...
@@ -1132,7 +1210,7 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen,
static
struct
devinet_sysctl_table
{
static
struct
devinet_sysctl_table
{
struct
ctl_table_header
*
sysctl_header
;
struct
ctl_table_header
*
sysctl_header
;
ctl_table
devinet_vars
[
19
];
ctl_table
devinet_vars
[
20
];
ctl_table
devinet_dev
[
2
];
ctl_table
devinet_dev
[
2
];
ctl_table
devinet_conf_dir
[
2
];
ctl_table
devinet_conf_dir
[
2
];
ctl_table
devinet_proto_dir
[
2
];
ctl_table
devinet_proto_dir
[
2
];
...
@@ -1259,6 +1337,14 @@ static struct devinet_sysctl_table {
...
@@ -1259,6 +1337,14 @@ static struct devinet_sysctl_table {
.
mode
=
0644
,
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
,
.
proc_handler
=
&
proc_dointvec
,
},
},
{
.
ctl_name
=
NET_IPV4_CONF_ARP_IGNORE
,
.
procname
=
"arp_ignore"
,
.
data
=
&
ipv4_devconf
.
arp_ignore
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
,
},
{
{
.
ctl_name
=
NET_IPV4_CONF_NOXFRM
,
.
ctl_name
=
NET_IPV4_CONF_NOXFRM
,
.
procname
=
"disable_xfrm"
,
.
procname
=
"disable_xfrm"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment