From nobody@FreeBSD.org  Thu Dec  3 11:58:23 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 18F99106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  3 Dec 2009 11:58:23 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 055518FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  3 Dec 2009 11:58:23 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nB3BwMqM096071
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 3 Dec 2009 11:58:22 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id nB3BwMKu096069;
	Thu, 3 Dec 2009 11:58:22 GMT
	(envelope-from nobody)
Message-Id: <200912031158.nB3BwMKu096069@www.freebsd.org>
Date: Thu, 3 Dec 2009 11:58:22 GMT
From: Alexander Zagrebin <alexz@visp.ru>
To: freebsd-gnats-submit@FreeBSD.org
Subject: "ioctl (SIOCAIFADDR): File exists" error when configuring ppp interfaces
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         141134
>Category:       kern
>Synopsis:       [ppp] "ioctl (SIOCAIFADDR): File exists" error when configuring ppp interfaces
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    qingli
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 03 12:00:11 UTC 2009
>Closed-Date:    Tue Jan 05 22:42:56 UTC 2010
>Last-Modified:  Tue Jan 05 22:42:56 UTC 2010
>Originator:     Alexander Zagrebin
>Release:        FreeBSD 8.0-RELEASE
>Organization:
-
>Environment:
FreeBSD gw.vosz.local 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sun Nov 29 00:37:18 MSK 2009     root@gw.vosz.local:/usr/src/sys/amd64/compile/KERNEL  amd64
>Description:
I use mpd 5.3 (ports/net/mpd5) as vpn server.
After upgrading to 8.0-RELEASE from 7.2-RELEASE I began to receive complaints from users. They says, that the first attempt to connect to our vpn server always fails, and only the second attempt is successful.
The log files confirms this.
I have found how to reproduce this problem with command line.

I'll create the interface tun10:

# ifconfig tun10 create inet 192.168.100.1 192.168.100.10 netmask 0xffffffff
# ifconfig tun10
tun10: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        inet 192.168.100.1 --> 192.168.100.10 netmask 0xffffffff
# netstat -rn
..
192.168.100.1      link#13            UHS         0        0    lo0
192.168.100.10     link#13            UH          0        0  tun10
..
# ping -c1 192.168.100.1
PING 192.168.100.1 (192.168.100.1): 56 data bytes
64 bytes from 192.168.100.1: icmp_seq=0 ttl=64 time=0.050 ms

--- 192.168.100.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.050/0.050/0.050/0.000 ms

All right.
The interface was successfully created, loopback route was added, and i can ping self.
Now I'll create the interface tun11 for another peer:

# ifconfig tun11 create inet 192.168.100.1 192.168.100.11 netmask 0xffffffff
ifconfig: ioctl (SIOCAIFADDR): File exists
# ifconfig tun11
tun11: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        inet 192.168.100.1 --> 192.168.100.11 netmask 0xffffffff
# netstat -rn
..
192.168.100.1      link#13            UHS         0        1    lo0
192.168.100.10     link#13            UH          0        0  tun10
192.168.100.11     link#14            UH          0        0  tun11
..

The first problem:
ifconfig returned error, but interface was successfully configured.
The same error, returned from ioctl, forces ppp daemon to terminate ipcp and disconnect a peer.

Now I'll destroy tun11 and will create it again or will reconfigure it with the same parameters (the result is the same):

# ifconfig tun11 destroy
# ifconfig tun11 create inet 192.168.100.1 192.168.100.11 netmask 0xffffffff
or
# ifconfig tun11 inet 192.168.100.1 192.168.100.11 netmask 0xffffffff
# netstat -rn
..
192.168.100.1      link#14            UHS         0        0    lo0
192.168.100.10     link#13            UH          0        0  tun10
192.168.100.11     link#14            UH          0        0  tun11
..

There is no error from ifconfig now. It's strange.
loopback route was changed.
This explains why the second attempt of a peer to connect is successful.
If we'll create additional interfaces (tun12,tun13, etc), the behavior will the same.

