List of commits:
Subject Hash Author Date (UTC)
Big fix for stuck programs. Stupid. f0ea19d9130bdc8851f08fb16a61a7be8da002cd Catalin(ux) M. BOIE 2011-08-24 20:19:56
More duilder updates 83d91834796de59a679545c25d62a423d6f04f0e Catalin(ux) M. BOIE 2011-08-24 20:17:33
More stuff added to TODO aaf5da40115dc3ee2562f42522468f5bd9362012 Catalin(ux) M. BOIE 2011-08-24 20:17:11
Corrected a merge problem. bb0ce0b8b1c869572d15babb81543154f0c5db39 Catalin(ux) M. BOIE 2011-08-24 03:41:36
Bump version to 0.9. 97343f56db715658dc0fbf6179db0d300c5d8545 Catalin(ux) M. BOIE 2011-08-24 03:37:36
Remove the need for SO_DOMAIN because we can get domain from accepting socket. a027bcfd13a15a98dd2a5db924af77199e156c7f Catalin(ux) M. BOIE 2011-08-10 20:19:38
SO_MARK may not be defined by glibc. 2204bbcf4b4480008cabc0e330f64460a8995255 Catalin(ux) M. BOIE 2011-08-10 20:08:43
Removed some debugging leftovers. 3b71558fc26d7958f83362926555c1f4100a57ab Catalin(ux) M. BOIE 2011-08-23 22:18:02
Spec files updates. 7a09b21c11b8d3c562544826c1fddb6009b16263 Catalin(ux) M. BOIE 2011-08-22 21:30:13
Duilder updates. f2b462384459025a3ffdcb8ebffcb070d8289ca7 Catalin(ux) M. BOIE 2011-08-22 21:29:51
Bump version to 0.8. e330ad91c75eeb6e627c6725b17fcc69d01eac50 Catalin(ux) M. BOIE 2011-08-22 15:17:00
Added a good example for tc prio classification. 32b9078e47fccc09527ca2c11904f82879934da3 Catalin(ux) M. BOIE 2011-08-22 15:16:21
Added support for multiple connections and chunk size for send_udp example. eff367aa527ed763fe525832891e0fc0df9badbb Catalin(ux) M. BOIE 2011-08-22 14:58:13
Do not count the time spent in sleep! e585e5e0b0b3ce0637674cf320a6f044afa42982 Catalin(ux) M. BOIE 2011-08-22 14:57:28
Give a real example for bandwidth enforcing. ca829bcb14183f7f5aa180bed4bf633199dc5839 Catalin(ux) M. BOIE 2011-08-22 14:57:01
Added possibility to force skb priority field (SO_PRIORITY). 9b4b2a6b03ff7573041a7ed96c86e7bcda86c580 Catalin(ux) M. BOIE 2011-08-06 21:55:43
Added support for FWMARK. 648b09b84fcd5bc17aaa7d6ba2bf2bfeeea583f7 Catalin(ux) M. BOIE 2011-08-06 21:35:23
Added support for IPv6 flowinfo (class + label). c23cc6042893fb98986b5aa38c146b7aec488079 Catalin(ux) M. BOIE 2011-08-06 21:11:46
Added support for connecting clients (socket -> connect or socket -> sendto). 8f94255890a99d4890206e53f031ffad79c55866 Catalin(ux) M. BOIE 2011-08-05 21:15:38
Bump version to 0.7. 1a51b690a50c482c9e727b3e8e129bbc2890f600 Catalin(ux) M. BOIE 2011-06-21 17:06:25
Commit f0ea19d9130bdc8851f08fb16a61a7be8da002cd - Big fix for stuck programs. Stupid.
Author: Catalin(ux) M. BOIE
Author date (UTC): 2011-08-24 20:19
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2011-08-24 20:19
Parent(s): 83d91834796de59a679545c25d62a423d6f04f0e
Signing key:
Tree: 245b0ab81002a6277bdafdaafaf7ded5d04cc5fc
File Lines added Lines deleted
force_bind.c 223 71
File force_bind.c changed (mode: 100644) (index 8b1645f..2402ec0)
... ... static unsigned int force_prio = 0, prio;
116 116 static struct private bw_global; static struct private bw_global;
117 117 static struct info fdinfo; static struct info fdinfo;
118 118 static unsigned int verbose = 0; static unsigned int verbose = 0;
119 static char *log_file = NULL;
120 static FILE *Log = NULL;
119 121
120 122 /* glibc may not be up-to-date at compile time */ /* glibc may not be up-to-date at compile time */
121 123 #ifndef SO_MARK #ifndef SO_MARK
122 124 #define SO_MARK 36 /* only on some architectures */ #define SO_MARK 36 /* only on some architectures */
123 125 #endif #endif
124 126
127
125 128 /* Helper functions */ /* Helper functions */
126 static int my_syslog(int priority, const char *format, ...)
129 static char *sdomain(const int domain)
130 {
131 static char tmp[16];
132
133 switch (domain) {
134 case AF_INET: return "IPv4";
135 case AF_INET6: return "IPv6";
136 default: snprintf(tmp, sizeof(tmp), "%d", domain); return tmp;
137 }
138 }
139
140 static char *stype(const int type)
141 {
142 static char tmp[16];
143
144 switch (type & 0xfff) {
145 case SOCK_STREAM: return "stream";
146 case SOCK_DGRAM: return "dgram";
147 case SOCK_RAW: return "raw";
148 case SOCK_SEQPACKET: return "seqpacket";
149 case SOCK_DCCP: return "dccp";
150 case SOCK_PACKET: return "packet";
151 default: snprintf(tmp, sizeof(tmp), "%d", type); return tmp;
152 }
153 }
154
155 static char *sprotocol(const int protocol)
156 {
157 static char tmp[16];
158
159 switch (protocol) {
160 case IPPROTO_TCP: return "tcp";
161 default: snprintf(tmp, sizeof(tmp), "%d", protocol); return tmp;
162 }
163 }
164
165 /*
166 * Set @out to a string with the address
167 */
168 static void saddr(char *out, const struct sockaddr_storage *ss)
169 {
170 struct sockaddr_in *s4;
171 struct sockaddr_in6 *s6;
172
173 switch (ss->ss_family) {
174 case AF_INET:
175 s4 = (struct sockaddr_in *) ss;
176 inet_ntop(AF_INET, (void *) &s4->sin_addr.s_addr, out, sizeof(struct sockaddr_in));
177 break;
178 case AF_INET6:
179 s6 = (struct sockaddr_in6 *) ss;
180 inet_ntop(AF_INET6, (void *) &s6->sin6_addr.s6_addr, out, sizeof(struct sockaddr_in6));
181 break;
182 default:
183 sprintf(out, "Unknown address type (%d)", ss->ss_family);
184 break;
185 }
186 }
187
188 static void xlog(const unsigned int level, const char *format, ...)
127 189 { {
128 190 va_list ap; va_list ap;
129 191
130 if (verbose == 0)
131 return 0;
192 if (Log == NULL)
193 return;
194
195 if (level > verbose)
196 return;
132 197
133 198 va_start(ap, format); va_start(ap, format);
134 vsyslog(priority, format, ap);
199 vfprintf(Log, format, ap);
135 200 va_end(ap); va_end(ap);
136
137 return 0;
138 201 } }
139 202
140 static void dump(const char *title, const void *buf, const unsigned int len)
203 static void dump(const int level, const char *title, const void *buf,
204 const unsigned int len)
141 205 { {
142 206 unsigned int i; unsigned int i;
143 207 unsigned char *buf2 = (unsigned char *) buf; unsigned char *buf2 = (unsigned char *) buf;
 
... ... static void dump(const char *title, const void *buf, const unsigned int len)
146 210 for (i = 0; i < len; i++) for (i = 0; i < len; i++)
147 211 snprintf(out + i * 3, 4, " %02x", buf2[i]); snprintf(out + i * 3, 4, " %02x", buf2[i]);
148 212
149 my_syslog(LOG_INFO, "force_bind: %s:%s\n", title, out);
213 xlog(level, "dump %s:%s\n", title, out);
150 214 } }
151 215
152 216 static struct node *get(const int fd) static struct node *get(const int fd)
 
