Diff for /embedaddon/iperf/src/net.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2016/10/18 13:28:18 version 1.1.1.2, 2021/03/17 00:36:46
Line 1 Line 1
 /*  /*
 * iperf, Copyright (c) 2014, 2015, The Regents of the University of * iperf, Copyright (c) 2014-2019, The Regents of the University of
  * California, through Lawrence Berkeley National Laboratory (subject   * California, through Lawrence Berkeley National Laboratory (subject
  * to receipt of any required approvals from the U.S. Dept. of   * to receipt of any required approvals from the U.S. Dept. of
  * Energy).  All rights reserved.   * Energy).  All rights reserved.
Line 29 Line 29
 #include <stdio.h>  #include <stdio.h>
 #include <unistd.h>  #include <unistd.h>
 #include <errno.h>  #include <errno.h>
   #include <arpa/inet.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/errno.h>  
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/tcp.h>  #include <netinet/tcp.h>
 #include <assert.h>  #include <assert.h>
 #include <netdb.h>  #include <netdb.h>
 #include <string.h>  #include <string.h>
#include <sys/fcntl.h>#include <fcntl.h>
 #include <limits.h>
   
 #ifdef HAVE_SENDFILE  #ifdef HAVE_SENDFILE
 #ifdef linux  #ifdef linux
Line 56 Line 57
 #endif  #endif
 #endif /* HAVE_SENDFILE */  #endif /* HAVE_SENDFILE */
   
   #ifdef HAVE_POLL_H
   #include <poll.h>
   #endif /* HAVE_POLL_H */
   
 #include "iperf_util.h"  #include "iperf_util.h"
 #include "net.h"  #include "net.h"
 #include "timer.h"  #include "timer.h"
   
   /*
    * Declaration of gerror in iperf_error.c.  Most other files in iperf3 can get this
    * by including "iperf.h", but net.c lives "below" this layer.  Clearly the
    * presence of this declaration is a sign we need to revisit this layering.
    */
   extern int gerror;
   
   /*
    * timeout_connect adapted from netcat, via OpenBSD and FreeBSD
    * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
    */
   int
   timeout_connect(int s, const struct sockaddr *name, socklen_t namelen,
       int timeout)
   {
           struct pollfd pfd;
           socklen_t optlen;
           int flags, optval;
           int ret;
   
           flags = 0;
           if (timeout != -1) {
                   flags = fcntl(s, F_GETFL, 0);
                   if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
                           return -1;
           }
   
           if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
                   pfd.fd = s;
                   pfd.events = POLLOUT;
                   if ((ret = poll(&pfd, 1, timeout)) == 1) {
                           optlen = sizeof(optval);
                           if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
                               &optval, &optlen)) == 0) {
                                   errno = optval;
                                   ret = optval == 0 ? 0 : -1;
                           }
                   } else if (ret == 0) {
                           errno = ETIMEDOUT;
                           ret = -1;
                   } else
                           ret = -1;
           }
   
           if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
                   ret = -1;
   
           return (ret);
   }
   
 /* netdial and netannouce code comes from libtask: http://swtch.com/libtask/  /* netdial and netannouce code comes from libtask: http://swtch.com/libtask/
  * Copyright: http://swtch.com/libtask/COPYRIGHT   * Copyright: http://swtch.com/libtask/COPYRIGHT
 */  */
   
 /* make connection to server */  /* make connection to server */
 int  int
