diff --git a/read_config.c b/read_config.c index a3449d9..70f3531 100644 --- a/read_config.c +++ b/read_config.c @@ -493,8 +493,28 @@ parse_receiver (struct receiver *receiverp, char portspec[NI_MAXSERV]; struct addrinfo hints, *res; int result; - + receiverp->flags = ctx->default_receiver_flags; + + if(receiverp->flags & pf_SPOOF_WITH_IP) { + + init_hints_from_preferences (&hints, ctx); + { + result = getaddrinfo (ctx->spoofed_src_addr, NULL, &hints, &res); + + if (result != 0) + { + return parse_error (ctx, "Parsing IP address (%s) failed", ctx->spoofed_src_addr); + } + + memcpy (&(receiverp->spoofed_src_addr), res->ai_addr, res->ai_addrlen); + receiverp->spoofed_src_addrlen = res->ai_addrlen; + freeaddrinfo(res); + } + + + } + receiverp->freqcount = 0; receiverp->freq = 1; receiverp->ttl = DEFAULT_TTL; @@ -768,6 +788,9 @@ parse_args (argc, argv, ctx) ctx->pid_file = (const char *) 0; ctx->sources = 0; ctx->default_receiver_flags = pf_CHECKSUM; + + ctx->spoofed_src_addr = NULL; + /* assume that command-line supplied receivers want to get all data */ sctx->source.ss_family = AF_INET; ((struct sockaddr_in *) &sctx->source)->sin_addr.s_addr = 0; @@ -776,7 +799,7 @@ parse_args (argc, argv, ctx) sctx->tx_delay = 0; optind = 1; - while ((i = getopt (argc, (char **) argv, "hu:b:d:t:m:p:s:x:c:fSn46")) != -1) + while ((i = getopt (argc, (char **) argv, "P:hu:b:d:t:m:p:s:x:c:fSn46")) != -1) { switch (i) { @@ -807,9 +830,13 @@ parse_args (argc, argv, ctx) case 'x': /* transmit delay */ sctx->tx_delay = atoi (optarg); break; + case 'P': + ctx->default_receiver_flags |= pf_SPOOF_WITH_IP; + ctx->spoofed_src_addr = optarg; + break; case 'S': /* spoof */ - ctx->default_receiver_flags |= pf_SPOOF; - break; + ctx->default_receiver_flags |= pf_SPOOF; + break; case 'c': /* config file */ if (read_cf_file (optarg, ctx) != 0) { @@ -868,8 +895,9 @@ Supported options:\n\ -t Exit with RC 5 if no data is received for this\n\ amount of milliseconds\n\ -b set socket buffer size (default %lu)\n\ - -n don't compute UDP checksum (leave at 0)\n\ + -n don't compute UDP checksum (leave at 0)\n\ -S maintain (spoof) source addresses\n\ + -P
spoof source address with specified address\n\ -x transmit delay in microseconds\n\ -c specify a config file to read\n\ -f fork program into background\n\ diff --git a/samplicate.c b/samplicate.c index 409ce97..a3f44fe 100644 --- a/samplicate.c +++ b/samplicate.c @@ -483,6 +483,16 @@ send_pdu_to_receiver (receiver, fpdu, length, source_addr) (struct sockaddr *) &receiver->addr, receiver->ttl, rawsend_flags); } + else if(receiver->flags & pf_SPOOF_WITH_IP) + { + + int rawsend_flags + = ((receiver->flags & pf_CHECKSUM) ? RAWSEND_COMPUTE_UDP_CHECKSUM : 0); + return raw_send_from_to (receiver->fd, fpdu, length, + (struct sockaddr *) &receiver->spoofed_src_addr, + (struct sockaddr *) &receiver->addr, + receiver->ttl, rawsend_flags); + } else { return sendto (receiver->fd, (char*) fpdu, length, 0, @@ -539,7 +549,7 @@ make_send_sockets (struct samplicator_context *ctx) struct receiver *receiver = &sctx->receivers[i]; int af = receiver->addr.ss_family; int af_index = af == AF_INET ? 0 : 1; - int spoof_p = receiver->flags & pf_SPOOF; + int spoof_p = receiver->flags & pf_SPOOF || receiver->flags & pf_SPOOF_WITH_IP; if (socks[spoof_p][af_index] == -1) { diff --git a/samplicator.h b/samplicator.h index 630ea11..6cd8609 100644 --- a/samplicator.h +++ b/samplicator.h @@ -12,6 +12,8 @@ enum receiver_flags { pf_SPOOF = 0x0001, pf_CHECKSUM = 0x0002, + pf_SPOOF_WITH_IP = 0x0004, + }; struct samplicator_context { @@ -34,6 +36,8 @@ struct samplicator_context { const char *config_file_name; int config_file_lineno; + + const char *spoofed_src_addr; /* statistics */ uint32_t unmatched_packets; @@ -48,6 +52,10 @@ struct receiver { int freqcount; int ttl; enum receiver_flags flags; + + struct sockaddr_storage spoofed_src_addr; + socklen_t spoofed_src_addrlen; + /* statistics */ uint32_t out_packets;