... ... static struct node *get(const int fd)
164 228 return NULL; return NULL;
165 229 } }
166 230
231 /*
232 * List all sockets
233 */
234 static void list(const int level)
235 {
236 struct node *q;
237 struct private *p;
238 char dest[64];
239
240 xlog(level, "list...\n");
241
242 q = fdinfo.head;
243 while (q != NULL) {
244 if (q->fd == -1) {
245 q = q->next;
246 continue;
247 }
248
249 p = &q->priv;
250 saddr(dest, &p->dest);
251 xlog(level, "\tfd=%4d domain=%s type=%s"
252 " flags=%04x limit=%llu"
253 " rest=%llu last=%u.%06u dest=%s\n",
254 q->fd, sdomain(p->domain), stype(p->type),
255 p->flags, p->limit,
256 p->rest, p->last.tv_sec, p->last.tv_usec, dest);
257 q = q->next;
258 }
259 }
260
167 261 static void add(const int fd, const struct private *p) static void add(const int fd, const struct private *p)
168 262 { {
169 263 struct node *q; struct node *q;
170 264
265 xlog(2, "add(fd=%d, ...)\n", fd);
266
171 267 /* do we have a copy? */ /* do we have a copy? */
172 268 q = get(fd); q = get(fd);
173 269 if (q == NULL) { if (q == NULL) {
 
... ... static void add(const int fd, const struct private *p)
185 281 if (q == NULL) { if (q == NULL) {
186 282 q = (struct node *) malloc(sizeof(struct node)); q = (struct node *) malloc(sizeof(struct node));
187 283 if (q == NULL) { if (q == NULL) {
188 my_syslog(LOG_INFO, "force_bind: Cannot alloc memory; ignore fd!\n");
284 xlog(0, "Cannot alloc memory; ignore fd!\n");
189 285 return; return;
190 286 } }
191 287
192 288 q->next = NULL; q->next = NULL;
193 289 q->fd = fd; q->fd = fd;
290
291 if (fdinfo.tail == NULL) {
292 fdinfo.head = q;
293 } else {
294 fdinfo.tail->next = q;
295 }
296 fdinfo.tail = q;
194 297 } }
195 298 } }
196 299 memcpy(&q->priv, p, sizeof(struct private)); memcpy(&q->priv, p, sizeof(struct private));
 
... ... static void add(const int fd, const struct private *p)
202 305 gettimeofday(&q->priv.last, NULL); gettimeofday(&q->priv.last, NULL);
203 306 } }
204 307
205 if (fdinfo.tail == NULL) {
206 fdinfo.head = q;
207 } else {
208 fdinfo.tail->next = q;
209 }
210 fdinfo.tail = q;
308 list(2);
211 309 } }
212 310
213 311 static void del(const int fd) static void del(const int fd)
214 312 { {
215 313 struct node *p; struct node *p;
216 314
315 xlog(2, "del(fd=%d)\n", fd);
316
217 317 p = fdinfo.head; p = fdinfo.head;
218 318 while (p != NULL) { while (p != NULL) {
219 319 if (p->fd == fd) { if (p->fd == fd) {
220 320 p->fd = -1; p->fd = -1;
221 return;
321 break;
222 322 } }
223 323
224 324 p = p->next; p = p->next;
225 325 } }
326
327 list(2);
226 328 } }
227 329
228 330
 