The second problem:
Suppose the peer on tun11 terminates her session.
# ifconfig tun11 destroy
# netstat -rn
..
192.168.100.10     link#13            UH          0        0  tun10
..
# ping -c1 192.168.100.1
PING 192.168.100.1 (192.168.100.1): 56 data bytes

--- 192.168.100.1 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss

So loopback route to 192.168.100.1 was deleted and I'll can't ping self. It's correct for destroyed tun11 (link#14), but as still there is the tun10 (link#13), we need loopback route to 192.168.100.1

After looking to the sources and doing some debugging I have found, that the first problem (EEXIST from ioctl) occurs because of call ifa_add_loopback_route
from in_ifinit (in.c:928). So I temporary disabled adding loopback routes via 
net.link.ether.inet.useloopback, but this is bad idea.


>How-To-Repeat:
See the "full description"
>Fix:
To prevent adding of loopback routes I use
sysctl net.link.ether.inet.useloopback=0


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Dec 3 23:42:59 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141134 
Responsible-Changed-From-To: freebsd-net->qingli 
Responsible-Changed-By: qingli 
Responsible-Changed-When: Fri Dec 4 18:05:10 UTC 2009 
Responsible-Changed-Why:  
Take ownership of this bug. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141134 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141134: commit references a PR
Date: Tue,  5 Jan 2010 22:16:13 +0000 (UTC)

 Author: qingli
 Date: Tue Jan  5 22:14:55 2010
 New Revision: 201614
 URL: http://svn.freebsd.org/changeset/base/201614
 
 Log:
   MFC r201282, r201543
   
   r201282
   -------
   The proxy arp entries could not be added into the system over the
   IFF_POINTOPOINT link types. The reason was due to the routing
   entry returned from the kernel covering the remote end is of an
   interface type that does not support ARP. This patch fixes this
   problem by providing a hint to the kernel routing code, which
   indicates the prefix route instead of the PPP host route should
   be returned to the caller. Since a host route to the local end
   point is also added into the routing table, and there could be
   multiple such instantiations due to multiple PPP links can be
   created with the same local end IP address, this patch also fixes
   the loopback route installation failure problem observed prior to
   this patch. The reference count of loopback route to local end would
   be either incremented or decremented. The first instantiation would
   create the entry and the last removal would delete the route entry.
   
   r201543
   -------
   The IFA_RTSELF address flag marks a loopback route has been installed
   for the interface address. This marker is necessary to properly support
   PPP types of links where multiple links can have the same local end
   IP address. The IFA_RTSELF flag bit maps to the RTF_HOST value, which
   was combined into the route flag bits during prefix installation in
   IPv6. This inclusion causing the prefix route to be unusable. This
   patch fixes this bug by excluding the IFA_RTSELF flag during route
   installation.
   
   PR:		ports/141342, kern/141134
 
 Modified:
   stable/8/sys/net/if_llatbl.c
   stable/8/sys/net/if_llatbl.h
   stable/8/sys/net/if_var.h
   stable/8/sys/net/route.c
   stable/8/sys/net/route.h
   stable/8/sys/net/rtsock.c
   stable/8/sys/netinet/in.c
   stable/8/sys/netinet6/in6.c
   stable/8/sys/netinet6/nd6_rtr.c
   stable/8/usr.sbin/arp/arp.c
 Directory Properties:
   stable/8/   (props changed)
   stable/8/ObsoleteFiles.inc   (props changed)
   stable/8/UPDATING   (props changed)
   stable/8/bin/   (props changed)
   stable/8/bin/csh/   (props changed)
   stable/8/bin/pax/   (props changed)
   stable/8/bin/ps/   (props changed)
   stable/8/bin/sh/   (props changed)
   stable/8/cddl/compat/opensolaris/   (props changed)
   stable/8/cddl/contrib/opensolaris/   (props changed)
   stable/8/cddl/contrib/opensolaris/cmd/zdb/   (props changed)
   stable/8/cddl/contrib/opensolaris/cmd/zfs/   (props changed)
   stable/8/cddl/contrib/opensolaris/lib/libzfs/   (props changed)
   stable/8/cddl/lib/libnvpair/   (props changed)
   stable/8/contrib/bind9/   (props changed)
   stable/8/contrib/bsnmp/   (props changed)
   stable/8/contrib/bzip2/   (props changed)
   stable/8/contrib/cpio/   (props changed)
   stable/8/contrib/csup/   (props changed)
   stable/8/contrib/ee/   (props changed)
   stable/8/contrib/expat/   (props changed)
   stable/8/contrib/file/   (props changed)
   stable/8/contrib/gcc/   (props changed)
   stable/8/contrib/gdb/   (props changed)
   stable/8/contrib/gdtoa/   (props changed)
   stable/8/contrib/less/   (props changed)
   stable/8/contrib/libpcap/   (props changed)
   stable/8/contrib/ncurses/   (props changed)
   stable/8/contrib/netcat/   (props changed)
   stable/8/contrib/ntp/   (props changed)
   stable/8/contrib/openbsm/   (props changed)
   stable/8/contrib/openpam/   (props changed)
   stable/8/contrib/pf/   (props changed)
   stable/8/contrib/sendmail/   (props changed)
   stable/8/contrib/tcpdump/   (props changed)
   stable/8/contrib/tcsh/   (props changed)
   stable/8/contrib/top/   (props changed)
   stable/8/contrib/top/install-sh   (props changed)
   stable/8/contrib/traceroute/   (props changed)
   stable/8/contrib/wpa/   (props changed)
   stable/8/crypto/openssh/   (props changed)
   stable/8/crypto/openssl/   (props changed)
   stable/8/etc/   (props changed)
   stable/8/games/factor/   (props changed)
   stable/8/games/fortune/   (props changed)
   stable/8/games/fortune/datfiles/   (props changed)
   stable/8/gnu/usr.bin/groff/   (props changed)
   stable/8/gnu/usr.bin/patch/   (props changed)
   stable/8/include/   (props changed)
   stable/8/kerberos5/lib/libgssapi_krb5/   (props changed)
   stable/8/kerberos5/lib/libgssapi_spnego/   (props changed)
   stable/8/lib/bind/   (props changed)
   stable/8/lib/csu/   (props changed)
   stable/8/lib/libarchive/   (props changed)
   stable/8/lib/libc/   (props changed)
   stable/8/lib/libc/stdtime/   (props changed)
   stable/8/lib/libdevinfo/   (props changed)
   stable/8/lib/libdisk/   (props changed)
   stable/8/lib/libexpat/   (props changed)
   stable/8/lib/libfetch/   (props changed)
   stable/8/lib/libjail/   (props changed)
   stable/8/lib/libkvm/   (props changed)
   stable/8/lib/libpmc/   (props changed)
   stable/8/lib/libradius/   (props changed)
   stable/8/lib/libstand/   (props changed)
   stable/8/lib/libtacplus/   (props changed)
   stable/8/lib/libthr/   (props changed)
   stable/8/lib/libusb/   (props changed)
   stable/8/lib/libusb/usb.h   (props changed)
   stable/8/lib/libutil/   (props changed)
   stable/8/libexec/rtld-elf/   (props changed)
   stable/8/release/   (props changed)
   stable/8/release/doc/   (props changed)
   stable/8/release/doc/en_US.ISO8859-1/hardware/   (props changed)
   stable/8/sbin/   (props changed)
   stable/8/sbin/atacontrol/   (props changed)
   stable/8/sbin/bsdlabel/   (props changed)
   stable/8/sbin/camcontrol/   (props changed)
   stable/8/sbin/ddb/   (props changed)
   stable/8/sbin/dhclient/   (props changed)
   stable/8/sbin/fsck/   (props changed)
   stable/8/sbin/geom/   (props changed)
   stable/8/sbin/ifconfig/   (props changed)
   stable/8/sbin/ipfw/   (props changed)
   stable/8/sbin/mksnap_ffs/   (props changed)
   stable/8/sbin/mount/   (props changed)
   stable/8/sbin/mount_cd9660/   (props changed)
   stable/8/sbin/mount_msdosfs/   (props changed)
   stable/8/sbin/mount_nfs/   (props changed)
   stable/8/sbin/umount/   (props changed)
   stable/8/secure/usr.bin/bdes/   (props changed)
   stable/8/share/man/man3/   (props changed)
   stable/8/share/man/man4/   (props changed)
   stable/8/share/man/man4/de.4   (props changed)
   stable/8/share/man/man5/   (props changed)
   stable/8/share/man/man7/   (props changed)
   stable/8/share/man/man8/   (props changed)
   stable/8/share/man/man9/   (props changed)
   stable/8/share/misc/   (props changed)
   stable/8/share/timedef/   (props changed)
   stable/8/share/zoneinfo/   (props changed)
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
   stable/8/tools/kerneldoc/subsys/   (props changed)
   stable/8/tools/regression/bin/sh/   (props changed)
   stable/8/tools/regression/lib/libc/   (props changed)
   stable/8/tools/regression/lib/msun/test-conj.t   (props changed)
   stable/8/tools/regression/poll/   (props changed)
   stable/8/tools/regression/priv/   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pgrep-_g.t   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pgrep-_s.t   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pkill-_g.t   (props changed)
   stable/8/tools/tools/ath/common/dumpregs.h   (props changed)
   stable/8/tools/tools/ath/common/dumpregs_5210.c   (props changed)
   stable/8/tools/tools/ath/common/dumpregs_5211.c   (props changed)
   stable/8/tools/tools/ath/common/dumpregs_5212.c   (props changed)
   stable/8/tools/tools/ath/common/dumpregs_5416.c   (props changed)
   stable/8/tools/tools/termcap/termcap.pl   (props changed)
   stable/8/tools/tools/vimage/   (props changed)
   stable/8/usr.bin/calendar/   (props changed)
   stable/8/usr.bin/calendar/calendars/calendar.freebsd   (props changed)
   stable/8/usr.bin/csup/   (props changed)
   stable/8/usr.bin/find/   (props changed)
   stable/8/usr.bin/finger/   (props changed)
   stable/8/usr.bin/fstat/   (props changed)
   stable/8/usr.bin/gcore/   (props changed)
   stable/8/usr.bin/gzip/   (props changed)
   stable/8/usr.bin/kdump/   (props changed)
   stable/8/usr.bin/locale/   (props changed)
   stable/8/usr.bin/look/   (props changed)
   stable/8/usr.bin/netstat/   (props changed)
   stable/8/usr.bin/perror/   (props changed)
   stable/8/usr.bin/procstat/   (props changed)
   stable/8/usr.bin/systat/   (props changed)
   stable/8/usr.bin/unifdef/   (props changed)
   stable/8/usr.bin/vmstat/   (props changed)
   stable/8/usr.bin/w/   (props changed)
   stable/8/usr.bin/whois/   (props changed)
   stable/8/usr.sbin/   (props changed)
   stable/8/usr.sbin/Makefile   (props changed)
   stable/8/usr.sbin/acpi/   (props changed)
   stable/8/usr.sbin/arp/   (props changed)
   stable/8/usr.sbin/bsnmpd/   (props changed)
   stable/8/usr.sbin/cdcontrol/   (props changed)
   stable/8/usr.sbin/crashinfo/   (props changed)
   stable/8/usr.sbin/cron/   (props changed)
   stable/8/usr.sbin/diskinfo/   (props changed)
   stable/8/usr.sbin/dumpcis/cardinfo.h   (props changed)
   stable/8/usr.sbin/dumpcis/cis.h   (props changed)
   stable/8/usr.sbin/freebsd-update/   (props changed)
   stable/8/usr.sbin/inetd/   (props changed)
   stable/8/usr.sbin/iostat/   (props changed)
   stable/8/usr.sbin/jail/   (props changed)
   stable/8/usr.sbin/jls/   (props changed)
   stable/8/usr.sbin/lpr/   (props changed)
   stable/8/usr.sbin/makefs/ffs/ffs_bswap.c   (props changed)
   stable/8/usr.sbin/makefs/ffs/ffs_subr.c   (props changed)
   stable/8/usr.sbin/makefs/ffs/ufs_bswap.h   (props changed)
   stable/8/usr.sbin/makefs/getid.c   (props changed)
   stable/8/usr.sbin/mfiutil/mfiutil.8   (props changed)
   stable/8/usr.sbin/ndp/   (props changed)
   stable/8/usr.sbin/ntp/   (props changed)
   stable/8/usr.sbin/ppp/   (props changed)
   stable/8/usr.sbin/pstat/   (props changed)
   stable/8/usr.sbin/service/   (props changed)
   stable/8/usr.sbin/sysinstall/   (props changed)
   stable/8/usr.sbin/syslogd/   (props changed)
   stable/8/usr.sbin/traceroute6/   (props changed)
   stable/8/usr.sbin/usbconfig/   (props changed)
   stable/8/usr.sbin/wpa/   (props changed)
   stable/8/usr.sbin/zic/   (props changed)
 
 Modified: stable/8/sys/net/if_llatbl.c
 ==============================================================================
 --- stable/8/sys/net/if_llatbl.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/if_llatbl.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -274,7 +274,9 @@ lla_rt_output(struct rt_msghdr *rtm, str
  #ifdef INET
  			if (dst->sa_family == AF_INET && 
  			    ((struct sockaddr_inarp *)dst)->sin_other != 0) {
 -				struct rtentry *rt = rtalloc1(dst, 0, 0);
 +				struct rtentry *rt;
 +				((struct sockaddr_inarp *)dst)->sin_other = 0;
 +				rt = rtalloc1(dst, 0, 0);
  				if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
  					log(LOG_INFO, "%s: RTM_ADD publish "
  					    "(proxy only) is invalid\n",
 
 Modified: stable/8/sys/net/if_llatbl.h
 ==============================================================================
 --- stable/8/sys/net/if_llatbl.h	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/if_llatbl.h	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -159,7 +159,7 @@ struct lltable {
  				    const struct sockaddr *mask);
  	struct llentry *	(*llt_lookup)(struct lltable *, u_int flags,
  				    const struct sockaddr *l3addr);
 -	int			(*llt_rtcheck)(struct ifnet *,
 +	int			(*llt_rtcheck)(struct ifnet *, u_int flags,
  				    const struct sockaddr *);
  	int			(*llt_dump)(struct lltable *,
  				     struct sysctl_req *);
 
 Modified: stable/8/sys/net/if_var.h
 ==============================================================================
 --- stable/8/sys/net/if_var.h	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/if_var.h	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -712,6 +712,7 @@ struct ifaddr {
  	struct mtx ifa_mtx;
  };
  #define	IFA_ROUTE	RTF_UP		/* route installed */
 +#define IFA_RTSELF	RTF_HOST	/* loopback route to self installed */
  
  /* for compatibility with other BSDs */
  #define	ifa_list	ifa_link
 
 Modified: stable/8/sys/net/route.c
 ==============================================================================
 --- stable/8/sys/net/route.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/route.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -98,8 +98,6 @@ VNET_DEFINE(struct rtstat, rtstat);
  #define	V_rttrash	VNET(rttrash)
  #define	V_rtstat	VNET(rtstat)
  
 -static void rt_maskedcopy(struct sockaddr *,
 -	    struct sockaddr *, struct sockaddr *);
  
  /* compare two sockaddr structures */
  #define	sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
 @@ -1315,7 +1313,7 @@ rt_setgate(struct rtentry *rt, struct so
  	return (0);
  }
  
 -static void
 +void
  rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask)
  {
  	register u_char *cp1 = (u_char *)src;
 
 Modified: stable/8/sys/net/route.h
 ==============================================================================
 --- stable/8/sys/net/route.h	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/route.h	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -384,6 +384,7 @@ void	 rt_missmsg(int, struct rt_addrinfo
  void	 rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
  void	 rt_newmaddrmsg(int, struct ifmultiaddr *);
  int	 rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
 +void 	 rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
  
  /*
   * Note the following locking behavior:
 
 Modified: stable/8/sys/net/rtsock.c
 ==============================================================================
 --- stable/8/sys/net/rtsock.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/net/rtsock.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -60,6 +60,7 @@
  #include <net/vnet.h>
  
  #include <netinet/in.h>
 +#include <netinet/if_ether.h>
  #ifdef INET6
  #include <netinet6/scope6_var.h>
  #endif
 @@ -622,6 +623,27 @@ route_output(struct mbuf *m, struct sock
  			}
  		}
  #endif
 +		/*
 +		 * If performing proxied L2 entry insertion, and
 +		 * the actual PPP host entry is found, perform
 +		 * another search to retrieve the prefix route of
 +		 * the local end point of the PPP link.
 +		 */
 +		if ((rtm->rtm_flags & RTF_ANNOUNCE) &&
 +		    (rt->rt_ifp->if_flags & IFF_POINTOPOINT)) {
 +			struct sockaddr laddr;
 +			rt_maskedcopy(rt->rt_ifa->ifa_addr,
 +				      &laddr,
 +				      rt->rt_ifa->ifa_netmask);
 +			/* 
 +			 * refactor rt and no lock operation necessary
 +			 */
 +			rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, rnh);
 +			if (rt == NULL) {
 +				RADIX_NODE_HEAD_RUNLOCK(rnh);
 +				senderr(ESRCH);
 +			}
 +		} 
  		RT_LOCK(rt);
  		RT_ADDREF(rt);
  		RADIX_NODE_HEAD_RUNLOCK(rnh);
 
 Modified: stable/8/sys/netinet/in.c
 ==============================================================================
 --- stable/8/sys/netinet/in.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/netinet/in.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -924,9 +924,25 @@ in_ifinit(struct ifnet *ifp, struct in_i
  	/*
  	 * add a loopback route to self
  	 */
 -	if (V_useloopback && !(ifp->if_flags & IFF_LOOPBACK))
 -		error = ifa_add_loopback_route((struct ifaddr *)ia, 
 +	if (V_useloopback && !(ifp->if_flags & IFF_LOOPBACK)) {
 +		struct route ia_ro;
 +
 +		bzero(&ia_ro, sizeof(ia_ro));
 +		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
 +		rtalloc_ign_fib(&ia_ro, 0, 0);
 +		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
 +		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
 +			RT_LOCK(ia_ro.ro_rt);
 +			RT_ADDREF(ia_ro.ro_rt);
 +			RTFREE_LOCKED(ia_ro.ro_rt);
 +		} else
 +			error = ifa_add_loopback_route((struct ifaddr *)ia, 
  				       (struct sockaddr *)&ia->ia_addr);
 +		if (error == 0)
 +			ia->ia_flags |= IFA_RTSELF;
 +		if (ia_ro.ro_rt != NULL)
 +			RTFREE(ia_ro.ro_rt);
 +	}
  
  	return (error);
  }
 @@ -1043,7 +1059,7 @@ in_scrubprefix(struct in_ifaddr *target)
  {
  	struct in_ifaddr *ia;
  	struct in_addr prefix, mask, p;
 -	int error;
 +	int error = 0;
  	struct sockaddr_in prefix0, mask0;
  
  	/*
 @@ -1057,9 +1073,28 @@ in_scrubprefix(struct in_ifaddr *target)
  	 * deletion is unconditional.
  	 */
  	if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
 -	    !(target->ia_ifp->if_flags & IFF_LOOPBACK)) {
 -		error = ifa_del_loopback_route((struct ifaddr *)target,
 +	    !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
 +	    (target->ia_flags & IFA_RTSELF)) {
 +		struct route ia_ro;
 +		int freeit = 0;
 +
 +		bzero(&ia_ro, sizeof(ia_ro));
 +		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr;
 +		rtalloc_ign_fib(&ia_ro, 0, 0);
 +		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
 +		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
 +			RT_LOCK(ia_ro.ro_rt);
 +			if (ia_ro.ro_rt->rt_refcnt <= 1)
 +				freeit = 1;
 +			else
 +				RT_REMREF(ia_ro.ro_rt);
 +			RTFREE_LOCKED(ia_ro.ro_rt);
 +		}
 +		if (freeit)
 +			error = ifa_del_loopback_route((struct ifaddr *)target,
  				       (struct sockaddr *)&target->ia_addr);
 +		if (error == 0)
 +			target->ia_flags &= ~IFA_RTSELF;
  		/* remove arp cache */
  		arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
  	}
 @@ -1317,7 +1352,7 @@ in_lltable_prefix_free(struct lltable *l
  
  
  static int
 -in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
 +in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
  {
  	struct rtentry *rt;
  
 @@ -1326,7 +1361,8 @@ in_lltable_rtcheck(struct ifnet *ifp, co
  
  	/* XXX rtalloc1 should take a const param */
  	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
 -	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
 +	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || 
 +	    ((rt->rt_ifp != ifp) && !(flags & LLE_PUB))) {
  #ifdef DIAGNOSTIC
  		log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
  		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
 @@ -1378,7 +1414,7 @@ in_lltable_lookup(struct lltable *llt, u
  		 * verify this.
  		 */
  		if (!(flags & LLE_IFADDR) &&
 -		    in_lltable_rtcheck(ifp, l3addr) != 0)
 +		    in_lltable_rtcheck(ifp, flags, l3addr) != 0)
  			goto done;
  
  		lle = in_lltable_new(l3addr, flags);
 
 Modified: stable/8/sys/netinet6/in6.c
 ==============================================================================
 --- stable/8/sys/netinet6/in6.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/netinet6/in6.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -1196,8 +1196,12 @@ in6_purgeaddr(struct ifaddr *ifa)
  	 * The check for the current setting of "nd6_useloopback" 
  	 * is not needed.
  	 */
 -	error = ifa_del_loopback_route((struct ifaddr *)ia,
 -			       (struct sockaddr *)&ia->ia_addr);
 +	if (ia->ia_flags & IFA_RTSELF) {
 +		error = ifa_del_loopback_route((struct ifaddr *)ia,
 +				       (struct sockaddr *)&ia->ia_addr);
 +		if (error == 0)
 +			ia->ia_flags &= ~IFA_RTSELF;
 +	}
  
  	/* stop DAD processing */
  	nd6_dad_stop(ifa);
 @@ -1758,6 +1762,8 @@ in6_ifinit(struct ifnet *ifp, struct in6
  		|| (ifp->if_flags & IFF_LOOPBACK))) {
  		error = ifa_add_loopback_route((struct ifaddr *)ia,
  				       (struct sockaddr *)&ia->ia_addr);
 +		if (error == 0)
 +			ia->ia_flags |= IFA_RTSELF;
  	}
  
  	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
 @@ -2340,7 +2346,9 @@ in6_lltable_prefix_free(struct lltable *
  }
  
  static int
 -in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
 +in6_lltable_rtcheck(struct ifnet *ifp, 
 +		    u_int flags, 
 +		    const struct sockaddr *l3addr)
  {
  	struct rtentry *rt;
  	char ip6buf[INET6_ADDRSTRLEN];
 @@ -2408,7 +2416,7 @@ in6_lltable_lookup(struct lltable *llt, 
  		 * verify this.
  		 */
  		if (!(flags & LLE_IFADDR) &&
 -		    in6_lltable_rtcheck(ifp, l3addr) != 0)
 +		    in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
  			return NULL;
  
  		lle = in6_lltable_new(l3addr, flags);
 
 Modified: stable/8/sys/netinet6/nd6_rtr.c
 ==============================================================================
 --- stable/8/sys/netinet6/nd6_rtr.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/sys/netinet6/nd6_rtr.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -1631,7 +1631,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
  	bzero(&mask6, sizeof(mask6));
  	mask6.sin6_len = sizeof(mask6);
  	mask6.sin6_addr = pr->ndpr_mask;
 -	rtflags = ifa->ifa_flags | RTF_UP;
 +	rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP;
  	error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
  	    ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
  	if (error == 0) {
 
 Modified: stable/8/usr.sbin/arp/arp.c
 ==============================================================================
 --- stable/8/usr.sbin/arp/arp.c	Tue Jan  5 21:14:48 2010	(r201613)
 +++ stable/8/usr.sbin/arp/arp.c	Tue Jan  5 22:14:55 2010	(r201614)
 @@ -326,7 +326,6 @@ set(int argc, char **argv)
  			doing_proxy = 1;
  			if (argc && strncmp(argv[1], "only", 3) == 0) {
  				proxy_only = 1;
 -				dst->sin_other = SIN_PROXY;
  				argc--; argv++;
  			}
  		} else if (strncmp(argv[0], "blackhole", 9) == 0) {
 @@ -365,33 +364,30 @@ set(int argc, char **argv)
  			sdl_m.sdl_alen = ETHER_ADDR_LEN;
  		}
  	}
 -	for (;;) {	/* try at most twice */
 -		rtm = rtmsg(RTM_GET, dst, &sdl_m);
 -		if (rtm == NULL) {
 -			warn("%s", host);
 -			return (1);
 -		}
 -		addr = (struct sockaddr_inarp *)(rtm + 1);
 -		sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
 -		if (addr->sin_addr.s_addr != dst->sin_addr.s_addr)	
 -			break;
 -		if (sdl->sdl_family == AF_LINK &&
 -		    !(rtm->rtm_flags & RTF_GATEWAY) &&
 -		    valid_type(sdl->sdl_type) )
 -			break;
 -		if (doing_proxy == 0) {
 -			printf("set: can only proxy for %s\n", host);
 -			return (1);
 -		}
 -		if (dst->sin_other & SIN_PROXY) {
 -			printf("set: proxy entry exists for non 802 device\n");
 -			return (1);
 -		}
 -		dst->sin_other = SIN_PROXY;
 -		proxy_only = 1;
 +
 +	/*
 +	 * In the case a proxy-arp entry is being added for
 +	 * a remote end point, the RTF_ANNOUNCE flag in the 
 +	 * RTM_GET command is an indication to the kernel
 +	 * routing code that the interface associated with
 +	 * the prefix route covering the local end of the
 +	 * PPP link should be returned, on which ARP applies.
 +	 */
 +	rtm = rtmsg(RTM_GET, dst, &sdl_m);
 +	if (rtm == NULL) {
 +		warn("%s", host);
 +		return (1);
 +	}
 +	addr = (struct sockaddr_inarp *)(rtm + 1);
 +	sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
 +	if (addr->sin_addr.s_addr == dst->sin_addr.s_addr) {
 +		printf("set: proxy entry exists for non 802 device\n");
 +		return (1);
  	}
  
 -	if (sdl->sdl_family != AF_LINK) {
 +	if ((sdl->sdl_family != AF_LINK) ||
 +	    (rtm->rtm_flags & RTF_GATEWAY) ||
 +	    !valid_type(sdl->sdl_type)) {
  		printf("cannot intuit interface index and type for %s\n", host);
  		return (1);
  	}
 @@ -436,7 +432,11 @@ delete(char *host, int do_proxy)
  	dst = getaddr(host);
  	if (dst == NULL)
  		return (1);
 -	dst->sin_other = do_proxy;
 +
 +	/*
 +	 * Perform a regular entry delete first.
 +	 */
 +	flags &= ~RTF_ANNOUNCE;
  
  	/*
  	 * setup the data structure to notify the kernel
 @@ -471,11 +471,16 @@ delete(char *host, int do_proxy)
  			break;
  		}
  
 -		if (dst->sin_other & SIN_PROXY) {
 +		/*
 +		 * Regualar entry delete failed, now check if there
 +		 * is a proxy-arp entry to remove.
 +		 */
 +		if (flags & RTF_ANNOUNCE) {
  			fprintf(stderr, "delete: cannot locate %s\n",host);
  			return (1);
  		}
 -		dst->sin_other = SIN_PROXY;
 +
 +		flags |= RTF_ANNOUNCE;
  	}
  	rtm->rtm_flags |= RTF_LLDATA;
  	if (rtmsg(RTM_DELETE, dst, NULL) != NULL) {
 @@ -485,6 +490,7 @@ delete(char *host, int do_proxy)
  	return (1);
  }
  
 +
  /*
   * Search the arp table and do some action on matching entries
   */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: qingli 
State-Changed-When: Tue Jan 5 22:42:40 UTC 2010 
State-Changed-Why:  
The fix has been committed. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=141134 
>Unformatted:

Take ownership of this bug.

