title: Using select for packet sockets
body: <p>Is it possible to use select for packet sockets? I mean whether its necessary for the socket to be connection-based in order to use select function on it properly?
  I'm seeing that the behavior of a socket which I got it by the following socket function call:</p>
  <pre><code>int socket_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  </code></pre>
  <p>is not as I expect. For example, I see that a ping packet which is 60 bytes long when received and read into a 20 bytes length buffer, it waits about a second between each recv function call. I used recvfrom and it didn't help. For this, I ask whether it's correct to use select for a packet socket?</p>
  <h2>Update</h2>
  <p>I'm going to include the code to discuss about it:</p>
  <pre><code>int MakeBridge(const char *if1, const char *if2)
  {
      int sock[2];
      sock[0] = OpenSocket(if1);
      sock[1] = OpenSocket(if2);
      int activity;
      char buf[20];
      const int numSocks = 2;
      int nfds = sock[0];
      for (int i = 1; i &lt; numSocks; i++)
          if (sock[i] &gt; nfds)
              nfds = sock[i];
      nfds++;
      while (true)
      {
          FD_ZERO(&amp;readfds);
          for (int i = 0; i &lt; numSocks; i++)
              FD_SET(sock[i], &amp;readfds);
          activity = select(nfds, &amp;readfds, NULL, NULL, NULL);
          if (activity == -1)  // sockets closed
              break;
          for (int i = 0; i &lt; numSocks; i++)
              if (FD_ISSET(_sock[i], &amp;readfds))
              {
                  int len;
                  CHECK(ioctl(_sock[i], FIONREAD, &amp;len) != -1, &quot;%s&quot;, strerror(errno));
                  printf(&quot;socket %d is set\n&quot;, i);
                  printf(&quot;total bytes available to read: %d\n&quot;, len);
                  CHECK(len &gt; 0, &quot;&quot;);
                  do
                  {
                      int n = min(len, sizeof(buf));
                      int nbr = recvfrom(_sock[i], buf, n, 0, NULL, NULL);
                      printf(&quot;n %d nbr %d\n&quot;, n, nbr);
                      CHECK(n == nbr, &quot;&quot;);
                      len -= n;
                  } while (len);
              }
      }
      return 0;
  }
  </code></pre>
  <h2>Update 2</h2>
  <p>Not going to segment messages and using large enough buffer makes the code as follows:</p>
  <pre><code>// This is a program which is going to make the bridge between two interfaces. brctl is going to be replaced by this program.
  
  #define Uses_CHECK
  #define Uses_close
  #define Uses_errno
  #define Uses_ETH_P_ALL
  #define Uses_FD_SET
  #define Uses_htons
  #define Uses_ifreq
  #define Uses_ioctl
  #define Uses_printf
  #define Uses_signal
  #define Uses_sockaddr_ll
  #define Uses_socket
  #define Uses_strerror
  #include &lt;general.dep&gt;
  
  int _sock[2];
  
  int _CtrlCHandler()
  {
      printf(&quot; terminating...\n&quot;);
      CHECK(close(_sock[0]) != -1, &quot;&quot;);
      CHECK(close(_sock[1]) != -1, &quot;&quot;);
      printf(&quot;all sockets closed successfully.\n&quot;);
  }
  
  void CtrlCHandler(int dummy)
  {
      _CtrlCHandler();
  }
  
  int OpenSocket(const char *ifname)
  {
      // getting socket
      int socket_fd = socket(PF_PACKET, SOCK_RAW/*|SOCK_NONBLOCK*/, htons(ETH_P_ALL));
      CHECK(socket_fd != -1, &quot;%s&quot;, strerror(errno));
  
      // init interface options struct with the interface name
      struct ifreq if_options;
      memset(&amp;if_options, 0, sizeof(struct ifreq));
      strncpy(if_options.ifr_name, ifname, sizeof(if_options.ifr_name) - 1);
      if_options.ifr_name[sizeof(if_options.ifr_name) - 1] = 0;
  
      // enable promiscuous mode
      CHECK(ioctl(socket_fd, SIOCGIFFLAGS, &amp;if_options) != -1, &quot;%s&quot;, strerror(errno));
      if_options.ifr_flags |= IFF_PROMISC;
      CHECK(ioctl(socket_fd, SIOCSIFFLAGS, &amp;if_options) != -1, &quot;%s&quot;, strerror(errno));
  
      // get interface index
      CHECK(ioctl(socket_fd, SIOCGIFINDEX, &amp;if_options) != -1, &quot;%s&quot;, strerror(errno));
  
      // bind socket to the interface
      struct sockaddr_ll my_addr;
      memset(&amp;my_addr, 0, sizeof(my_addr));
      my_addr.sll_family = AF_PACKET;
      my_addr.sll_ifindex = if_options.ifr_ifindex;
      CHECK(bind(socket_fd, (struct sockaddr *)&amp;my_addr, sizeof(my_addr)) != -1, &quot;%s&quot;, strerror(errno));
  
      // socket is ready
      return socket_fd;
  }
  
  int MakeBridge(const char *if1, const char *if2)
  {
      _sock[0] = OpenSocket(if1);
      CHECK_NO_MSG(_sock[0]);
      _sock[1] = OpenSocket(if2);
      CHECK_NO_MSG(_sock[1]);
      printf(&quot;sockets %d and %d opened successfully\n&quot;, _sock[0], _sock[1]);
  
      fd_set readfds, orig;
      int activity;
      char buf[1&lt;&lt;16];
      signal(SIGINT, CtrlCHandler);
      int packetNumber = 0;
      const int numSocks = _countof(_sock);
      int nfds = _sock[0];
      for (int i = 1; i &lt; numSocks; i++)
          if (_sock[i] &gt; nfds)
              nfds = _sock[i];
      nfds++;
      FD_ZERO(&amp;orig);
      for (int i = 0; i &lt; numSocks; i++)
          FD_SET(_sock[i], &amp;orig);
      while (true)
      {
          readfds = orig;
          activity = select(nfds, &amp;readfds, NULL, NULL, NULL);
          if (activity == -1)  // sockets closed
              break;
          CHECK(activity &gt; 0, &quot;&quot;);
          for (int i = 0; i &lt; numSocks; i++)
              if (FD_ISSET(_sock[i], &amp;readfds))
              {
                  int len = recvfrom(_sock[i], buf, sizeof(buf), MSG_TRUNC, NULL, NULL);
                  CHECK(len &gt; 0, &quot;&quot;);
                  CHECK(len &lt;= sizeof(buf), &quot;small size buffer&quot;);
                  printf(&quot;%10d %d %d\n&quot;, ++packetNumber, i, len);
                  CHECK(sendto(_sock[!i], buf, len, 0, NULL, 0) == len, &quot;&quot;);
              }
      }
  
      return 0;
  }
  
  int Usage(int argc, const char *argv[])
  {
      printf(&quot;Usage: %s &lt;if1&gt; &lt;if2&gt;\n&quot;, argv[0]);
      printf(&quot;Bridges two interfaces with the names specified.\n&quot;);
      return 0;
  }
  
  int main(int argc, const char *argv[])
  {
      if (argc != 3)
          return Usage(argc, argv);
      CHECK_NO_MSG(MakeBridge(argv[1], argv[2]));
      return 0;
  }
  </code></pre>