Neil,

Thanks for the patches... here are some comments:

* You've obviously put a lot of effort into understanding the code to write
this patch.  But did you consider any alternative approaches, such as starting
multiple OpenVPN instances and binding each to a separate local interface?

* A lot of function prototypes get changed so that both from and to
sockaddr_in pointers must be passed.  Do you think it might make more sense to
make a new struct that represents a bidirectional socketaddr_in and embed from
and to inside of it?  I'm mostly thinking about this from the angle of easing
future maintenance.  As much as is possible, I would like to see this patch
live in it's own location (probably a separate source file) and require a
minimal amount of modification of existing code.

* It would be nice to see the #ifdef IP_PKTINFO code (which appears to be
non-portable) isolated somewhere and bracketed inside of an internal API which
would make it easy for different cases to be implemented for different OSes.

* The change to link_socket_set_outgoing_addr is probably okay, though
remember that this is in the main line event loop, so efficiency is important
here.  Most of link_socket_set_outgoing_addr is structured around the fact
that a bunch of special things need to happen if the remote address changes,
but what similar kinds of things need to happen when the local address changes?

James

Neil Brown <ne...@cse.unsw.edu.au> said:

> 
> Hi.
>  This is the first of 4 patches that I would like to offer for
>  openvpn.
>  They are against 2.0_beta7.
> 
> This first one is a refinement of a patch I posted earlier which, at
> that time, didn't work.
> The purpose of the patch is to use the IP_PKTINFO socket option to get
> and set the local address for UDP packets being sent or received.
> This means that if you have a multihomed server, then packets sent to
> it will always come from the address that they corresponding packets
> were sent to.  This is needed to pass cleanly through a NAT.
> 
> In replaces "struct sockaddr_in from" in "struct context_2" with
>  struct sockaddr_in incoming_from, incoming_to
> and records the address provided by IP_PKTINFO in incoming_to.
> 
> It adds "struct sockaddr_in actuallocal" alongside "struct sockaddr_in
> actual" in  "struct lock_socket_addr", for storing the local enpoint
> if a udp "connection" in this structure.
> 
> It adds "struct sockaddr_in local_addr"  alongside "remote_addr" in 
> "struct key_state" for a similar purpose.
> 
> And it makes sure these fields are set and used appropriately.
> 
> The main reason that it didn't work before was that in
> multi_process_incoming_link, when the packet and address are
> transferred from the "mt" structure into the per-session context
> structure, I wasn't copying the incoming_to address as well.  I do now.
> 
> One part of the change that I am not completely happy with is
> +      /* alway set localaddr address */
> +      info->lsa->actuallocal = *localaddr;
> in link_socket_set_outgoing_addr.
> The current code only changes the outgoing address if it has changed,
> and it does that inside link_socket_connection_initiated.  However it
> is possible for the localaddress to change without the remote address
> changing.
> e.g. If I stop and restart my openvpn instance on my notebook, and it
> gets a different IP address via DNS lookup.  In this case it will
> appear to be a continuation of the same session, but will need to use
> a different local address.  I think it is OK to change the
> localaddress on every packet, but I am open to be convinced otherwise,
> or that the code could be cleaner.
> 
> Anyway, here is the patch.  I hope it can be included in an upcoming
> beta of openvpn.
> 
> Thanks,
> NeilBrown
> 
>  
> ============================================
> 
> ### Diffstat output
>  ./forward.c |   23 ++++++++++++--------
>  ./multi.c   |   10 +++++---
>  ./openvpn.h |    5 +++-
>  ./socket.c  |   46 ++++++++++++++++++++++++++++++++++++++++-
>  ./socket.h  |   67 
> ++++++++++++++++++++++++++++++++++++++++++++++++++----------
>  ./ssl.c     |   25 +++++++++++++++++-----
>  ./ssl.h     |    4 +++
>  7 files changed, 148 insertions(+), 32 deletions(-)
> 
> diff ./forward.c~current~ ./forward.c
> --- ./forward.c~current~      2004-07-09 19:56:34.000000000 +1000
> +++ ./forward.c       2004-07-26 14:02:07.000000000 +1000
> @@ -87,6 +87,7 @@ check_tls_dowork (struct context *c)
>      {
>        if (tls_multi_process
>         (c->c2.tls_multi, &c->c2.to_link, &c->c2.to_link_addr,
> +        &c->c2.from_link_addr,
>          get_link_socket_info (c), &wakeup))
>       {
>         update_time ();
> @@ -342,7 +343,7 @@ encrypt_sign (struct context *c, bool co
>     * Get the address we will be sending the packet to.
>     */
>    link_socket_get_outgoing_addr (&c->c2.buf, get_link_socket_info (c),
> -                              &c->c2.to_link_addr);
> +                              &c->c2.to_link_addr, &c->c2.from_link_addr);
>  #ifdef USE_CRYPTO
>  #ifdef USE_SSL
>    /*
> @@ -463,7 +464,7 @@ static inline void
>  socks_postprocess_incoming_link (struct context *c)
>  {
>    if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto ==
PROTO_UDPv4)
> -    socks_process_incoming_udp (&c->c2.buf, &c->c2.from);
> +    socks_process_incoming_udp (&c->c2.buf, &c->c2.incoming_from);
>  }
>  
>  static inline void
> @@ -505,7 +506,8 @@ read_incoming_link (struct context *c)
>  
>    c->c2.buf = c->c2.buffers->read_link_buf;
>    ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame)));
> -  status = link_socket_read (c->c2.link_socket, &c->c2.buf,
MAX_RW_SIZE_LINK (&c->c2.frame), &c->c2.from);
> +  status = link_socket_read (c->c2.link_socket, &c->c2.buf,
MAX_RW_SIZE_LINK (&c->c2.frame),
> +                          &c->c2.incoming_from, &c->c2.incoming_to);
>  
>    if (socket_connection_reset (c->c2.link_socket, status))
>      {
> @@ -561,7 +563,7 @@ process_incoming_link (struct context *c
>    msg (D_LINK_RW, "%s READ [%d] from %s: %s",
>         proto2ascii (lsi->proto, true),
>         BLEN (&c->c2.buf),
> -       print_sockaddr (&c->c2.from, &gc),
> +       print_sockaddr (&c->c2.incoming_from, &gc),
>         PROTO_DUMP (&c->c2.buf, &gc));
>  
>    /*
> @@ -573,8 +575,8 @@ process_incoming_link (struct context *c
>     */
>    if (c->c2.buf.len > 0)
>      {
> -      if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi, &c->c2.from))
> -     link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.from);
> +      if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi,
&c->c2.incoming_from))
> +     link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.incoming_from);
>  
>  #ifdef USE_CRYPTO
>  #ifdef USE_SSL
> @@ -591,7 +593,9 @@ process_incoming_link (struct context *c
>          * and return false.
>          */
>         //tls_mutex_lock (c->c2.tls_multi);
> -       if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf,
&c->c2.crypto_options))
> +       if (tls_pre_decrypt (c->c2.tls_multi,
> +                            &c->c2.incoming_from, &c->c2.incoming_to,
> +                            &c->c2.buf, &c->c2.crypto_options))
>           {
>             interval_action (&c->c2.tmp_int);
>  
> @@ -641,7 +645,7 @@ process_incoming_link (struct context *c
>         * Also, update the persisted version of our packet-id.
>         */
>        if (!TLS_MODE)
> -     link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL);
> +     link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.incoming_from,
&c->c2.incoming_to, NULL);
>  
>        /* reset packet received timer */
>        if (c->options.ping_rec_timeout && c->c2.buf.len > 0)
> @@ -826,7 +830,8 @@ process_outgoing_link (struct context *c
>           socks_preprocess_outgoing_link (c, &to_addr, &size_delta);
>  
>           /* Send packet */
> -         size = link_socket_write (c->c2.link_socket, &c->c2.to_link, 
> to_addr);
> +         size = link_socket_write (c->c2.link_socket, &c->c2.to_link, 
> to_addr,
> +                                   &c->c2.from_link_addr);
>  
>           /* Undo effect of prepend */
>           link_socket_write_post_size_adjust (&size, size_delta, 
> &c->c2.to_link);
> 
> diff ./multi.c~current~ ./multi.c
> --- ./multi.c~current~        2004-07-26 14:36:28.000000000 +1000
> +++ ./multi.c 2004-07-26 14:36:35.000000000 +1000
> @@ -544,7 +544,7 @@ multi_get_create_instance (struct multi_
>    struct multi_instance *mi = NULL;
>    struct hash *hash = mt->multi->hash;
>  
> -  if (mroute_extract_sockaddr_in (&real, &mt->top.c2.from, true))
> +  if (mroute_extract_sockaddr_in (&real, &mt->top.c2.incoming_from, true))
>      {
>        struct hash_element *he;
>        const uint32_t hv = hash_value (hash, &real);
> @@ -560,7 +560,8 @@ multi_get_create_instance (struct multi_
>        else
>       {
>         if (!mt->top.c2.tls_auth_standalone
> -           || tls_pre_decrypt_lite (mt->top.c2.tls_auth_standalone,
&mt->top.c2.from, &mt->top.c2.buf))
> +           || tls_pre_decrypt_lite (mt->top.c2.tls_auth_standalone,
> +                                    &mt->top.c2.incoming_from, 
> &mt->top.c2.incoming_to,
&mt->top.c2.buf))
>           {
>             if (frequency_limit_event_allowed 
> (mt->multi->new_connection_limiter))
>               {
> @@ -1330,8 +1331,9 @@ multi_process_incoming_link (struct mult
>        /* transfer packet pointer from top-level context buffer to instance */
>        c->c2.buf = mt->top.c2.buf;
>  
> -      /* transfer from-addr from top-level context buffer to instance */
> -      c->c2.from = mt->top.c2.from;
> +      /* transfer from-addr and to-addr from top-level context buffer to
instance */
> +      c->c2.incoming_from = mt->top.c2.incoming_from;
> +      c->c2.incoming_to = mt->top.c2.incoming_to;
>  
>        /* decrypt in instance context */
>        process_incoming_link (c);
> 
> diff ./openvpn.h~current~ ./openvpn.h
> --- ./openvpn.h~current~      2004-07-09 19:56:34.000000000 +1000
> +++ ./openvpn.h       2004-07-26 13:00:39.000000000 +1000
> @@ -167,7 +167,10 @@ struct context_2
>    const struct link_socket *accept_from; /* possibly do accept() on a
parent link_socket */
>  
>    struct sockaddr_in to_link_addr;    /* IP address of remote */
> -  struct sockaddr_in from;               /* address of incoming datagram */
> +  struct sockaddr_in from_link_addr;  /* Address to send messages from */
> +
> +  struct sockaddr_in incoming_from;      /* address of incoming datagram */
> +  struct sockaddr_in incoming_to;     /* address incoming datagram was to */
>  
>    /* MTU frame parameters */
>    struct frame frame;
> 
> diff ./socket.c~current~ ./socket.c
> --- ./socket.c~current~       2004-07-09 19:56:34.000000000 +1000
> +++ ./socket.c        2004-07-27 11:41:34.000000000 +1000
> @@ -392,6 +392,12 @@ create_socket_udp (void)
>  
>    if ((sd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
>      msg (M_SOCKERR, "UDP: Cannot create UDP socket");
> +#ifdef IP_PKTINFO
> +  else {
> +       int pad = 1;
> +       setsockopt(sd, SOL_IP, IP_PKTINFO, (void*)&pad, sizeof(pad));
> +  }
> +#endif
>    return sd;
>  }
>  
> @@ -1135,6 +1141,7 @@ void
>  link_socket_connection_initiated (const struct buffer *buf,
>                                 struct link_socket_info *info,
>                                 const struct sockaddr_in *addr,
> +                               const struct sockaddr_in *localaddr,
>                                 const char *common_name)
>  {
>    struct gc_arena gc = gc_new ();
> @@ -1143,6 +1150,7 @@ link_socket_connection_initiated (const 
>    mutex_lock_static (L_SCRIPT);
>  
>    info->lsa->actual = *addr; /* Note: skip this line for --force-dest */
> +  info->lsa->actuallocal = *localaddr;
>    setenv_trusted (info);
>    info->connection_established = true;
>  
> @@ -1582,13 +1590,49 @@ int
>  link_socket_read_udp_posix (struct link_socket *sock,
>                           struct buffer *buf,
>                           int maxsize,
> -                         struct sockaddr_in *from)
> +                         struct sockaddr_in *from,
> +                         struct sockaddr_in *to)
>  {
>    socklen_t fromlen = sizeof (*from);
>    CLEAR (*from);
> +  CLEAR (*to);
>    ASSERT (buf_safe (buf, maxsize));
> +#ifdef IP_PKTINFO
> +  {
> +    struct iovec iov;
> +    char b[sizeof(struct cmsghdr)+sizeof(struct in_pktinfo)];
> +    struct msghdr mesg;
> +    iov.iov_base = BPTR (buf);
> +    iov.iov_len = maxsize;
> +    mesg.msg_iov = &iov;
> +    mesg.msg_iovlen = 1;
> +    mesg.msg_name = from;
> +    mesg.msg_namelen = fromlen;
> +    mesg.msg_control = b;
> +    mesg.msg_controllen = sizeof(b);
> +    CLEAR(*to);
> +    buf->len = recvmsg (sock->sd, &mesg, 0);
> +    if (buf->len >= 0) 
> +     {
> +       struct cmsghdr *cmsg;
> +       fromlen = mesg.msg_namelen;
> +       cmsg = CMSG_FIRSTHDR (&mesg);
> +       if (cmsg != NULL
> +        && CMSG_NXTHDR (&mesg, cmsg) == NULL
> +        && cmsg->cmsg_level == SOL_IP 
> +        && cmsg->cmsg_type == IP_PKTINFO
> +        && cmsg->cmsg_len >= (sizeof (struct cmsghdr)
> +                              + sizeof (struct in_pktinfo))) 
> +        {
> +            struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
> +            to->sin_addr = pkti->ipi_addr;
> +        }
> +      }
> +  }
> +#else
>    buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,
>                      (struct sockaddr *) from, &fromlen);
> +#endif
>    if (fromlen != sizeof (*from))
>      bad_address_length (fromlen, sizeof (*from));
>    return buf->len;
> 
> diff ./socket.h~current~ ./socket.h
> --- ./socket.h~current~       2004-07-09 19:56:34.000000000 +1000
> +++ ./socket.h        2004-07-27 11:40:04.000000000 +1000
> @@ -70,6 +70,7 @@ struct link_socket_addr
>    struct sockaddr_in local;
>    struct sockaddr_in remote; /* initial remote */
>    struct sockaddr_in actual; /* remote may change due to --float */
> +  struct sockaddr_in actuallocal; /* make sure we reply from  right address 
> */
>  };
>  
>  struct link_socket_info
> @@ -273,6 +274,7 @@ in_addr_t link_socket_current_remote (co
>  void link_socket_connection_initiated (const struct buffer *buf,
>                                      struct link_socket_info *info,
>                                      const struct sockaddr_in *addr,
> +                                    const struct sockaddr_in *localaddr,
>                                      const char *common_name);
>  
>  void link_socket_bad_incoming_addr (struct buffer *buf,
> @@ -443,7 +445,8 @@ link_socket_verify_incoming_addr (struct
>  static inline void
>  link_socket_get_outgoing_addr (struct buffer *buf,
>                             const struct link_socket_info *info,
> -                           struct sockaddr_in *addr)
> +                           struct sockaddr_in *addr,
> +                           struct sockaddr_in *fromaddr)
>  {
>    if (buf->len > 0)
>      {
> @@ -453,6 +456,10 @@ link_socket_get_outgoing_addr (struct bu
>         addr->sin_family = lsa->actual.sin_family;
>         addr->sin_addr.s_addr = lsa->actual.sin_addr.s_addr;
>         addr->sin_port = lsa->actual.sin_port;
> +
> +       fromaddr->sin_family = lsa->actuallocal.sin_family;
> +       fromaddr->sin_addr.s_addr = lsa->actuallocal.sin_addr.s_addr;
> +       fromaddr->sin_port = lsa->actuallocal.sin_port;
>       }
>        else
>       {
> @@ -466,6 +473,7 @@ static inline void
>  link_socket_set_outgoing_addr (const struct buffer *buf,
>                              struct link_socket_info *info,
>                              const struct sockaddr_in *addr,
> +                            const struct sockaddr_in *localaddr,
>                              const char *common_name)
>  {
>    if (!buf || buf->len > 0)
> @@ -481,8 +489,10 @@ link_socket_set_outgoing_addr (const str
>             || addr_match_proto (addr, &lsa->remote, info->proto))
>         )
>       {
> -       link_socket_connection_initiated (buf, info, addr, common_name);
> +       link_socket_connection_initiated (buf, info, addr, localaddr, 
> common_name);
>       }
> +      /* alway set localaddr address */
> +      info->lsa->actuallocal = *localaddr;
>      }
>  }
>  
> @@ -528,7 +538,8 @@ link_socket_read_udp_win32 (struct link_
>  int link_socket_read_udp_posix (struct link_socket *sock,
>                               struct buffer *buf,
>                               int maxsize,
> -                             struct sockaddr_in *from);
> +                             struct sockaddr_in *from,
> +                             struct sockaddr_in *to);
>  
>  #endif
>  
> @@ -537,16 +548,17 @@ static inline int
>  link_socket_read (struct link_socket *sock,
>                 struct buffer *buf,
>                 int maxsize,
> -               struct sockaddr_in *from)
> +               struct sockaddr_in *from,
> +               struct sockaddr_in *to)
>  {
>    if (sock->info.proto == PROTO_UDPv4)
>      {
>        int res;
> -
> +      CLEAR (*to);
>  #ifdef WIN32
>        res = link_socket_read_udp_win32 (sock, buf, from);
>  #else
> -      res = link_socket_read_udp_posix (sock, buf, maxsize, from);
> +      res = link_socket_read_udp_posix (sock, buf, maxsize, from, to);
>  #endif
>        return res;
>      }
> @@ -601,8 +613,39 @@ link_socket_write_win32 (struct link_soc
>  static inline int
>  link_socket_write_udp_posix (struct link_socket *sock,
>                            struct buffer *buf,
> -                          struct sockaddr_in *to)
> +                          struct sockaddr_in *to,
> +                          struct sockaddr_in *from)
>  {
> +#ifdef IP_PKTINFO
> + if (addr_defined(from)) 
> +   {
> +     struct iovec iov;
> +     struct msghdr mesg;
> +     struct cmsghdr *cmsg;
> +     struct in_pktinfo *pkti;
> +
> +     char b[sizeof(struct cmsghdr)+sizeof(struct in_pktinfo)];
> +     iov.iov_base = BPTR (buf);
> +     iov.iov_len = BLEN (buf);
> +     mesg.msg_iov = &iov;
> +     mesg.msg_iovlen = 1;
> +     mesg.msg_name = to;
> +     mesg.msg_namelen = sizeof(*to);
> +     mesg.msg_control = b;
> +     mesg.msg_controllen = sizeof(b);
> +     mesg.msg_flags = 0;
> +     cmsg = CMSG_FIRSTHDR(&mesg);
> +     cmsg->cmsg_len = sizeof(b);
> +     cmsg->cmsg_level = SOL_IP;
> +     cmsg->cmsg_type = IP_PKTINFO;
> +     pkti = (struct in_pktinfo *)CMSG_DATA(cmsg);
> +     pkti->ipi_ifindex = 0;
> +     pkti->ipi_spec_dst = from->sin_addr;
> +     pkti->ipi_addr = from->sin_addr;
> +
> +     return sendmsg (sock->sd, &mesg, 0);
> +   }
> +#endif
>    return sendto (sock->sd, BPTR (buf), BLEN (buf), 0,
>                (struct sockaddr *) to,
>                (socklen_t) sizeof (*to));
> @@ -621,12 +664,13 @@ link_socket_write_tcp_posix (struct link
>  static inline int
>  link_socket_write_udp (struct link_socket *sock,
>                      struct buffer *buf,
> -                    struct sockaddr_in *to)
> +                    struct sockaddr_in *to,
> +                    struct sockaddr_in *from)
>  {
>  #ifdef WIN32
>    return link_socket_write_win32 (sock, buf, to);
>  #else
> -  return link_socket_write_udp_posix (sock, buf, to);
> +  return link_socket_write_udp_posix (sock, buf, to, from);
>  #endif
>  }
>  
> @@ -634,11 +678,12 @@ link_socket_write_udp (struct link_socke
>  static inline int
>  link_socket_write (struct link_socket *sock,
>                  struct buffer *buf,
> -                struct sockaddr_in *to)
> +                struct sockaddr_in *to,
> +                struct sockaddr_in *from)
>  {
>    if (sock->info.proto == PROTO_UDPv4)
>      {
> -      return link_socket_write_udp (sock, buf, to);
> +      return link_socket_write_udp (sock, buf, to, from);
>      }
>    else if (sock->info.proto == PROTO_TCPv4_SERVER || sock->info.proto ==
PROTO_TCPv4_CLIENT)
>      {
> 
> diff ./ssl.c~current~ ./ssl.c
> --- ./ssl.c~current~  2004-07-09 19:56:34.000000000 +1000
> +++ ./ssl.c   2004-07-09 19:58:00.000000000 +1000
> @@ -1494,6 +1494,7 @@ write_control_auth (struct tls_session *
>                   struct key_state *ks,
>                   struct buffer *buf,
>                   struct sockaddr_in *to_link_addr,
> +                 struct sockaddr_in *from_link_addr,
>                   int opcode,
>                   int max_ack,
>                   bool prepend_ack)
> @@ -1514,6 +1515,7 @@ write_control_auth (struct tls_session *
>        ASSERT (swap_hmac (buf, &session->tls_auth, false));
>      }
>    *to_link_addr = ks->remote_addr;
> +  *from_link_addr = ks->local_addr;
>  }
>  
>  /*
> @@ -1916,6 +1918,7 @@ key_state_soft_reset (struct tls_session
>    key_state_init (session, ks);
>    ks->session_id_remote = ks_lame->session_id_remote;
>    ks->remote_addr = ks_lame->remote_addr;
> +  ks->local_addr = ks_lame->local_addr;
>  }
>  
>  /*
> @@ -1932,6 +1935,7 @@ tls_process (struct tls_multi *multi,
>            struct tls_session *session,
>            struct buffer *to_link,
>            struct sockaddr_in *to_link_addr,
> +          struct sockaddr_in *from_link_addr,
>            struct link_socket_info *to_link_socket_info,
>            interval_t *wakeup)
>  {
> @@ -2052,7 +2056,8 @@ tls_process (struct tls_multi *multi,
>                 INCR_SUCCESS;
>  
>                 /* Set outgoing address for data channel packets */
> -               link_socket_set_outgoing_addr (NULL, to_link_socket_info,
&ks->remote_addr, session->common_name);
> +               link_socket_set_outgoing_addr (NULL, to_link_socket_info, 
> &ks->remote_addr,
> +                                              &ks->local_addr, 
> session->common_name);
>  
>  #ifdef MEASURE_TLS_HANDSHAKE_STATS
>                 show_tls_performance_stats();
> @@ -2072,7 +2077,8 @@ tls_process (struct tls_multi *multi,
>             b = *buf;
>             INCR_SENT;
>  
> -           write_control_auth (session, ks, &b, to_link_addr, opcode,
> +           write_control_auth (session, ks, &b, to_link_addr, 
> +                               from_link_addr, opcode,
>                                 CONTROL_SEND_ACK_MAX, true);
>             *to_link = b;
>             active = true;
> @@ -2087,7 +2093,8 @@ tls_process (struct tls_multi *multi,
>           {
>             buf = &ks->ack_write_buf;
>             ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame)));
> -           write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1,
> +           write_control_auth (session, ks, buf, to_link_addr, 
> from_link_addr,
> +                               P_ACK_V1,
>                                 RELIABLE_ACK_SIZE, false);
>             *to_link = *buf;
>             active = true;
> @@ -2391,7 +2398,7 @@ tls_process (struct tls_multi *multi,
>      {
>        buf = &ks->ack_write_buf;
>        ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame)));
> -      write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1,
> +      write_control_auth (session, ks, buf, to_link_addr, from_link_addr,
P_ACK_V1,
>                         RELIABLE_ACK_SIZE, false);
>        *to_link = *buf;
>        active = true;
> @@ -2453,6 +2460,7 @@ bool
>  tls_multi_process (struct tls_multi *multi,
>                  struct buffer *to_link,
>                  struct sockaddr_in *to_link_addr,
> +                struct sockaddr_in *from_link_addr,
>                  struct link_socket_info *to_link_socket_info,
>                  interval_t *wakeup)
>  {
> @@ -2473,8 +2481,10 @@ tls_multi_process (struct tls_multi *mul
>  
>        /* set initial remote address */
>        if (i == TM_ACTIVE && ks->state == S_INITIAL &&
> -       addr_defined (&to_link_socket_info->lsa->actual))
> +       addr_defined (&to_link_socket_info->lsa->actual)) {
>       ks->remote_addr = to_link_socket_info->lsa->actual;
> +     ks->local_addr = to_link_socket_info->lsa->actuallocal;
> +      }
>  
>        msg (D_TLS_DEBUG,
>          "TLS: tls_multi_process: i=%d state=%s, mysid=%s, stored-sid=%s,
stored-ip=%s",
> @@ -2488,7 +2498,7 @@ tls_multi_process (struct tls_multi *mul
>       {
>         update_time ();
>  
> -       if (tls_process (multi, session, to_link, to_link_addr,
> +       if (tls_process (multi, session, to_link, to_link_addr, 
> from_link_addr,
>                          to_link_socket_info, wakeup))
>           active = true;
>  
> @@ -2617,6 +2627,7 @@ tls_rec_payload (struct tls_multi *multi
>  bool
>  tls_pre_decrypt (struct tls_multi *multi,
>                struct sockaddr_in *from,
> +              struct sockaddr_in *to,
>                struct buffer *buf,
>                struct crypto_options *opt)
>  {
> @@ -2919,6 +2930,7 @@ tls_pre_decrypt (struct tls_multi *multi
>             {
>               ks->session_id_remote = sid;
>               ks->remote_addr = *from;
> +             ks->local_addr = *to;
>               ++multi->n_sessions;
>             }
>           else if (!addr_port_match (&ks->remote_addr, from))
> @@ -3023,6 +3035,7 @@ tls_pre_decrypt (struct tls_multi *multi
>  bool
>  tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
>                     const struct sockaddr_in *from,
> +                   const struct sockaddr_in *to,
>                     const struct buffer *buf)
>  {
>    struct gc_arena gc = gc_new ();
> 
> diff ./ssl.h~current~ ./ssl.h
> --- ./ssl.h~current~  2004-07-09 19:56:34.000000000 +1000
> +++ ./ssl.h   2004-07-09 19:58:18.000000000 +1000
> @@ -236,6 +236,7 @@ struct key_state
>    int initial_opcode;                /* our initial P_ opcode */
>    struct session_id session_id_remote; /* peer's random session ID */
>    struct sockaddr_in remote_addr;      /* peer's IP addr */
> +  struct sockaddr_in local_addr;       /* address peer expects reply from */
>    struct packet_id packet_id;               /* for data channel, to prevent 
> replay
attacks */
>  
>    struct key_ctx_bi key;            /* data channel keys for
encrypt/decrypt/hmac */
> @@ -456,6 +457,7 @@ void tls_multi_init_set_options(struct t
>  bool tls_multi_process (struct tls_multi *multi,
>                       struct buffer *to_link,
>                       struct sockaddr_in *to_link_addr,
> +                     struct sockaddr_in *from_link_addr,
>                       struct link_socket_info *to_link_socket_info,
>                       interval_t *wakeup);
>  
> @@ -463,11 +465,13 @@ void tls_multi_free (struct tls_multi *m
>  
>  bool tls_pre_decrypt (struct tls_multi *multi,
>                     struct sockaddr_in *from,
> +                   struct sockaddr_in *to,
>                     struct buffer *buf,
>                     struct crypto_options *opt);
>  
>  bool tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
>                          const struct sockaddr_in *from,
> +                        const struct sockaddr_in *to,
>                          const struct buffer *buf);
>  
>  void tls_pre_encrypt (struct tls_multi *multi,
> 
> 



-- 




Reply via email to