netdial(int domain, int proto, char *local, int local_port, char *server, int port)netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout)
 {  {
     struct addrinfo hints, *local_res, *server_res;      struct addrinfo hints, *local_res, *server_res;
    int s;    int s, saved_errno;
   
     if (local) {      if (local) {
         memset(&hints, 0, sizeof(hints));          memset(&hints, 0, sizeof(hints));
         hints.ai_family = domain;          hints.ai_family = domain;
         hints.ai_socktype = proto;          hints.ai_socktype = proto;
        if (getaddrinfo(local, NULL, &hints, &local_res) != 0)        if ((gerror = getaddrinfo(local, NULL, &hints, &local_res)) != 0)
             return -1;              return -1;
     }      }
   
     memset(&hints, 0, sizeof(hints));      memset(&hints, 0, sizeof(hints));
     hints.ai_family = domain;      hints.ai_family = domain;
     hints.ai_socktype = proto;      hints.ai_socktype = proto;
    if (getaddrinfo(server, NULL, &hints, &server_res) != 0)    if ((gerror = getaddrinfo(server, NULL, &hints, &server_res)) != 0)
         return -1;          return -1;
   
     s = socket(server_res->ai_family, proto, 0);      s = socket(server_res->ai_family, proto, 0);
Line 93  netdial(int domain, int proto, char *local, int local_ Line 148  netdial(int domain, int proto, char *local, int local_
         return -1;          return -1;
     }      }
   
       /* Bind the local address if given a name (with or without --cport) */
     if (local) {      if (local) {
         if (local_port) {          if (local_port) {
             struct sockaddr_in *lcladdr;              struct sockaddr_in *lcladdr;
             lcladdr = (struct sockaddr_in *)local_res->ai_addr;              lcladdr = (struct sockaddr_in *)local_res->ai_addr;
             lcladdr->sin_port = htons(local_port);              lcladdr->sin_port = htons(local_port);
             local_res->ai_addr = (struct sockaddr *)lcladdr;  
         }          }
   
         if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {          if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
               saved_errno = errno;
             close(s);              close(s);
             freeaddrinfo(local_res);              freeaddrinfo(local_res);
             freeaddrinfo(server_res);              freeaddrinfo(server_res);
               errno = saved_errno;
             return -1;              return -1;
         }          }
         freeaddrinfo(local_res);          freeaddrinfo(local_res);
     }      }
       /* No local name, but --cport given */
       else if (local_port) {
           size_t addrlen;
           struct sockaddr_storage lcl;
   
           /* IPv4 */
           if (server_res->ai_family == AF_INET) {
               struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
               lcladdr->sin_family = AF_INET;
               lcladdr->sin_port = htons(local_port);
               lcladdr->sin_addr.s_addr = INADDR_ANY;
               addrlen = sizeof(struct sockaddr_in);
           }
           /* IPv6 */
           else if (server_res->ai_family == AF_INET6) {
               struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
               lcladdr->sin6_family = AF_INET6;
               lcladdr->sin6_port = htons(local_port);
               lcladdr->sin6_addr = in6addr_any;
               addrlen = sizeof(struct sockaddr_in6);
           }
           /* Unknown protocol */
           else {
               errno = EAFNOSUPPORT;
               return -1;
           }
   
           if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
               saved_errno = errno;
               close(s);
               freeaddrinfo(server_res);
               errno = saved_errno;
               return -1;
           }
       }
   
     ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port);      ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port);
    if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {    if (timeout_connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen, timeout) < 0 && errno != EINPROGRESS) {
         saved_errno = errno;
         close(s);          close(s);
         freeaddrinfo(server_res);          freeaddrinfo(server_res);
           errno = saved_errno;
         return -1;          return -1;
     }      }
   
