The following reply was made to PR kern/38554; it has been noted by GNATS.

From: Bruce M Simpson <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
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--
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to