... ... static void init(void)
241 343 fdinfo.head = NULL; fdinfo.head = NULL;
242 344 fdinfo.tail = NULL; fdinfo.tail = NULL;
243 345
346 log_file = getenv("FORCE_NET_LOG");
347 if (log_file != NULL)
348 Log = fopen(log_file, "w");
349
244 350 x = getenv("FORCE_NET_VERBOSE"); x = getenv("FORCE_NET_VERBOSE");
245 351 if (x != NULL) if (x != NULL)
246 352 verbose = strtol(x, NULL, 10); verbose = strtol(x, NULL, 10);
247 353
248 my_syslog(LOG_INFO, "force_bind: Init started...\n");
354 xlog(1, "Init started...\n");
249 355
250 356 x = getenv("FORCE_BIND_ADDRESS_V4"); x = getenv("FORCE_BIND_ADDRESS_V4");
251 357 if (x != NULL) { if (x != NULL) {
252 358 force_address_v4 = x; force_address_v4 = x;
253 my_syslog(LOG_INFO, "force_bind: Force bind to address %s.\n",
359 xlog(1, "Force bind to address %s.\n",
254 360 force_address_v4); force_address_v4);
255 361 } }
256 362
257 363 x = getenv("FORCE_BIND_ADDRESS_V6"); x = getenv("FORCE_BIND_ADDRESS_V6");
258 364 if (x != NULL) { if (x != NULL) {
259 365 force_address_v6 = x; force_address_v6 = x;
260 my_syslog(LOG_INFO, "force_bind: Force bind to address %s.\n",
366 xlog(1, "Force bind to address %s.\n",
261 367 force_address_v6); force_address_v6);
262 368 } }
263 369
 
... ... static void init(void)
266 372 if (x != NULL) { if (x != NULL) {
267 373 force_address_v4 = x; force_address_v4 = x;
268 374 force_address_v6 = x; force_address_v6 = x;
269 my_syslog(LOG_INFO, "force_bind: Force bind to address %s."
375 xlog(1, "Force bind to address %s."
270 376 " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n", " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n",
271 377 force_address_v4); force_address_v4);
272 378 } }
 
... ... static void init(void)
274 380 x = getenv("FORCE_BIND_PORT_V4"); x = getenv("FORCE_BIND_PORT_V4");
275 381 if (x != NULL) { if (x != NULL) {
276 382 force_port_v4 = strtol(x, NULL, 10); force_port_v4 = strtol(x, NULL, 10);
277 my_syslog(LOG_INFO, "force_bind: Force bind to port %d.\n",
383 xlog(1, "Force bind to port %d.\n",
278 384 force_port_v4); force_port_v4);
279 385 } }
280 386
281 387 x = getenv("FORCE_BIND_PORT_V6"); x = getenv("FORCE_BIND_PORT_V6");
282 388 if (x != NULL) { if (x != NULL) {
283 389 force_port_v6 = strtol(x, NULL, 10); force_port_v6 = strtol(x, NULL, 10);
284 my_syslog(LOG_INFO, "force_bind: Force bind to port %d.\n",
390 xlog(1, "Force bind to port %d.\n",
285 391 force_port_v6); force_port_v6);
286 392 } }
287 393
 
... ... static void init(void)
290 396 if (x != NULL) { if (x != NULL) {
291 397 force_port_v4 = strtol(x, NULL, 10); force_port_v4 = strtol(x, NULL, 10);
292 398 force_port_v6 = strtol(x, NULL, 10); force_port_v6 = strtol(x, NULL, 10);
293 my_syslog(LOG_INFO, "force_bind: Force bind to port %d."
399 xlog(1, "Force bind to port %d."
294 400 " Obsolete, use FORCE_BIND_PORT_V4/6.\n", " Obsolete, use FORCE_BIND_PORT_V4/6.\n",
295 401 force_port_v4); force_port_v4);
296 402 } }
 
