title: MSG_PROXY not working to provide/specify alternate addresses for transparent proxying
body: <p>I'm trying to write a transparent proxy that translates arbitrary UDP packets to a custom protocol and back again.  I'm trying to use transparent proxying to read the incoming UDP packets that need translation, and to write the outgoing UDP packets that have just been reverse-translated.</p>
  
  <p>My setup for the socket I use for both flavors of UDP sockets is as follows:</p>
  
  <pre><code>static int
  setup_clear_sock(uint16_t proxy_port)
  {
      struct sockaddr_in saddr;
      int sock;
      int val = 1;
      socklen_t ttllen = sizeof(std_ttl);
  
      sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if (sock &lt; 0)
      {
          perror("Failed to create clear proxy socket");
          return -1;
      }
      if (getsockopt(sock, IPPROTO_IP, IP_TTL, &amp;std_ttl, &amp;ttllen) &lt; 0)
      {
          perror("Failed to read IP TTL option on clear proxy socket");
          return -1;
      }
      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &amp;val, sizeof(val)) &lt; 0)
      {
          perror("Failed to set reuse address option on clear socket");
          return -1;
      }
      if (setsockopt(sock, IPPROTO_IP, IP_TRANSPARENT, &amp;val, sizeof(val)) &lt; 0)
      {
          perror("Failed to set transparent proxy option on clear socket");
          return -1;
      }
      saddr.sin_family = AF_INET;
      saddr.sin_port = htons(proxy_port);
      saddr.sin_addr.s_addr = INADDR_ANY;
      if (bind(sock, (struct sockaddr *) &amp;saddr, sizeof(saddr)) &lt; 0)
      {
          perror("Failed to bind local address to clear proxy socket");
          return -1;
      }
  
      return sock;
  }
  </code></pre>
  
  <p>I have two distinct, but possibly related problems.  First, when I read an incoming UDP packet from this socket, using this code:</p>
  
  <pre><code>struct sock_double_addr_in
  {
      __SOCKADDR_COMMON (sin_);
      in_port_t sin_port_a;
      struct in_addr sin_addr_a;
      sa_family_t sin_family_b;
      in_port_t sin_port_b;
      struct in_addr sin_addr_b;
      unsigned char sin_zero[sizeof(struct sockaddr) - __SOCKADDR_COMMON_SIZE - 8
                               - sizeof(struct in_addr) - sizeof(in_port_t)];
  };
  
  
  void
  handle_clear_sock(void)
  {
      ssize_t rcvlen;
      uint16_t nbo_udp_len, coded_len;
      struct sockaddr_in saddr;
      struct sock_double_addr_in sdaddr;
      bch_coding_context_t ctx;
      socklen_t addrlen = sizeof(sdaddr);
  
      rcvlen = recvfrom(sock_clear, &amp;clear_buf, sizeof(clear_buf),
                        MSG_DONTWAIT | MSG_PROXY,
                        (struct sockaddr *) &amp;sdaddr, &amp;addrlen);
      if (rcvlen &lt; 0)
      {
          perror("Failed to receive a packet from clear socket");
          return;
      }
  
      ....
  </code></pre>
  
  <p>I don't see a destination address come back in sdaddr.  The sin_family_b, sin_addr_b, and sin_port_b fields are all zero.  I've done a block memory dump of the structure in gdb, and indeed the bytes are coming back zero from the kernel (it's not a bad placement of the field in my structure definition).</p>
  
  <p>Temporarily working around this by hard-coding a fixed IP address and port for testing purposes, I can debug the rest of my proxy application until I get to the point of sending an outgoing UDP packet that has just been reverse-translated.  That happens with this code:</p>
  
  <pre><code>    ....
  
      udp_len = ntohs(clear_buf.u16[2]);
      if (udp_len + 6 &gt; decoded_len)
          fprintf(stderr, "Decoded fewer bytes (%u) than outputting in clear "
                          "(6 + %u)!\n", decoded_len, udp_len);
  
      sdaddr.sin_family = AF_INET;
      sdaddr.sin_port_a = clear_buf.u16[0];
      sdaddr.sin_addr_a.s_addr = coded_buf.u32[4];
      sdaddr.sin_family_b = AF_INET;
      sdaddr.sin_port_b = clear_buf.u16[1];
      sdaddr.sin_addr_b.s_addr = coded_buf.u32[3];
      if (sendto(sock_clear, &amp;(clear_buf.u16[3]), udp_len, MSG_PROXY,
                 (struct sockaddr *) &amp;sdaddr, sizeof(sdaddr)) &lt; 0)
          perror("Failed to send a packet on clear socket");
  }
  </code></pre>
  
  <p>and the packet never shows up.  I've checked the entire contents of the sdaddr structure I've built, and all fields look good.  The UDP payload data looks good.  There's no error coming back from the sendto() syscall -- indeed, it returns zero.  And the packet never shows up in wireshark.</p>
  
  <p>So what's going on with my transparent proxying?  How do I get this to work?  (FWIW: development host is a generic x86_64 ubuntu 14.04 LTS box.)  Thanks!</p>