Flowgrind
Advanced TCP traffic generator
fg_socket.h File Reference

Routines used to manipulate socket parameters for Flowgrind. More...

#include "config.h"
#include <netinet/tcp.h>
#include <sys/socket.h>

Go to the source code of this file.

Functions

const char * fg_nameinfo (const struct sockaddr *sa, socklen_t salen)
 
int get_imtu (int fd)
 
int get_pmtu (int fd)
 
int get_port (int fd)
 
int set_congestion_control (int fd, const char *cc_alg)
 
int set_dscp (int fd, int dscp)
 
int set_ip_mtu_discover (int fd)
 
int set_keepalive (int fd, int how)
 
int set_nodelay (int fd)
 
int set_non_blocking (int fd)
 
int set_route_record (int fd)
 
int set_so_debug (int fd)
 
int set_so_dscp (int fd, uint8_t)
 
int set_so_elcn (int fd, int val)
 
int set_so_lcd (int fd)
 
int set_tcp_cork (int fd)
 
int set_tcp_mtcp (int fd)
 
int set_tcp_nodelay (int fd)
 
int set_window_size (int, int)
 
int set_window_size_directed (int, int, int)
 
char sockaddr_compare (const struct sockaddr *a, const struct sockaddr *b)
 
int toggle_tcp_cork (int fd)
 

Detailed Description

Routines used to manipulate socket parameters for Flowgrind.

Definition in file fg_socket.h.

Function Documentation

const char* fg_nameinfo ( const struct sockaddr *  sa,
socklen_t  salen 
)

Definition at line 374 of file fg_socket.c.

375 {
376  static char host[NI_MAXHOST];
377 
378  if (getnameinfo(sa, salen, host, sizeof(host),
379  NULL, 0, NI_NUMERICHOST) != 0) {
380  *host = '\0';
381  }
382 
383  if (*host == '\0')
384  inet_ntop(sa->sa_family, sa, host, sizeof(host));
385 
386  return host;
387 }
int get_imtu ( int  fd)

Definition at line 214 of file fg_socket.c.

216 {
217  struct sockaddr_storage sa;
218  socklen_t sl = sizeof(sa);
219 
220  struct ifreq ifreqs[20];
221 
222  struct ifconf ifconf;
223  int nifaces, i, mtu = 0;
224 
225  memset(&ifconf,0,sizeof(ifconf));
226  ifconf.ifc_buf = (char*)(ifreqs);
227  ifconf.ifc_len = sizeof(ifreqs);
228 
229  if (getsockname(fd, (struct sockaddr *)&sa, &sl) < 0)
230  return 0;
231 
232  if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0)
233  return 0;
234 
235  nifaces = ifconf.ifc_len/sizeof(struct ifreq);
236 
237  for(i = 0; i < nifaces; i++)
238  {
239  if (sockaddr_compare((struct sockaddr *)&ifreqs[i].ifr_addr, (struct sockaddr *)&sa))
240  break;
241  }
242 
243  if (ioctl(fd, SIOCGIFMTU, &ifreqs[i]) < 0)
244  return 0;
245 
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);
249 
250  mtu = ifreqs[i].ifr_mtu;
251 
252  if (mtu > 0)
253  return mtu;
254  else
255  return 0;
256 }
const char * fg_nameinfo(const struct sockaddr *sa, socklen_t salen)
Definition: fg_socket.c:374
char sockaddr_compare(const struct sockaddr *a, const struct sockaddr *b)
Definition: fg_socket.c:389
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int get_pmtu ( int  fd)

Definition at line 193 of file fg_socket.c.

195 {
196 #ifdef SOL_IP
197  int mtu = 0;
198 
199  if (fd < 0)
200  return 0;
201 
202  socklen_t mtu_len = sizeof(mtu);
203 
204  if (getsockopt(fd, SOL_IP, IP_MTU, &mtu, &mtu_len) < 0)
205  return 0;
206  else
207  return mtu;
208 #else /* SOL_IP */
209  UNUSED_ARGUMENT(fd);
210  return 0;
211 #endif /* SOL_IP */
212 }
#define IP_MTU
Definition: fg_socket.c:75
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.
int get_port ( int  fd)

Definition at line 441 of file fg_socket.c.

442 {
443  struct sockaddr_storage addr;
444  socklen_t addrlen = sizeof(addr);
445  static char service[NI_MAXSERV];
446 
447  if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) != 0)
448  return -1;
449 
450  if (getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
451  service, sizeof(service), NI_NUMERICSERV) != 0)
452  return -1;
453 
454  return atoi(service);
455 }
int set_congestion_control ( int  fd,
const char *  cc_alg 
)

Definition at line 265 of file fg_socket.c.

266 {
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));
270 #else /* HAVE_SO_TCP_CONGESTION */
271  UNUSED_ARGUMENT(fd);
272  UNUSED_ARGUMENT(cc_alg);
273  DEBUG_MSG(LOG_ERR, "cannot set cc_alg, no TCP_CONGESTION sockopt");
274  return -1;
275 #endif /* HAVE_SO_TCP_CONGESTION */
276 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.
int set_dscp ( int  fd,
int  dscp 
)

