37 #include <sys/types.h> 
   40 #include <sys/ioctl.h> 
   42 #include <sys/socket.h> 
   44 #include <netinet/in.h> 
   45 #include <netinet/in_systm.h> 
   46 #include <netinet/ip.h> 
   49 #include <arpa/inet.h> 
   66 #define SOL_TCP IPPROTO_TCP 
   70 #define SOL_IP IPPROTO_IP 
   81         unsigned optlen = 
sizeof w;
 
   84                 DEBUG_MSG(LOG_NOTICE, 
"getting %sBUF from fd %d ",
 
   85                           (direction == SO_SNDBUF ? 
"SND" : 
"RCV"), fd);
 
   87                 DEBUG_MSG(LOG_NOTICE, 
"setting %sBUF on fd %d to %d",
 
   88                           (direction == SO_SNDBUF ? 
"SND" : 
"RCV"), fd, window);
 
   90         rc = getsockopt(fd, SOL_SOCKET, direction, (
char *)&w, &optlen);
 
   98                 rc = setsockopt(fd, SOL_SOCKET, direction,
 
   99                                 (
char *)&
try, optlen);
 
  102         } 
while (
try > w && rc == -1);
 
  104         rc = getsockopt(fd, SOL_SOCKET, direction, (
char *)&w, &optlen);
 
  108                 DEBUG_MSG(LOG_NOTICE, 
"set %sBUF on fd %d to %d (instead of %d)",
 
  109                                 (direction == SO_SNDBUF ? 
"SND" : 
"RCV"),
 
  122                 DEBUG_MSG(LOG_NOTICE, 
"getting window size of fd %d", fd);
 
  124                 DEBUG_MSG(LOG_NOTICE, 
"setting window size of fd %d to %d", fd,
 
  129         return send < receive? send: receive;
 
  134         int optname = IP_TOS;
 
  135         int optlevel = IPPROTO_IP;
 
  137         DEBUG_MSG(LOG_NOTICE, 
"setting DSCP of fd %d to %0x", fd, dscp);
 
  146         return setsockopt(fd, optlevel, optname, &dscp, 
sizeof(dscp));
 
  155         char rspace[3 + 4 * 
NROUTES + 1];
 
  157         DEBUG_MSG(LOG_NOTICE, 
"enabling route_record for fd %d ", fd);
 
  159         if (!(rc = setsockopt(fd, IPPROTO_IP, IP_RECVOPTS, &opt_on, 
sizeof(opt_on))))
 
  162         bzero(rspace, 
sizeof(rspace));
 
  163         rspace[0] = IPOPT_NOP;
 
  164         rspace[1+IPOPT_OPTVAL] = IPOPT_RR;
 
  165         rspace[1+IPOPT_OLEN] = 
sizeof(rspace)-1;
 
  166         rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF;
 
  167         if (!(rc = setsockopt(fd, IPPROTO_IP, IP_OPTIONS, rspace, 
sizeof(rspace))))
 
  169         return setsockopt(fd, 
SOL_TCP, IP_TTL, &nroutes, 
sizeof(nroutes));
 
  176         DEBUG_MSG(LOG_NOTICE, 
"setting fd %d non-blocking", fd);
 
  179         if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
 
  181         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 
  188         DEBUG_MSG(LOG_NOTICE, 
"setting TCP_NODELAY on fd %d", fd);
 
  190         return setsockopt(fd, 
SOL_TCP, TCP_NODELAY, &opt_on, 
sizeof(opt_on));
 
  202         socklen_t mtu_len = 
sizeof(mtu);
 
  204         if (getsockopt(fd, SOL_IP, 
IP_MTU, &mtu, &mtu_len) < 0)
 
  217         struct sockaddr_storage sa;
 
  218         socklen_t sl = 
sizeof(sa);
 
  220         struct ifreq ifreqs[20];
 
  222         struct ifconf ifconf;
 
  223         int nifaces, i, mtu = 0;
 
  225         memset(&ifconf,0,
sizeof(ifconf));
 
  226         ifconf.ifc_buf = (
char*)(ifreqs);
 
  227         ifconf.ifc_len = 
sizeof(ifreqs);
 
  229         if (getsockname(fd, (
struct sockaddr *)&sa, &sl) < 0)
 
  232         if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0)
 
  235         nifaces =  ifconf.ifc_len/
sizeof(
struct ifreq);
 
  237         for(i = 0; i < nifaces; i++)
 
  239                 if (
sockaddr_compare((
struct sockaddr *)&ifreqs[i].ifr_addr, (
struct sockaddr *)&sa))
 
  243         if (ioctl(fd, SIOCGIFMTU, &ifreqs[i]) < 0)
 
  246         DEBUG_MSG(LOG_NOTICE, 
"interface %s (%s) has mtu %d", ifreqs[i].ifr_name,
 
  247                   fg_nameinfo((
struct sockaddr *)&ifreqs[i].ifr_addr,
 
  248                   sizeof(
struct sockaddr)), ifreqs[i].ifr_mtu);
 
  250         mtu = ifreqs[i].ifr_mtu;
 
  260         DEBUG_MSG(LOG_NOTICE, 
"setting TCP_KEEPALIVE(%d) on fd %d", how, fd);
 
  262         return setsockopt(fd, 
SOL_TCP, SO_KEEPALIVE, &how, 
sizeof(how));
 
  267 #ifdef HAVE_SO_TCP_CONGESTION 
  268         DEBUG_MSG(LOG_NOTICE, 
"setting cc_alg=\"%s\" for fd %d", cc_alg, fd);
 
  269         return setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, cc_alg, strlen(cc_alg));
 
  273         DEBUG_MSG(LOG_ERR, 
"cannot set cc_alg, no  TCP_CONGESTION sockopt");
 
  283         DEBUG_MSG(LOG_WARNING, 
"setting TCP_ELCN on fd %d", fd);
 
  294         DEBUG_MSG(LOG_WARNING, 
"setting TCP_LCD on fd %d", fd);
 
  302 #ifdef HAVE_SO_IP_MTU_DISCOVER 
  303         const int dummy = IP_PMTUDISC_DO;
 
  305         DEBUG_MSG(LOG_WARNING, 
"setting IP_MTU_DISCOVERY on fd %d", fd);
 
  306         return setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &dummy, 
