title: Behavior of SO_REUSEADDR and SO_REUSEPORT changed?
body: <p>In older versions of Mac OS X, wildcard binding works like described here:</p>
  
  <p><a href="https://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t">Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?</a></p>
  
  <blockquote>
    <p>Multicast Addresses</p>
    
    <p>The meaning of SO_REUSEADDR changes for multicast addresses as it allows multiple sockets to be bound to exactly the same combination of source multicast address and port. In other words, for multicast addresses SO_REUSEADDR behaves exactly as SO_REUSEPORT for unicast addresses. Actually the code treats SO_REUSEADDR and SO_REUSEPORT identically for multicast addresses, that means you could say that SO_REUSEADDR implies SO_REUSEPORT for all multicast addresses and the other way round.</p>
  </blockquote>
  
  <p>and</p>
  
  <blockquote>
    <p>MacOS X</p>
    
    <p>At its very core, MacOS X is simply a BSD-style UNIX, based on a rather late fork of the BSD code, which was even synchronized with FreeBSD 5 for the Mac OS 10.3 release. That's why MacOS X offers the same options as BSD and they also behave the same way as in BSD.</p>
  </blockquote>
  
  <p>but in 10.10.5 I discovered a change when I was testing my networking library.</p>
  
  <p>Two unbound (wildcard) UDP sockets can not share the same port anymore (errno=EADDRINUSE), even when SO_REUSEADDR is set.
  SO_REUSEPORT has to be set on both two, which is a mystery to me.</p>
  
  <p>It is reproducible with this simple test code:</p>
  
  <pre><code>#include &lt;arpa/inet.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/ioctl.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;errno.h&gt;
  
  int main() {
      for(int p = 0; p &lt; 4; ++p) {
          printf("Flags set: ");
          if(p&amp;1) printf("SO_REUSEADDR ");
          if(p&amp;2) printf("SO_REUSEPORT");
          printf("\n");
  
          int handles[2];
          bool success = true;
          for(int i = 0; i &lt; sizeof(handles)/sizeof(int); ++i) {
              handles[i] = socket(AF_INET, SOCK_DGRAM, 0);
  
              int flag = 1;
              if((p&amp;1) &amp;&amp; setsockopt(handles[i], SOL_SOCKET, SO_REUSEADDR, &amp;flag, sizeof(flag)) == -1) {
                  printf("Setsockopt %d, SO_REUSEADDR failed with errno\n", i, errno);
                  success = false;
                  break;
              }
              if((p&amp;2) &amp;&amp; setsockopt(handles[i], SOL_SOCKET, SO_REUSEPORT, &amp;flag, sizeof(flag)) == -1) {
                  printf("Setsockopt %d, SO_REUSEPORT failed with errno\n", i, errno);
                  success = false;
                  break;
              }
  
              struct sockaddr_in addr;
              memset(&amp;addr, 0, sizeof(addr));
              addr.sin_family = AF_INET;
              addr.sin_port = 2000; // does not matter as long as it is currently free
              addr.sin_addr.s_addr = 0; // wildcard address
  
              if(bind(handles[i], (struct sockaddr*)&amp;addr, sizeof(addr)) == -1) {
                  printf("Bind %d failed with errno %d\n", i, errno);
                  success = false;
                  break;
              }
          }
          if(success)
              printf("Alright\n");
  
          for(int i = 0; i &lt; sizeof(handles)/sizeof(int); ++i)
              close(handles[i]);
          printf("\n");
      }
  
      return 0;
  }
  </code></pre>
  
  <p>Which outputs:</p>
  
  <pre><code>Flags set: 
  Bind 1 failed with errno 48
  
  Flags set: SO_REUSEADDR 
  Bind 1 failed with errno 48
  
  Flags set: SO_REUSEPORT
  Alright
  
  Flags set: SO_REUSEADDR SO_REUSEPORT
  Alright
  </code></pre>