diff -ur v2.4.26/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt --- v2.4.26/linux/Documentation/filesystems/proc.txt 2003-06-14 08:41:59.000000000 +0300 +++ linux/Documentation/filesystems/proc.txt 2004-02-28 21:44:02.907689168 +0200 @@ -1567,6 +1567,16 @@ Determines whether to send ICMP redirects to other hosts. +hidden +------ + +Hide addresses attached to this device from other devices. +Such addresses will never be selected by source address autoselection +mechanism, host does not answer broadcast ARP requests for them, +does not announce them as source address of ARP requests, but they +are still reachable via IP. This flag is activated only if it is +enabled both in specific device section and in "all" section. + Routing settings ---------------- diff -ur v2.4.26/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- v2.4.26/linux/Documentation/networking/ip-sysctl.txt 2004-02-28 21:31:33.000000000 +0200 +++ linux/Documentation/networking/ip-sysctl.txt 2004-02-28 21:38:24.611118064 +0200 @@ -530,6 +530,14 @@ The max value from conf/{all,interface}/arp_ignore is used when ARP request is received on the {interface} +hidden - BOOLEAN + Hide addresses attached to this device from other devices. + Such addresses will never be selected by source address autoselection + mechanism, host does not answer broadcast ARP requests for them, + does not announce them as source address of ARP requests, but they + are still reachable via IP. This flag is activated only if it is + enabled both in specific device section and in "all" section. + tag - INTEGER Allows you to write a number, which can be used as required. Default value is 0. diff -ur v2.4.26/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h --- v2.4.26/linux/include/linux/inetdevice.h 2004-02-28 21:31:34.000000000 +0200 +++ linux/include/linux/inetdevice.h 2004-02-28 21:38:24.627115632 +0200 @@ -22,6 +22,7 @@ int arp_ignore; int medium_id; int force_igmp_version; + int hidden; void *sysctl; }; @@ -58,6 +59,7 @@ #define IN_DEV_LOG_MARTIANS(in_dev) (ipv4_devconf.log_martians || (in_dev)->cnf.log_martians) #define IN_DEV_PROXY_ARP(in_dev) (ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp) +#define IN_DEV_HIDDEN(in_dev) ((in_dev)->cnf.hidden && ipv4_devconf.hidden) #define IN_DEV_SHARED_MEDIA(in_dev) (ipv4_devconf.shared_media || (in_dev)->cnf.shared_media) #define IN_DEV_TX_REDIRECTS(in_dev) (ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects) #define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) diff -ur v2.4.26/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.4.26/linux/include/linux/sysctl.h 2004-02-28 21:31:34.000000000 +0200 +++ linux/include/linux/sysctl.h 2004-02-28 21:38:24.628115480 +0200 @@ -363,6 +363,7 @@ NET_IPV4_CONF_FORCE_IGMP_VERSION=17, NET_IPV4_CONF_ARP_ANNOUNCE=18, NET_IPV4_CONF_ARP_IGNORE=19, + NET_IPV4_CONF_HIDDEN=20, }; /* /proc/sys/net/ipv4/netfilter */ diff -ur v2.4.26/linux/net/ipv4/arp.c linux/net/ipv4/arp.c --- v2.4.26/linux/net/ipv4/arp.c 2004-02-28 21:31:34.000000000 +0200 +++ linux/net/ipv4/arp.c 2004-02-28 21:38:24.631115024 +0200 @@ -70,6 +70,8 @@ * arp_xmit so intermediate drivers like * bonding can change the skb before * sending (e.g. insert 8021q tag). + * Julian Anastasov: "hidden" flag: hide the + * interface and don't reply for it */ #include @@ -327,21 +329,34 @@ u32 target = *(u32*)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev = in_dev_get(dev); + struct in_device *in_dev2 = NULL; + struct net_device *dev2 = NULL; + int mode; if (!in_dev) return; - switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { + mode = IN_DEV_ARP_ANNOUNCE(in_dev); + if (mode != 2 && skb && (dev2 = ip_dev_find(skb->nh.iph->saddr)) != NULL && + (saddr = skb->nh.iph->saddr, in_dev2 = in_dev_get(dev2)) != NULL && + IN_DEV_HIDDEN(in_dev2)) { + saddr = 0; + goto get; + } + + switch (mode) { default: case 0: /* By default announce any local IP */ + if (saddr) + break; if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) saddr = skb->nh.iph->saddr; break; case 1: /* Restrict announcements of saddr in same subnet */ if (!skb) break; - saddr = skb->nh.iph->saddr; - if (inet_addr_type(saddr) == RTN_LOCAL) { + if (saddr || (saddr = skb->nh.iph->saddr, + inet_addr_type(saddr) == RTN_LOCAL)) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break; @@ -352,6 +367,12 @@ break; } +get: + if (dev2) { + if (in_dev2) + in_dev_put(in_dev2); + dev_put(dev2); + } if (in_dev) in_dev_put(in_dev); if (!saddr) @@ -427,6 +448,26 @@ return flag; } +static int arp_hidden(u32 tip, struct net_device *dev) +{ + struct net_device *dev2 = NULL; + struct in_device *in_dev2 = NULL; + int ret = 0; + + if (!ipv4_devconf.hidden) + return 0; + + if ((dev2 = ip_dev_find(tip)) && dev2 != dev && + (in_dev2 = in_dev_get(dev2)) && IN_DEV_HIDDEN(in_dev2)) + ret = 1; + if (dev2) { + if (in_dev2) + in_dev_put(in_dev2); + dev_put(dev2); + } + return ret; +} + /* OBSOLETE FUNCTIONS */ /* @@ -848,6 +889,7 @@ if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(tip) == RTN_LOCAL && + !arp_hidden(tip, dev) && !arp_ignore(in_dev,dev,sip,tip)) arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr); goto out; @@ -868,6 +910,8 @@ dont_send |= arp_ignore(in_dev,dev,sip,tip); if (!dont_send && IN_DEV_ARPFILTER(in_dev)) dont_send |= arp_filter(sip,tip,dev); + if (!dont_send && skb->pkt_type != PACKET_HOST) + dont_send |= arp_hidden(tip,dev); if (!dont_send) arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); diff -ur v2.4.26/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c --- v2.4.26/linux/net/ipv4/devinet.c 2004-02-28 21:31:34.000000000 +0200 +++ linux/net/ipv4/devinet.c 2004-02-28 21:39:35.222383520 +0200 @@ -756,7 +756,8 @@ read_lock(&in_dev->lock); for_primary_ifa(in_dev) { - if (ifa->ifa_scope != RT_SCOPE_LINK && + if (!IN_DEV_HIDDEN(in_dev) && + ifa->ifa_scope != RT_SCOPE_LINK && ifa->ifa_scope <= scope) { read_unlock(&in_dev->lock); read_unlock(&inetdev_lock); @@ -1134,7 +1135,7 @@ static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table devinet_vars[20]; + ctl_table devinet_vars[21]; ctl_table devinet_dev[2]; ctl_table devinet_conf_dir[2]; ctl_table devinet_proto_dir[2]; @@ -1183,6 +1184,9 @@ {NET_IPV4_CONF_ARPFILTER, "arp_filter", &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_CONF_HIDDEN, "hidden", + &ipv4_devconf.hidden, sizeof(int), 0644, NULL, + &proc_dointvec}, {NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce", &ipv4_devconf.arp_announce, sizeof(int), 0644, NULL, &proc_dointvec},