-1

In this link, https://backreference.org/2010/03/26/tuntap-interface-tutorial/, there's a code sample that uses tun/tap interface to create a TCP tunnel as below.

  /* net_fd is the network file descriptor (to the peer), tap_fd is the
     descriptor connected to the tun/tap interface */

  /* use select() to handle two descriptors at once */
  maxfd = (tap_fd > net_fd)?tap_fd:net_fd;

  while(1) {
    int ret;
    fd_set rd_set;

    FD_ZERO(&rd_set);
    FD_SET(tap_fd, &rd_set); FD_SET(net_fd, &rd_set);

    ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);

    if (ret < 0 && errno == EINTR) {
      continue;
    }

    if (ret < 0) {
      perror("select()");
      exit(1);
    }

    if(FD_ISSET(tap_fd, &rd_set)) {
      /* data from tun/tap: just read it and write it to the network */

      nread = cread(tap_fd, buffer, BUFSIZE);

      /* write length + packet */
      plength = htons(nread);
      nwrite = cwrite(net_fd, (char *)&plength, sizeof(plength));
      nwrite = cwrite(net_fd, buffer, nread);
    }

    if(FD_ISSET(net_fd, &rd_set)) {
      /* data from the network: read it, and write it to the tun/tap interface.
       * We need to read the length first, and then the packet */

      /* Read length */
      nread = read_n(net_fd, (char *)&plength, sizeof(plength));

      /* read packet */
      nread = read_n(net_fd, buffer, ntohs(plength));

      /* now buffer[] contains a full packet or frame, write it into the tun/tap interface */
      nwrite = cwrite(tap_fd, buffer, nread);
    }
  }

What's the purpose of "maxfd" in that code excerpt? The exact lines are:

maxfd = (tap_fd > net_fd)?tap_fd:net_fd;

ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
itsmarziparzi
  • 699
  • 7
  • 21
  • 1
    If you did `printf("%ld\n",sizeof(fd_set));` you see the number of _bytes_ in one. Multiply by 8. You'll get something around 1,000 or so. `maxfd` tells `select` to only scan up to that [much] shorter limit. It's an efficiency thing. – Craig Estey Dec 02 '18 at 03:45
  • 3
    See the [documentation for select](http://man7.org/linux/man-pages/man2/select.2.html) and specifically the description of the `nfds` parameter. – Steffen Ullrich Dec 02 '18 at 04:06

1 Answers1

1

It's an artifact of the way the dangerous and obsolete select function works. It requires an argument that is a bound on the size (in bits) of the fd_set objects passed to it, and cannot work with fd numbers larger than an arbitrary limit imposed by FD_SETSIZE. If you fail to meet these requirements, Undefined Behavior results.

Wherever you see select, you should replace it by poll which does not suffer from these limitations, has an easier-to-use interface, and has more features.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711