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);