... ... static void init(void)
300 406 if (x != NULL) { if (x != NULL) {
301 407 force_tos = 1; force_tos = 1;
302 408 tos = strtoul(x, NULL, 0); tos = strtoul(x, NULL, 0);
303 my_syslog(LOG_INFO, "force_bind: Force TOS to %hhu.\n",
409 xlog(1, "Force TOS to %hhu.\n",
304 410 tos); tos);
305 411 } }
306 412
 
... ... static void init(void)
309 415 if (x != NULL) { if (x != NULL) {
310 416 force_ttl = 1; force_ttl = 1;
311 417 ttl = strtoul(x, NULL, 0); ttl = strtoul(x, NULL, 0);
312 my_syslog(LOG_INFO, "force_bind: Force TTL to %hhu.\n",
418 xlog(1, "Force TTL to %hhu.\n",
313 419 ttl); ttl);
314 420 } }
315 421
 
... ... static void init(void)
318 424 if (x != NULL) { if (x != NULL) {
319 425 force_keepalive = 1; force_keepalive = 1;
320 426 keepalive = strtoul(x, NULL, 0); keepalive = strtoul(x, NULL, 0);
321 my_syslog(LOG_INFO, "force_bind: Force KA to %u.\n",
427 xlog(1, "Force KA to %u.\n",
322 428 keepalive); keepalive);
323 429 } }
324 430
 
... ... static void init(void)
327 433 if (x != NULL) { if (x != NULL) {
328 434 force_mss = 1; force_mss = 1;
329 435 mss = strtoul(x, NULL, 0); mss = strtoul(x, NULL, 0);
330 my_syslog(LOG_INFO, "force_bind: Force MSS to %u.\n",
436 xlog(1, "Force MSS to %u.\n",
331 437 mss); mss);
332 438 } }
333 439
 
... ... static void init(void)
336 442 if (x != NULL) { if (x != NULL) {
337 443 force_reuseaddr = 1; force_reuseaddr = 1;
338 444 reuseaddr = strtoul(x, NULL, 0); reuseaddr = strtoul(x, NULL, 0);
339 my_syslog(LOG_INFO, "force_bind: Force REUSEADDR to %u.\n",
445 xlog(1, "Force REUSEADDR to %u.\n",
340 446 reuseaddr); reuseaddr);
341 447 } }
342 448
 
... ... static void init(void)
345 451 if (x != NULL) { if (x != NULL) {
346 452 force_nodelay = 1; force_nodelay = 1;
347 453 nodelay = strtoul(x, NULL, 0); nodelay = strtoul(x, NULL, 0);
348 my_syslog(LOG_INFO, "force_bind: Force NODELAY to %u.\n",
454 xlog(1, "Force NODELAY to %u.\n",
349 455 nodelay); nodelay);
350 456 } }
351 457
 