Definition at line 132 of file fg_socket.c.

133 {
134  int optname = IP_TOS;
135  int optlevel = IPPROTO_IP;
136 
137  DEBUG_MSG(LOG_NOTICE, "setting DSCP of fd %d to %0x", fd, dscp);
138 
139  if (dscp & ~0x3F) {
140  errno = EINVAL;
141  return -1;
142  }
143 
144  dscp <<= 2;
145 
146  return setsockopt(fd, optlevel, optname, &dscp, sizeof(dscp));
147 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_ip_mtu_discover ( int  fd)

Definition at line 300 of file fg_socket.c.

301 {
302 #ifdef HAVE_SO_IP_MTU_DISCOVER
303  const int dummy = IP_PMTUDISC_DO;
304 
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)) ;
307 
308 #else /* HAVE_SO_IP_MTU_DISCOVER */
309  UNUSED_ARGUMENT(fd);
310  DEBUG_MSG(LOG_ERR, "cannot set IP_MTU_DISCOVERY for OS other than "
311  "Linux");
312  return -1;
313 #endif /* HAVE_SO_IP_MTU_DISCOVER */
314 
315 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.
int set_keepalive ( int  fd,
int  how 
)

Definition at line 258 of file fg_socket.c.

259 {
260  DEBUG_MSG(LOG_NOTICE, "setting TCP_KEEPALIVE(%d) on fd %d", how, fd);
261 
262  return setsockopt(fd, SOL_TCP, SO_KEEPALIVE, &how, sizeof(how));
263 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_nodelay ( int  fd)

Definition at line 184 of file fg_socket.c.

185 {
186  int opt_on = 1;
187 
188  DEBUG_MSG(LOG_NOTICE, "setting TCP_NODELAY on fd %d", fd);
189 
190  return setsockopt(fd, SOL_TCP, TCP_NODELAY, &opt_on, sizeof(opt_on));
191 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_non_blocking ( int  fd)

Definition at line 172 of file fg_socket.c.

173 {
174  int flags;
175 
176  DEBUG_MSG(LOG_NOTICE, "setting fd %d non-blocking", fd);
177 
178 
179  if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
180  flags = 0;
181  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
182 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_route_record ( int  fd)

Definition at line 149 of file fg_socket.c.

150 {
151 #define NROUTES 9
152  int rc = 0;
153  int opt_on = 1;
154  int nroutes = NROUTES;
155  char rspace[3 + 4 * NROUTES + 1];
156 
157  DEBUG_MSG(LOG_NOTICE, "enabling route_record for fd %d ", fd);
158 
159  if (!(rc = setsockopt(fd, IPPROTO_IP, IP_RECVOPTS, &opt_on, sizeof(opt_on))))
160  return rc;
161 
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))))
168  return rc;
169  return setsockopt(fd, SOL_TCP, IP_TTL, &nroutes, sizeof(nroutes));
170 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define NROUTES
int set_so_debug ( int  fd)

Definition at line 366 of file fg_socket.c.

367 {
368  int opt = 1;
369 
370  DEBUG_MSG(LOG_WARNING, "setting TCP_DEBUG on fd %d", fd);
371  return setsockopt(fd, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt));
372 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_so_dscp ( int  fd,
uint8_t   
)
int set_so_elcn ( int  fd,
int  val 
)

Definition at line 278 of file fg_socket.c.

279 {
280 #ifndef TCP_ELCN
281 #define TCP_ELCN 20
282 #endif /* TCP_ELCN */
283  DEBUG_MSG(LOG_WARNING, "setting TCP_ELCN on fd %d", fd);
284 
285  return setsockopt(fd, SOL_TCP, TCP_ELCN, &val, sizeof(val));
286 }
#define SOL_TCP
Definition: fg_socket.c:66
#define TCP_ELCN
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_so_lcd ( int  fd)

Definition at line 288 of file fg_socket.c.