Line 124  netdial(int domain, int proto, char *local, int local_ Line 218  netdial(int domain, int proto, char *local, int local_
 /***************************************************************/  /***************************************************************/
   
 int  int
netannounce(int domain, int proto, char *local, int port)netannounce(int domain, int proto, const char *local, int port)
 {  {
     struct addrinfo hints, *res;      struct addrinfo hints, *res;
     char portstr[6];      char portstr[6];
    int s, opt;    int s, opt, saved_errno;
   
     snprintf(portstr, 6, "%d", port);      snprintf(portstr, 6, "%d", port);
     memset(&hints, 0, sizeof(hints));      memset(&hints, 0, sizeof(hints));
Line 152  netannounce(int domain, int proto, char *local, int po Line 246  netannounce(int domain, int proto, char *local, int po
     }      }
     hints.ai_socktype = proto;      hints.ai_socktype = proto;
     hints.ai_flags = AI_PASSIVE;      hints.ai_flags = AI_PASSIVE;
    if (getaddrinfo(local, portstr, &hints, &res) != 0)    if ((gerror = getaddrinfo(local, portstr, &hints, &res)) != 0)
         return -1;           return -1; 
   
     s = socket(res->ai_family, proto, 0);      s = socket(res->ai_family, proto, 0);
Line 164  netannounce(int domain, int proto, char *local, int po Line 258  netannounce(int domain, int proto, char *local, int po
     opt = 1;      opt = 1;
     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 
                    (char *) &opt, sizeof(opt)) < 0) {                     (char *) &opt, sizeof(opt)) < 0) {
           saved_errno = errno;
         close(s);          close(s);
         freeaddrinfo(res);          freeaddrinfo(res);
           errno = saved_errno;
         return -1;          return -1;
     }      }
     /*      /*
Line 184  netannounce(int domain, int proto, char *local, int po Line 280  netannounce(int domain, int proto, char *local, int po
             opt = 1;              opt = 1;
         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,           if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
                        (char *) &opt, sizeof(opt)) < 0) {                         (char *) &opt, sizeof(opt)) < 0) {
               saved_errno = errno;
             close(s);              close(s);
             freeaddrinfo(res);              freeaddrinfo(res);
               errno = saved_errno;
             return -1;              return -1;
         }          }
     }      }
 #endif /* IPV6_V6ONLY */  #endif /* IPV6_V6ONLY */
   
     if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {      if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
           saved_errno = errno;
         close(s);          close(s);
         freeaddrinfo(res);          freeaddrinfo(res);
           errno = saved_errno;
         return -1;          return -1;
     }      }
   
     freeaddrinfo(res);      freeaddrinfo(res);
           
     if (proto == SOCK_STREAM) {      if (proto == SOCK_STREAM) {
        if (listen(s, 5) < 0) {        if (listen(s, INT_MAX) < 0) {
             saved_errno = errno;
             close(s);              close(s);
               errno = saved_errno;
             return -1;              return -1;
         }          }
     }      }
Line 351  Nsendfile(int fromfd, int tofd, const char *buf, size_ Line 453  Nsendfile(int fromfd, int tofd, const char *buf, size_
 }  }
   
 /*************************************************************************/  /*************************************************************************/
   
 /**  
  * getsock_tcp_mss - Returns the MSS size for TCP  
  *  
  */  
   
 int  
 getsock_tcp_mss(int inSock)  
 {  
     int             mss = 0;  
   
     int             rc;  
     socklen_t       len;  
   
     assert(inSock >= 0); /* print error and exit if this is not true */  
   
     /* query for mss */  
     len = sizeof(mss);  
     rc = getsockopt(inSock, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, &len);  
     if (rc == -1) {  
         perror("getsockopt TCP_MAXSEG");  
         return -1;  
     }  
   
     return mss;  
 }  
   
   
   
 /*************************************************************/  
   
 /* sets TCP_NODELAY and TCP_MAXSEG if requested */  
 // XXX: This function is not being used.  
   
 int  
 set_tcp_options(int sock, int no_delay, int mss)  
 {  
     socklen_t len;  
     int rc;  
     int new_mss;  
   
     if (no_delay == 1) {  
         len = sizeof(no_delay);  
         rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&no_delay, len);  
         if (rc == -1) {  
             perror("setsockopt TCP_NODELAY");  
             return -1;  
         }  
     }  
 #ifdef TCP_MAXSEG  
     if (mss > 0) {  
         len = sizeof(new_mss);  
         assert(sock != -1);  
   
         /* set */  
         new_mss = mss;  
         len = sizeof(new_mss);  
         rc = setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, (char *)&new_mss, len);  
         if (rc == -1) {  
             perror("setsockopt TCP_MAXSEG");  
             return -1;  
         }  
         /* verify results */  
         rc = getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, (char *)&new_mss, &len);  
         if (rc == -1) {  
             perror("getsockopt TCP_MAXSEG");  
             return -1;  
         }  
         if (new_mss != mss) {  
             perror("setsockopt value mismatch");  
             return -1;  
         }  
     }  
 #endif  
     return 0;  
 }  
   
 /****************************************************************************/  
   
 int  int
 setnonblocking(int fd, int nonblocking)  setnonblocking(int fd, int nonblocking)

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>