... ... static void init(void)
355 461 bw_global.limit = strtoul(x, NULL, 0); bw_global.limit = strtoul(x, NULL, 0);
356 462 gettimeofday(&bw_global.last, NULL); gettimeofday(&bw_global.last, NULL);
357 463 bw_global.rest = 0; bw_global.rest = 0;
358 my_syslog(LOG_INFO, "force_bind: Force bandwidth to %llub/s.\n",
464 xlog(1, "Force bandwidth to %llub/s.\n",
359 465 bw_global.limit); bw_global.limit);
360 466 } else { } else {
361 467 bw_global.limit = 0; bw_global.limit = 0;
 
... ... static void init(void)
365 471 x = getenv("FORCE_NET_BW_PER_SOCKET"); x = getenv("FORCE_NET_BW_PER_SOCKET");
366 472 if (x != NULL) { if (x != NULL) {
367 473 if (bw_global.limit > 0) { if (bw_global.limit > 0) {
368 my_syslog(LOG_INFO, "force_bind: Cannot set limit per socket"
474 xlog(1, "Cannot set limit per socket"
369 475 " when global one is set.\n"); " when global one is set.\n");
370 476 } else { } else {
371 477 bw_limit_per_socket = strtoul(x, NULL, 0); bw_limit_per_socket = strtoul(x, NULL, 0);
372 my_syslog(LOG_INFO, "force_bind: Force bandwidth per socket to %llub/s.\n",
478 xlog(1, "Force bandwidth per socket to %llub/s.\n",
373 479 bw_limit_per_socket); bw_limit_per_socket);
374 480 } }
375 481 } }
 
... ... static void init(void)
379 485 if (x != NULL) { if (x != NULL) {
380 486 force_flowinfo = 1; force_flowinfo = 1;
381 487 flowinfo = strtoul(x, NULL, 0) & IPV6_FLOWINFO_MASK; flowinfo = strtoul(x, NULL, 0) & IPV6_FLOWINFO_MASK;
382 my_syslog(LOG_INFO, "force_bind: Force FLOWINFO to 0x%x.\n",
488 xlog(1, "Force FLOWINFO to 0x%x.\n",
383 489 flowinfo); flowinfo);
384 490 } }
385 491
 
... ... static void init(void)
388 494 if (x != NULL) { if (x != NULL) {
389 495 force_fwmark = 1; force_fwmark = 1;
390 496 fwmark = strtoul(x, NULL, 0); fwmark = strtoul(x, NULL, 0);
391 my_syslog(LOG_INFO, "force_bind: Force fwmark to 0x%x.\n",
497 xlog(1, "Force fwmark to 0x%x.\n",
392 498 fwmark); fwmark);
393 499 } }
394 500
 
... ... static void init(void)
397 503 if (x != NULL) { if (x != NULL) {
398 504 force_prio = 1; force_prio = 1;
399 505 prio = strtoul(x, NULL, 0); prio = strtoul(x, NULL, 0);
400 my_syslog(LOG_INFO, "force_bind: Force prio to %u.\n",
506 xlog(1, "Force prio to %u.\n",
401 507 prio); prio);
402 508 } }
403 509
404 510
405 511 old_bind = dlsym(RTLD_NEXT, "bind"); old_bind = dlsym(RTLD_NEXT, "bind");
406 512 if (old_bind == NULL) { if (old_bind == NULL) {
407 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'bind'!\n");
513 xlog(0, "Cannot resolve 'bind'!\n");
408 514 exit(1); exit(1);
409 515 } }
410 516
411 517 old_setsockopt = dlsym(RTLD_NEXT, "setsockopt"); old_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
412 518 if (old_setsockopt == NULL) { if (old_setsockopt == NULL) {
413 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'setsockopt'!\n");
519 xlog(0, "Cannot resolve 'setsockopt'!\n");
414 520 exit(1); exit(1);
415 521 } }
416 522
417 523 old_socket = dlsym(RTLD_NEXT, "socket"); old_socket = dlsym(RTLD_NEXT, "socket");
418 524 if (old_socket == NULL) { if (old_socket == NULL) {
419 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'socket'!\n");
525 xlog(0, "Cannot resolve 'socket'!\n");
420 526 exit(1); exit(1);
421 527 } }
422 528
423 529 old_close = dlsym(RTLD_NEXT, "close"); old_close = dlsym(RTLD_NEXT, "close");
424 530 if (old_close == NULL) { if (old_close == NULL) {
425 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'close'!\n");
531 xlog(0, "Cannot resolve 'close'!\n");
426 532 exit(1); exit(1);
427 533 } }
428 534
429 535 old_write = dlsym(RTLD_NEXT, "write"); old_write = dlsym(RTLD_NEXT, "write");
430 536 if (old_write == NULL) { if (old_write == NULL) {
431 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'write'!\n");
537 xlog(0, "Cannot resolve 'write'!\n");
432 538 exit(1); exit(1);
433 539 } }
434 540
435 541 old_send = dlsym(RTLD_NEXT, "send"); old_send = dlsym(RTLD_NEXT, "send");
436 542 if (old_send == NULL) { if (old_send == NULL) {
437 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'send'!\n");
543 xlog(0, "Cannot resolve 'send'!\n");
438 544 exit(1); exit(1);
439 545 } }
440 546
441 547 old_sendto = dlsym(RTLD_NEXT, "sendto"); old_sendto = dlsym(RTLD_NEXT, "sendto");
442 548 if (old_sendto == NULL) { if (old_sendto == NULL) {
443 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'sendto'!\n");
549 xlog(0, "Cannot resolve 'sendto'!\n");
444 550 exit(1); exit(1);
445 551 } }
446 552
447 553 old_sendmsg = dlsym(RTLD_NEXT, "sendmsg"); old_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
448 554 if (old_sendmsg == NULL) { if (old_sendmsg == NULL) {
449 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'sendmsg'!\n");
555 xlog(0, "Cannot resolve 'sendmsg'!\n");
450 556 exit(1); exit(1);
451 557 } }
452 558
453 559 old_accept = dlsym(RTLD_NEXT, "accept"); old_accept = dlsym(RTLD_NEXT, "accept");
454 560 if (old_accept == NULL) { if (old_accept == NULL) {
455 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'accept'!\n");
561 xlog(0, "Cannot resolve 'accept'!\n");
456 562 exit(1); exit(1);
457 563 } }
458 564
459 565 old_connect = dlsym(RTLD_NEXT, "connect"); old_connect = dlsym(RTLD_NEXT, "connect");
460 566 if (old_connect == NULL) { if (old_connect == NULL) {
461 my_syslog(LOG_ERR, "force_bind: Cannot resolve 'connect'!\n");
567 xlog(0, "Cannot resolve 'connect'!\n");
462 568 exit(1); exit(1);
463 569 } }
464 570
465 my_syslog(LOG_INFO, "force_bind: Init ended.\n");
571 xlog(1, "Init ended.\n");
466 572 } }
467 573
468 574 static int set_ka(int sockfd) static int set_ka(int sockfd)
 
... ... static int set_ka(int sockfd)
474 580
475 581 flag = (keepalive > 0) ? 1 : 0; flag = (keepalive > 0) ? 1 : 0;
476 582 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag));
477 my_syslog(LOG_INFO, "force_bind: changing SO_KEEPALIVE to %d (ret=%d(%s)) [%d].\n",
583 xlog(1, "changing SO_KEEPALIVE to %d (ret=%d(%s)) [%d].\n",
478 584 flag, ret, strerror(errno), sockfd); flag, ret, strerror(errno), sockfd);
479 585
480 586 return ret; return ret;
 