289 {
290 #ifndef TCP_LCD
291 #define TCP_LCD 21
292 #endif /* TCP_LCD */
293  int opt = 1;
294  DEBUG_MSG(LOG_WARNING, "setting TCP_LCD on fd %d", fd);
295 
296  return setsockopt(fd, SOL_TCP, TCP_LCD, &opt, sizeof(opt));
297 
298 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define TCP_LCD
int set_tcp_cork ( int  fd)

Definition at line 317 of file fg_socket.c.

318 {
319 #ifdef HAVE_SO_TCP_CORK
320  int opt = 1;
321 
322  DEBUG_MSG(LOG_WARNING, "setting TCP_CORK on fd %d", fd);
323  return setsockopt(fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
324 #else /* HAVE_SO_TCP_CORK */
325  UNUSED_ARGUMENT(fd);
326  DEBUG_MSG(LOG_ERR, "cannot set TCP_CORK for OS other than Linux");
327  return -1;
328 #endif /* HAVE_SO_TCP_CORK */
329 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.
int set_tcp_mtcp ( int  fd)

Definition at line 347 of file fg_socket.c.

348 {
349 #ifndef TCP_MTCP
350 #define TCP_MTCP 15
351 #endif /* TCP_MTCP */
352  int opt = 1;
353 
354  DEBUG_MSG(LOG_WARNING, "setting TCP_MTCP on fd %d", fd);
355  return setsockopt(fd, SOL_TCP, TCP_MTCP, &opt, sizeof(opt));
356 }
#define SOL_TCP
Definition: fg_socket.c:66
#define TCP_MTCP
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_tcp_nodelay ( int  fd)

Definition at line 358 of file fg_socket.c.

359 {
360  int opt = 1;
361 
362  DEBUG_MSG(LOG_WARNING, "setting TCP_NODELAY on fd %d", fd);
363  return setsockopt(fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
364 }
#define SOL_TCP
Definition: fg_socket.c:66
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_window_size ( int  ,
int   
)

Definition at line 117 of file fg_socket.c.

118 {
119  int send, receive;
120 
121  if (window <= 0)
122  DEBUG_MSG(LOG_NOTICE, "getting window size of fd %d", fd);
123  else
124  DEBUG_MSG(LOG_NOTICE, "setting window size of fd %d to %d", fd,
125  window);
126 
127  send = set_window_size_directed(fd, window, SO_SNDBUF);
128  receive = set_window_size_directed(fd, window, SO_RCVBUF);
129  return send < receive? send: receive;
130 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
int set_window_size_directed(int fd, int window, int direction)
Definition: fg_socket.c:78
int set_window_size_directed ( int  ,
int  ,
int   
)

Definition at line 78 of file fg_socket.c.

79 {
80  int rc, try, w;
81  unsigned optlen = sizeof w;
82 
83  if (window <= 0)
84  DEBUG_MSG(LOG_NOTICE, "getting %sBUF from fd %d ",
85  (direction == SO_SNDBUF ? "SND" : "RCV"), fd);
86  else
87  DEBUG_MSG(LOG_NOTICE, "setting %sBUF on fd %d to %d",
88  (direction == SO_SNDBUF ? "SND" : "RCV"), fd, window);
89 
90  rc = getsockopt(fd, SOL_SOCKET, direction, (char *)&w, &optlen);
91  if (rc == -1)
92  return -1;
93  if (window <= 0)
94  return w;
95 
96  try = window;
97  do {
98  rc = setsockopt(fd, SOL_SOCKET, direction,
99  (char *)&try, optlen);
100  try *= 7;
101  try /= 8;
102  } while (try > w && rc == -1);
103 
104  rc = getsockopt(fd, SOL_SOCKET, direction, (char *)&w, &optlen);
105  if (rc == -1)
106  return -1;
107  else {
108  DEBUG_MSG(LOG_NOTICE, "set %sBUF on fd %d to %d (instead of %d)",
109  (direction == SO_SNDBUF ? "SND" : "RCV"),
110  fd, w, window);
111 
112  return w;
113  }
114 }
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
char sockaddr_compare ( const struct sockaddr *  a,
const struct sockaddr *  b 
)

Definition at line 389 of file fg_socket.c.

390 {
391  assert(a != NULL);
392  assert(b != NULL);
393 
394  if (a->sa_family != b->sa_family)
395  return 0;
396 
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;
400 
401  /* compare scope */
402  if (a6->sin6_scope_id && b6->sin6_scope_id &&
403  a6->sin6_scope_id != b6->sin6_scope_id)
404  return 0;
405 
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))
412  return 0;
413 
414  /* compare port part
415  * either port may be 0(any), resulting in a good match */
416  return (a6->sin6_port == 0) || (b6->sin6_port == 0) ||
417  (a6->sin6_port == b6->sin6_port);
418  }
419 
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;
423 
424  /* compare address part
425  * either may be INADDR_ANY, resulting in a good match */
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))
429  return 0;
430 
431  /* compare port part */
432  /* either port may be 0(any), resulting in a good match */
433  return (a_in->sin_port == 0) || (b_in->sin_port == 0) ||
434  (a_in->sin_port == b_in->sin_port);
435  }
436 
437  /* For all other socket types, return false. Bummer */
438  return 0;
439 }
int toggle_tcp_cork ( int  fd)

Definition at line 331 of file fg_socket.c.

332 {
333 #ifdef HAVE_SO_TCP_CORK
334  int opt = 0;
335 
336  DEBUG_MSG(LOG_WARNING, "clearing TCP_CORK on fd %d", fd);
337  if (setsockopt(fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt)) == -1)
338  return -1;
339  return set_tcp_cork(fd);
340 #else /* HAVE_SO_TCP_CORK */
341  UNUSED_ARGUMENT(fd);
342  DEBUG_MSG(LOG_ERR, "cannot toggle TCP_CORK for OS other than Linux");
343  return -1;
344 #endif /* HAVE_SO_TCP_CORK */
345 }
#define SOL_TCP
Definition: fg_socket.c:66
int set_tcp_cork(int fd)
Definition: fg_socket.c:317
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.