sizeof(dummy)) ;
 
  310         DEBUG_MSG(LOG_ERR, 
"cannot set IP_MTU_DISCOVERY for OS other than " 
  319 #ifdef HAVE_SO_TCP_CORK 
  322         DEBUG_MSG(LOG_WARNING, 
"setting TCP_CORK on fd %d", fd);
 
  323         return setsockopt(fd, 
SOL_TCP, TCP_CORK, &opt, 
sizeof(opt));
 
  326         DEBUG_MSG(LOG_ERR, 
"cannot set TCP_CORK for OS other than Linux");
 
  333 #ifdef HAVE_SO_TCP_CORK 
  336         DEBUG_MSG(LOG_WARNING, 
"clearing TCP_CORK on fd %d", fd);
 
  337         if (setsockopt(fd, 
SOL_TCP, TCP_CORK, &opt, 
sizeof(opt)) == -1)
 
  342         DEBUG_MSG(LOG_ERR, 
"cannot toggle TCP_CORK for OS other than Linux");
 
  354         DEBUG_MSG(LOG_WARNING, 
"setting TCP_MTCP on fd %d", fd);
 
  362         DEBUG_MSG(LOG_WARNING, 
"setting TCP_NODELAY on fd %d", fd);
 
  363         return setsockopt(fd, 
SOL_TCP, TCP_NODELAY, &opt, 
sizeof(opt));
 
  370         DEBUG_MSG(LOG_WARNING, 
"setting TCP_DEBUG on fd %d", fd);
 
  371         return setsockopt(fd, SOL_SOCKET, SO_DEBUG, &opt, 
sizeof(opt));
 
  374 const char *
fg_nameinfo(
const struct sockaddr *sa, socklen_t salen)
 
  376         static char host[NI_MAXHOST];
 
  378         if (getnameinfo(sa, salen, host, 
sizeof(host),
 
  379                                 NULL, 0, NI_NUMERICHOST) != 0) {
 
  384                 inet_ntop(sa->sa_family, sa, host, 
sizeof(host));
 
  394         if (a->sa_family != b->sa_family)
 
  397         if (a->sa_family == AF_INET6) {
 
  398                 const struct sockaddr_in6 *a6 = (
const struct sockaddr_in6 *)a;
 
  399                 const struct sockaddr_in6 *b6 = (
const struct sockaddr_in6 *)b;
 
  402                 if (a6->sin6_scope_id && b6->sin6_scope_id &&
 
  403                                 a6->sin6_scope_id != b6->sin6_scope_id)
 
  406                 if ((memcmp(&(a6->sin6_addr), &in6addr_any,
 
  407                                                 sizeof(
struct in6_addr)) != 0) &&
 
  408                                 (memcmp(&(b6->sin6_addr), &in6addr_any,
 
  409                                         sizeof(
struct in6_addr)) != 0) &&
 
  410                                 (memcmp(&(a6->sin6_addr), &(b6->sin6_addr),
 
  411                                         sizeof(
struct in6_addr)) != 0))
 
  416                 return (a6->sin6_port == 0) || (b6->sin6_port == 0) ||
 
  417                                 (a6->sin6_port == b6->sin6_port);
 
  420         if (a->sa_family == AF_INET) {
 
  421                 const struct sockaddr_in *a_in = (
const struct sockaddr_in *)a;
 
  422                 const struct sockaddr_in *b_in = (
const struct sockaddr_in *)b;
 
  426                 if ((a_in->sin_addr.s_addr != INADDR_ANY) &&
 
  427                                 (b_in->sin_addr.s_addr != INADDR_ANY) &&
 
  428                                 (a_in->sin_addr.s_addr != b_in->sin_addr.s_addr))
 
  433                 return (a_in->sin_port == 0) || (b_in->sin_port == 0) ||
 
  434                                 (a_in->sin_port == b_in->sin_port);
 
  443         struct sockaddr_storage addr;
 
  444         socklen_t addrlen = 
sizeof(addr);
 
  445         static char service[NI_MAXSERV];
 
  447         if (getsockname(fd, (
struct sockaddr*)&addr, &addrlen) != 0)
 
  450         if (getnameinfo((
struct sockaddr*)&addr, addrlen, NULL, 0,
 
  451                                 service, 
sizeof(service), NI_NUMERICSERV) != 0)
 
  454         return atoi(service);