... ... static int set_ka_idle(int sockfd)
488 594 return 0; return 0;
489 595
490 596 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive));
491 my_syslog(LOG_INFO, "force_bind: changing TCP_KEEPIDLE to %us (ret=%d(%s)) [%d].\n",
597 xlog(1, "changing TCP_KEEPIDLE to %us (ret=%d(%s)) [%d].\n",
492 598 keepalive, ret, strerror(errno), sockfd); keepalive, ret, strerror(errno), sockfd);
493 599
494 600 return ret; return ret;
 
... ... static int set_mss(int sockfd)
502 608 return 0; return 0;
503 609
504 610 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss));
505 my_syslog(LOG_INFO, "force_bind: changing MSS to %u (ret=%d(%s)) [%d].\n",
611 xlog(1, "changing MSS to %u (ret=%d(%s)) [%d].\n",
506 612 mss, ret, strerror(errno), sockfd); mss, ret, strerror(errno), sockfd);
507 613
508 614 return ret; return ret;
 
... ... static int set_tos(int sockfd)
516 622 return 0; return 0;
517 623
518 624 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
519 my_syslog(LOG_INFO, "force_bind: changing TOS to %hhu (ret=%d(%s)) [%d].\n",
625 xlog(1, "changing TOS to %hhu (ret=%d(%s)) [%d].\n",
520 626 tos, ret, strerror(errno), sockfd); tos, ret, strerror(errno), sockfd);
521 627
522 628 return ret; return ret;
 
... ... static int set_ttl(int sockfd)
530 636 return 0; return 0;
531 637
532 638 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
533 my_syslog(LOG_INFO, "force_bind: changing TTL to %hhu (ret=%d(%s)) [%d].\n",
639 xlog(1, "changing TTL to %hhu (ret=%d(%s)) [%d].\n",
534 640 ttl, ret, strerror(errno), sockfd); ttl, ret, strerror(errno), sockfd);
535 641
536 642 return ret; return ret;
 
... ... static int set_reuseaddr(int sockfd)
544 650 return 0; return 0;
545 651
546 652 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
547 my_syslog(LOG_INFO, "force_bind: changing reuseaddr to %u (ret=%d(%s)) [%d].\n",
653 xlog(1, "changing reuseaddr to %u (ret=%d(%s)) [%d].\n",
548 654 reuseaddr, ret, strerror(errno), sockfd); reuseaddr, ret, strerror(errno), sockfd);
549 655
550 656 return ret; return ret;
 
... ... static int set_nodelay(int sockfd)
558 664 return 0; return 0;
559 665
560 666 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
561 my_syslog(LOG_INFO, "force_bind: changing nodelay to %u (ret=%d(%s)) [%d].\n",
667 xlog(1, "changing nodelay to %u (ret=%d(%s)) [%d].\n",
562 668 nodelay, ret, strerror(errno), sockfd); nodelay, ret, strerror(errno), sockfd);
563 669
564 670 return ret; return ret;
 
... ... static void set_flowinfo(int sockfd, struct private *p)
595 701 mgr.flr_share = IPV6_FL_S_ANY; mgr.flr_share = IPV6_FL_S_ANY;
596 702 mgr.flr_flags = IPV6_FL_F_CREATE; mgr.flr_flags = IPV6_FL_F_CREATE;
597 703 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &mgr, sizeof(mgr)); ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &mgr, sizeof(mgr));
598 my_syslog(LOG_INFO, "force_bind: flow mgr (ret=%d(%s)) [%d].\n",
704 xlog(1, "flow mgr (ret=%d(%s)) [%d].\n",
599 705 ret, strerror(errno), sockfd); ret, strerror(errno), sockfd);
600 706
601 707 yes = 1; yes = 1;
602 708 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &yes, sizeof(yes)); ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &yes, sizeof(yes));
603 my_syslog(LOG_INFO, "force_bind: changing flowinfo to 'yes' (ret=%d(%s)) [%d].\n",
709 xlog(1, "changing flowinfo to 'yes' (ret=%d(%s)) [%d].\n",
604 710 ret, strerror(errno), sockfd); ret, strerror(errno), sockfd);
605 711 } }
606 712
 
... ... static int set_fwmark(int sockfd)
612 718 return 0; return 0;
613 719
614 720 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark));
615 my_syslog(LOG_INFO, "force_bind: changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
721 xlog(1, "changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
616 722 fwmark, ret, strerror(errno), sockfd); fwmark, ret, strerror(errno), sockfd);
617 723
618 724 return ret; return ret;
 
... ... static int set_prio(int sockfd)
626 732 return 0; return 0;
627 733
628 734 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
629 my_syslog(LOG_INFO, "force_bind: changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
735 xlog(1, "changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
630 736 prio, ret, strerror(errno), sockfd); prio, ret, strerror(errno), sockfd);
631 737
632 738 return ret; return ret;
 
