Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Sep 2006 17:40:24 GMT
From:      Bruce M Simpson <bms@incunabulum.net>
To:        freebsd-net@FreeBSD.org
Subject:   Re: kern/38554: changing interface ipaddress doesn't seem to work
Message-ID:  <200609231740.k8NHeOX0046882@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/38554; it has been noted by GNATS.

From: Bruce M Simpson <bms@incunabulum.net>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/38554: changing interface ipaddress doesn't seem to work
Date: Sat, 23 Sep 2006 18:35:50 +0100

 This is a multi-part message in MIME format.
 --------------030000070707080504040106
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Before I suspend my work on this PR, here's a diff I pulled from trying 
 to port the changes to today's CURRENT.
 The patch doesn't work but haven't tested exhaustively. Need to focus on 
 other things.
 
 --------------030000070707080504040106
 Content-Type: text/x-patch;
  name="archie-locia-20060923.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="archie-locia-20060923.diff"
 
 ==== //depot/user/bms/nethead/sys/netinet/in.c#1 - /home/bms/fp4/nethead/sys/netinet/in.c ====
 --- /tmp/tmp.23928.0	Sat Sep 23 18:32:59 2006
 +++ /home/bms/fp4/nethead/sys/netinet/in.c	Sat Sep 23 17:37:13 2006
 @@ -459,6 +459,11 @@
  		 * a routing process they will come back.
  		 */
  		in_ifadown(&ia->ia_ifa, 1);
 +		/*
 +		 * Mark the interface address as no longer valid.
 +		 * Sockets that are bound to it should notice.
 +		 */
 +		ia->ia_ifa.ifa_flags |= RTF_REJECT;
  		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  		error = 0;
  		break;
 ==== //depot/user/bms/nethead/sys/netinet/in_pcb.c#1 - /home/bms/fp4/nethead/sys/netinet/in_pcb.c ====
 --- /tmp/tmp.23928.1	Sat Sep 23 18:32:59 2006
 +++ /home/bms/fp4/nethead/sys/netinet/in_pcb.c	Sat Sep 23 18:02:08 2006
 @@ -238,14 +238,17 @@
  	anonport = inp->inp_lport == 0 && (nam == NULL ||
  	    ((struct sockaddr_in *)nam)->sin_port == 0);
  	error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr,
 -	    &inp->inp_lport, cred);
 +	    &inp->inp_lport, &inp->inp_locia, cred);
  	if (error)
  		return (error);
  	if (in_pcbinshash(inp) != 0) {
  		inp->inp_laddr.s_addr = INADDR_ANY;
  		inp->inp_lport = 0;
 +		inp->inp_locia = NULL;
  		return (EAGAIN);
  	}
 +	if (inp->inp_locia != NULL)
 +		IFAREF(&inp->inp_locia->ia_ifa);
  	if (anonport)
  		inp->inp_flags |= INP_ANONPORT;
  	return (0);
 @@ -262,12 +265,13 @@
   */
  int
  in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
 -    u_short *lportp, struct ucred *cred)
 +    u_short *lportp, struct in_ifaddr **iap, struct ucred *cred)
  {
  	struct socket *so = inp->inp_socket;
  	unsigned short *lastport;
  	struct sockaddr_in *sin;
  	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 +	struct in_ifaddr *ia = NULL;
  	struct in_addr laddr;
  	u_short lport = 0;
  	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
 @@ -319,7 +323,8 @@
  		} else if (sin->sin_addr.s_addr != INADDR_ANY) {
  			sin->sin_port = 0;		/* yech... */
  			bzero(&sin->sin_zero, sizeof(sin->sin_zero));
 -			if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
 +			if ((ia = (struct in_ifaddr *)ifa_ifwithaddr(
 +			    (struct sockaddr *)sin)) == 0)
  				return (EADDRNOTAVAIL);
  		}
  		laddr = sin->sin_addr;
 @@ -478,6 +483,8 @@
  		return (EINVAL);
  	*laddrp = laddr.s_addr;
  	*lportp = lport;
 +	if (iap != NULL)
 +		*iap = ia;
  	return (0);
  }
  
 @@ -490,6 +497,7 @@
  int
  in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
  {
 +	struct in_ifaddr *locia;
  	u_short lport, fport;
  	in_addr_t laddr, faddr;
  	int anonport, error;
 @@ -501,7 +509,7 @@
  	laddr = inp->inp_laddr.s_addr;
  	anonport = (lport == 0);
  	error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport,
 -	    NULL, cred);
 +	    NULL, &locia, cred);
  	if (error)
  		return (error);
  
 @@ -519,6 +527,9 @@
  	/* Commit the remaining changes. */
  	inp->inp_lport = lport;
  	inp->inp_laddr.s_addr = laddr;
 +	inp->inp_locia = locia;
 +	if (inp->inp_locia != NULL)
 +		IFAREF(&inp->inp_locia->ia_ifa);
  	inp->inp_faddr.s_addr = faddr;
  	inp->inp_fport = fport;
  	in_pcbrehash(inp);
 @@ -536,7 +547,9 @@
   * On entry, *laddrp and *lportp should contain the current local
   * address and port for the PCB; these are updated to the values
   * that should be placed in inp_laddr and inp_lport to complete
 - * the connect.
 + * the connect. If iap is not NULL, *iap is set to the interface
 + * address corresponding to *laddrp, if any, but no new reference
 + * to it has been added.
   *
   * On success, *faddrp and *fportp will be set to the remote address
   * and port. These are not updated in the error case.
 @@ -549,7 +562,7 @@
  int
  in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
      in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp,
 -    struct inpcb **oinpp, struct ucred *cred)
 +    struct inpcb **oinpp, struct in_ifaddr **iap, struct ucred *cred)
  {
  	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
  	struct in_ifaddr *ia;
 @@ -560,6 +573,7 @@
  	u_short lport, fport;
  	int error;
  
 +	ia = NULL;
  	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
  	INP_LOCK_ASSERT(inp);
  
 @@ -582,7 +596,7 @@
  		sa.sin_len = sizeof(sa);
  		sa.sin_family = AF_INET;
  		error = in_pcbbind_setup(inp, (struct sockaddr *)&sa,
 -		    &laddr.s_addr, &lport, cred);
 +		    &laddr.s_addr, &lport, &ia, cred);
  		if (error)
  			return (error);
  	}
 @@ -664,7 +678,7 @@
  	}
  	if (lport == 0) {
  		error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport,
 -		    cred);
 +		    &ia, cred);
  		if (error)
  			return (error);
  	}
 @@ -672,6 +686,8 @@
  	*lportp = lport;
  	*faddrp = faddr.s_addr;
  	*fportp = fport;
 +	if (iap != NULL)
 +		*iap = ia;
  	return (0);
  }
  
 @@ -720,6 +736,8 @@
  #endif /*IPSEC*/
  	inp->inp_gencnt = ++ipi->ipi_gencnt;
  	in_pcbremlists(inp);
 +	if (inp->inp_locia != NULL)
 +		IFAFREE(&inp->inp_locia->ia_ifa);
  	if (inp->inp_options)
  		(void)m_free(inp->inp_options);
  	ip_freemoptions(inp->inp_moptions);
 ==== //depot/user/bms/nethead/sys/netinet/in_pcb.h#1 - /home/bms/fp4/nethead/sys/netinet/in_pcb.h ====
 --- /tmp/tmp.23928.2	Sat Sep 23 18:32:59 2006
 +++ /home/bms/fp4/nethead/sys/netinet/in_pcb.h	Sat Sep 23 17:46:41 2006
 @@ -71,6 +71,7 @@
  struct in_endpoints {
  	u_int16_t	ie_fport;		/* foreign port */
  	u_int16_t	ie_lport;		/* local port */
 +	struct in_ifaddr *ie_locia;		/* locally bound address */
  	/* protocol dependent part, local and foreign addr */
  	union {
  		/* foreign host table entry */
 @@ -102,6 +103,7 @@
  #define inc_isipv6	inc_flags	/* temp compatability */
  #define	inc_fport	inc_ie.ie_fport
  #define	inc_lport	inc_ie.ie_lport
 +#define	inc_locia	inc_ie.ie_locia
  #define	inc_faddr	inc_ie.ie_faddr
  #define	inc_laddr	inc_ie.ie_laddr
  #define	inc6_faddr	inc_ie.ie6_faddr
 @@ -145,6 +147,7 @@
  	} inp_depend4;
  #define	inp_fport	inp_inc.inc_fport
  #define	inp_lport	inp_inc.inc_lport
 +#define	inp_locia	inp_inc.inc_locia
  #define	inp_faddr	inp_inc.inc_faddr
  #define	inp_laddr	inp_inc.inc_laddr
  #define	inp_ip_tos	inp_depend4.inp4_ip_tos
 @@ -332,6 +335,8 @@
  #define	INP_CHECK_SOCKAF(so, af)	(INP_SOCKAF(so) == af)
  
  #ifdef _KERNEL
 +struct in_ifaddr;
 +
  extern int	ipport_reservedhigh;
  extern int	ipport_reservedlow;
  extern int	ipport_lowfirstauto;
 @@ -346,11 +351,11 @@
  int	in_pcballoc(struct socket *, struct inpcbinfo *);
  int	in_pcbbind(struct inpcb *, struct sockaddr *, struct ucred *);
  int	in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
 -	    u_short *, struct ucred *);
 +	    u_short *, struct in_ifaddr **, struct ucred *);
  int	in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
  int	in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
  	    u_short *, in_addr_t *, u_short *, struct inpcb **,
 -	    struct ucred *);
 +	    struct in_ifaddr **, struct ucred *);
  void	in_pcbdetach(struct inpcb *);
  void	in_pcbdisconnect(struct inpcb *);
  void	in_pcbdrop(struct inpcb *);
 ==== //depot/user/bms/nethead/sys/netinet/tcp_output.c#1 - /home/bms/fp4/nethead/sys/netinet/tcp_output.c ====
 --- /tmp/tmp.23928.3	Sat Sep 23 18:32:59 2006
 +++ /home/bms/fp4/nethead/sys/netinet/tcp_output.c	Sat Sep 23 17:47:35 2006
 @@ -51,12 +51,15 @@
  #include <sys/sysctl.h>
  
  #include <net/route.h>
 +#include <net/if.h>
 +#include <net/if_var.h>
  
  #include <netinet/in.h>
  #include <netinet/in_systm.h>
  #include <netinet/ip.h>
  #include <netinet/in_pcb.h>
  #include <netinet/ip_var.h>
 +#include <netinet/in_var.h>
  #include <netinet/ip_options.h>
  #ifdef INET6
  #include <netinet6/in6_pcb.h>
 @@ -872,6 +875,16 @@
  		ipov = (struct ipovly *)ip;
  		th = (struct tcphdr *)(ip + 1);
  		tcpip_fillheaders(tp->t_inpcb, ip, th);
 +	}
 +
 +	/*
 +	 * Check that our local (source) IP address is still valid.
 +	 */
 +	if (tp->t_inpcb->inp_locia != NULL
 +	    && (tp->t_inpcb->inp_locia->ia_ifa.ifa_flags & RTF_REJECT) != 0) {
 +		error = EADDRNOTAVAIL;
 +		m_freem(m);
 +		goto out;
  	}
  
  	/*
 ==== //depot/user/bms/nethead/sys/netinet/tcp_usrreq.c#1 - /home/bms/fp4/nethead/sys/netinet/tcp_usrreq.c ====
 --- /tmp/tmp.23928.4	Sat Sep 23 18:33:00 2006
 +++ /home/bms/fp4/nethead/sys/netinet/tcp_usrreq.c	Sat Sep 23 17:53:09 2006
 @@ -1102,6 +1102,7 @@
  {
  	struct inpcb *inp = tp->t_inpcb, *oinp;
  	struct socket *so = inp->inp_socket;
 +	struct in_ifaddr *locia;
  	struct in_addr laddr;
  	u_short lport;
  	int error;
 @@ -1122,13 +1123,20 @@
  	 */
  	laddr = inp->inp_laddr;
  	lport = inp->inp_lport;
 +	locia = inp->inp_locia;
  	error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport,
 -	    &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred);
 +	    &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, &locia,
 +	    td->td_ucred);
  	if (error && oinp == NULL)
  		return error;
  	if (oinp)
  		return EADDRINUSE;
  	inp->inp_laddr = laddr;
 +	if (inp->inp_locia != NULL)
 +		IFAFREE(&inp->inp_locia->ia_ifa);
 +	inp->inp_locia = locia;
 +	if (inp->inp_locia != NULL)
 +		IFAREF(&inp->inp_locia->ia_ifa);
  	in_pcbrehash(inp);
  
  	/* Compute window scaling to request.  */
 ==== //depot/user/bms/nethead/sys/netinet/udp_usrreq.c#1 - /home/bms/fp4/nethead/sys/netinet/udp_usrreq.c ====
 --- /tmp/tmp.23928.5	Sat Sep 23 18:33:00 2006
 +++ /home/bms/fp4/nethead/sys/netinet/udp_usrreq.c	Sat Sep 23 17:51:24 2006
 @@ -724,6 +724,7 @@
  {
  	register struct udpiphdr *ui;
  	register int len = m->m_pkthdr.len;
 +	struct in_ifaddr *locia;
  	struct in_addr faddr, laddr;
  	struct cmsghdr *cm;
  	struct sockaddr_in *sin, src;
 @@ -809,13 +810,14 @@
  
  	laddr = inp->inp_laddr;
  	lport = inp->inp_lport;
 +	locia = inp->inp_locia;
  	if (src.sin_addr.s_addr != INADDR_ANY) {
  		if (lport == 0) {
  			error = EINVAL;
  			goto release;
  		}
  		error = in_pcbbind_setup(inp, (struct sockaddr *)&src,
 -		    &laddr.s_addr, &lport, td->td_ucred);
 +		    &laddr.s_addr, &lport, &locia, td->td_ucred);
  		if (error)
  			goto release;
  	}
 @@ -829,7 +831,7 @@
  			goto release;
  		}
  		error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport,
 -		    &faddr.s_addr, &fport, NULL, td->td_ucred);
 +		    &faddr.s_addr, &fport, NULL, &locia, td->td_ucred);
  		if (error)
  			goto release;
  
 @@ -859,6 +861,14 @@
  	}
  
  	/*
 +	 * Check that the local (source) IP address is valid.
 +	 */
 +	if (locia != NULL && (locia->ia_ifa.ifa_flags & RTF_REJECT) != 0) {
 +		error = EADDRNOTAVAIL;
 +		goto release;
 +	}
 +
 +	/*
  	 * Calculate data length and get a mbuf for UDP, IP, and possible
  	 * link-layer headers.  Immediate slide the data pointer back forward
  	 * since we won't use that space at this layer.
 @@ -1088,6 +1098,10 @@
  
  	in_pcbdisconnect(inp);
  	inp->inp_laddr.s_addr = INADDR_ANY;
 +	if (inp->inp_locia != NULL) {
 +		IFAFREE(&inp->inp_locia->ia_ifa);
 +		inp->inp_locia = NULL;
 +	}
  	SOCK_LOCK(so);
  	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
  	SOCK_UNLOCK(so);
 
 --------------030000070707080504040106--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609231740.k8NHeOX0046882>