... ... static int set_prio(int sockfd)
634 740
635 741 /* /*
636 742 * Alters a struct sockaddr, based on environment variables * Alters a struct sockaddr, based on environment variables
743 * Returns 1 if the struct was altered, 0 otherwise.
637 744 */ */
638 static void alter_sa(const int sockfd, struct sockaddr *sa)
745 static int alter_sa(const int sockfd, struct sockaddr *sa)
639 746 { {
640 747 struct sockaddr_in *sa4; struct sockaddr_in *sa4;
641 748 struct sockaddr_in6 *sa6; struct sockaddr_in6 *sa6;
 
... ... static void alter_sa(const int sockfd, struct sockaddr *sa)
643 750 void *p; void *p;
644 751 char *force_address; char *force_address;
645 752 int force_port; int force_port;
646 int err;
753 int err, ret = 0;
754
755 xlog(2, "alter_sa(sockfd=%d, ...)\n", sockfd);
647 756
648 757 switch (sa->sa_family) { switch (sa->sa_family) {
649 758 case AF_INET: case AF_INET:
 
... ... static void alter_sa(const int sockfd, struct sockaddr *sa)
663 772 break; break;
664 773
665 774 default: default:
666 my_syslog(LOG_INFO, "force_bind: unsupported family=%u [%d]!\n",
775 xlog(1, "unsupported family=%u [%d]!\n",
667 776 sa->sa_family, sockfd); sa->sa_family, sockfd);
668 return;
777 return 0;
669 778 } }
670 779
671 780 if (force_address != NULL) { if (force_address != NULL) {
672 781 err = inet_pton(sa->sa_family, force_address, p); err = inet_pton(sa->sa_family, force_address, p);
673 782 if (err != 1) { if (err != 1) {
674 my_syslog(LOG_INFO, "force_bind: cannot convert [%s] (%d) (%s) [%d]!\n",
783 xlog(1, "cannot convert [%s] (%d) (%s) [%d]!\n",
675 784 force_address, err, strerror(errno), sockfd); force_address, err, strerror(errno), sockfd);
676 return;
785 return 0;
677 786 } }
787 ret = 1;
678 788 } }
679 789
680 if (force_port != -1)
790 if (force_port != -1) {
681 791 *pport = htons(force_port); *pport = htons(force_port);
792 ret = 1;
793 }
794
795 return ret;
682 796 } }
683 797
684 798 /* /*
 
... ... static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len
689 803 struct node *q; struct node *q;
690 804 struct sockaddr *sa = (struct sockaddr *) ss; struct sockaddr *sa = (struct sockaddr *) ss;
691 805 struct sockaddr_in6 *sa6; struct sockaddr_in6 *sa6;
806 char addr[64];
692 807
693 808 init(); init();
694 809
810 saddr(addr, ss);
811 xlog(2, "alter_dest_sa(sockfd=%d, [domain=%s, addr=%s])\n",
812 sockfd, sdomain(ss->ss_family), addr);
813
695 814 /* We do not touch non network sockets */ /* We do not touch non network sockets */
696 815 q = get(sockfd); q = get(sockfd);
697 816 if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)) if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0))
 
... ... static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len
701 820 case AF_INET6: case AF_INET6:
702 821 sa6 = (struct sockaddr_in6 *) sa; sa6 = (struct sockaddr_in6 *) sa;
703 822 if (force_flowinfo == 1) { if (force_flowinfo == 1) {
704 my_syslog(LOG_INFO, "force_bind: changing flowinfo from 0x%x to 0x%x [%d]!\n",
823 xlog(1, "changing flowinfo from 0x%x to 0x%x [%d]!\n",
705 824 ntohl(sa6->sin6_flowinfo), flowinfo, sockfd); ntohl(sa6->sin6_flowinfo), flowinfo, sockfd);
706 825 sa6->sin6_flowinfo = htonl(flowinfo); sa6->sin6_flowinfo = htonl(flowinfo);
707 826 } }
 
... ... static void change_local_binding(int sockfd)
727 846
728 847 init(); init();
729 848
849 xlog(2, "change_local_binding(sockfd=%d)\n", sockfd);
850
730 851 /* We do not touch non network sockets */ /* We do not touch non network sockets */
731 852 q = get(sockfd); q = get(sockfd);
732 853 if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)) if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0))
 
... ... static void change_local_binding(int sockfd)
739 860 tmp_len = sizeof(struct sockaddr_storage); tmp_len = sizeof(struct sockaddr_storage);
740 861 err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len); err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len);
741 862 if (err != 0) { if (err != 0) {
742 my_syslog(LOG_INFO, "force_bind: Cannot get socket name err=%d (%s) [%d]!\n",
863 xlog(1, "Cannot get socket name err=%d (%s) [%d]!\n",
743 864 err, strerror(errno), sockfd); err, strerror(errno), sockfd);
744 865 return; return;
745 866 } }
746 alter_sa(sockfd, (struct sockaddr *) &tmp);
867
868 if (alter_sa(sockfd, (struct sockaddr *) &tmp) == 0)
869 return;
870
747 871 err = old_bind(sockfd, (struct sockaddr *) &tmp, tmp_len); err = old_bind(sockfd, (struct sockaddr *) &tmp, tmp_len);
748 872 q->priv.flags |= FB_FLAGS_BIND_CALLED; q->priv.flags |= FB_FLAGS_BIND_CALLED;
749 873 if (err != 0) if (err != 0)
750 my_syslog(LOG_INFO, "force_bind: Cannot bind err=%d (%s) [%d]!\n",
874 xlog(1, "Cannot bind err=%d (%s) [%d]!\n",
751 875 err, strerror(errno), sockfd); err, strerror(errno), sockfd);
752 876 } }
753 877
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
756 880 struct node *q; struct node *q;
757 881 struct sockaddr_storage new; struct sockaddr_storage new;
758 882
759 memcpy(&new, addr, addrlen);
760
761 883 init(); init();
762 884
885 xlog(1, "bind(sockfd=%d, ...)!\n", sockfd);
886
887 memcpy(&new, addr, addrlen);
888
763 889 /* We do not touch non network sockets */ /* We do not touch non network sockets */
764 890 q = get(sockfd); q = get(sockfd);
765 891 if ((q != NULL) && ((q->priv.flags & FB_FLAGS_NETSOCK) != 0)) { if ((q != NULL) && ((q->priv.flags & FB_FLAGS_NETSOCK) != 0)) {
 
... ... void socket_create_callback(const int sockfd, int domain, int type)
814 940
815 941 init(); init();
816 942
943 xlog(2, "socket_create_callback(%d, %s, %s)\n",
944 sockfd, sdomain(domain), stype(type));
945
817 946 set_tos(sockfd); set_tos(sockfd);
818 947 set_ttl(sockfd); set_ttl(sockfd);
819 948 set_ka(sockfd); set_ka(sockfd);
 
... ... void socket_create_callback(const int sockfd, int domain, int type)
830 959 p.flags = FB_FLAGS_NETSOCK; p.flags = FB_FLAGS_NETSOCK;
831 960 memset(&p.dest, 0, sizeof(struct sockaddr_storage)); memset(&p.dest, 0, sizeof(struct sockaddr_storage));
832 961 p.dest_len = 0; p.dest_len = 0;
962 p.limit = 0;
963 p.rest = 0;
964 p.last.tv_sec = p.last.tv_usec = 0;
833 965 add(sockfd, &p); add(sockfd, &p);
834 966 } }
835 967
 
... ... int socket(int domain, int type, int protocol)
842 974
843 975 init(); init();
844 976
977 xlog(1, "socket(domain=%s, type=%s, protocol=%d)\n",
978 sdomain(domain), stype(type), sprotocol(protocol));
979
845 980 sockfd = old_socket(domain, type, protocol); sockfd = old_socket(domain, type, protocol);
846 981 if (sockfd == -1) if (sockfd == -1)
847 982 return -1; return -1;
 
... ... static void bw(const int sockfd, const ssize_t bytes)
864 999 struct node *q; struct node *q;
865 1000 struct private *p; struct private *p;
866 1001
1002 xlog(2, "bw(sockfd=%d, bytes=%zd)\n", sockfd, bytes);
1003
867 1004 if (bytes <= 0) if (bytes <= 0)
868 1005 return; return;
869 1006
 
... ... static void bw(const int sockfd, const ssize_t bytes)
923 1060 continue; continue;
924 1061 } }
925 1062
926 my_syslog(LOG_INFO, "force_bind: nanosleep returned error"
1063 xlog(1, "nanosleep returned error"
927 1064 " (%d) (%s).\n", " (%d) (%s).\n",
928 1065 err, strerror(errno)); err, strerror(errno));
929 1066 } }
 
... ... int close(int fd)
936 1073 { {
937 1074 init(); init();
938 1075
1076 xlog(1, "close(fd=%d)\n", fd);
1077
939 1078 del(fd); del(fd);
940 1079
941 1080 return old_close(fd); return old_close(fd);
 
... ... ssize_t send(int sockfd, const void *buf, size_t len, int flags)
955 1094 { {
956 1095 ssize_t n; ssize_t n;
957 1096
1097 xlog(1, "send(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1098 sockfd, len, flags);
1099
958 1100 n = old_send(sockfd, buf, len, flags); n = old_send(sockfd, buf, len, flags);
959 1101 bw(sockfd, n); bw(sockfd, n);
960 1102
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
967 1109 ssize_t n; ssize_t n;
968 1110 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
969 1111
1112 xlog(1, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
1113 sockfd, len, flags);
1114
970 1115 change_local_binding(sockfd); change_local_binding(sockfd);
971 1116
972 1117 memcpy(&new_dest, dest_addr, addrlen); memcpy(&new_dest, dest_addr, addrlen);
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
988 1133 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
989 1134 */ */
990 1135
1136 xlog(1, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
1137 sockfd, flags);
1138
991 1139 change_local_binding(sockfd); change_local_binding(sockfd);
992 1140
993 1141 /* TODO: how do we alter flowinfo in this case?! /* TODO: how do we alter flowinfo in this case?!
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1013 1161
1014 1162 init(); init();
1015 1163
1164 xlog(2, "accept(sockfd=%d, ...)\n", sockfd);
1165
1016 1166 new_sock = old_accept(sockfd, addr, addrlen); new_sock = old_accept(sockfd, addr, addrlen);
1017 1167 if (new_sock == -1) if (new_sock == -1)
1018 1168 return -1; return -1;
 
... ... int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1032 1182 { {
1033 1183 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
1034 1184
1185 xlog(2, "connect(sockfd=%d, ...)\n", sockfd);
1186
1035 1187 change_local_binding(sockfd); change_local_binding(sockfd);
1036 1188
1037 1189 memcpy(&new_dest, addr, addrlen); memcpy(&new_dest, addr, addrlen);
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/force_bind

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/force_bind

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/force_bind

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main