From 729eb50738777d6dbc27f81d854c824b32bebb05 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Fri, 6 May 2016 15:14:16 +0200 Subject: ripe-atlas-fw: imported version 4730 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- eperd/traceroute.c | 524 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 463 insertions(+), 61 deletions(-) (limited to 'eperd/traceroute.c') diff --git a/eperd/traceroute.c b/eperd/traceroute.c index 4875721..c446d8e 100644 --- a/eperd/traceroute.c +++ b/eperd/traceroute.c @@ -28,7 +28,7 @@ #define uh_sum check #endif -#define TRACEROUTE_OPT_STRING ("!46IUFrTa:b:c:f:g:i:m:p:w:z:A:O:S:H:D:") +#define TRACEROUTE_OPT_STRING ("!46IUFrTa:b:c:f:g:i:m:p:w:z:A:O:S:H:D:R:W:") #define OPT_4 (1 << 0) #define OPT_6 (1 << 1) @@ -103,6 +103,9 @@ struct trtstate unsigned duptimeout; unsigned timeout; + char *response_in; /* Fuzzing */ + char *response_out; + /* Base and index in table */ struct trtbase *base; int index; @@ -157,6 +160,8 @@ struct trtstate size_t reslen; size_t resmax; char open_result; + + FILE *resp_file_out; /* Fuzzing */ }; static struct trtbase *trt_base; @@ -189,6 +194,12 @@ struct v6info }; static int create_socket(struct trtstate *state, int do_tcp); +static void ready_callback4(int __attribute((unused)) unused, + const short __attribute((unused)) event, void *s); +static void ready_tcp4(int __attribute((unused)) unused, + const short __attribute((unused)) event, void *s); +static void ready_callback6(int __attribute((unused)) unused, + const short __attribute((unused)) event, void *s); #define OPT_PAD1 0 #define OPT_PADN 1 @@ -528,7 +539,12 @@ static void send_pkt(struct trtstate *state) if (state->do_tcp) { - sock= socket(AF_INET6, SOCK_RAW, IPPROTO_TCP); + if (state->response_in) + sock= open("/dev/null", O_RDWR); + else + { + sock= socket(AF_INET6, SOCK_RAW, IPPROTO_TCP); + } if (sock == -1) { crondlog(DIE9 "socket failed"); @@ -552,9 +568,14 @@ static void send_pkt(struct trtstate *state) #endif /* Bind to source addr/port */ - r= bind(sock, - (struct sockaddr *)&state->loc_sin6, - state->loc_socklen); + if (state->response_in) + r= 0; /* No need to bind */ + else + { + r= bind(sock, + (struct sockaddr *)&state->loc_sin6, + state->loc_socklen); + } if (r == -1) { serrno= errno; @@ -618,9 +639,14 @@ static void send_pkt(struct trtstate *state) sin6copy= state->sin6; sin6copy.sin6_port= 0; - r= sendto(sock, base->packet, len, 0, - (struct sockaddr *)&sin6copy, - state->socklen); + if (state->response_in) + r= 0; /* No need to send anything */ + else + { + r= sendto(sock, base->packet, len, 0, + (struct sockaddr *)&sin6copy, + state->socklen); + } #if 0 { static int doit=1; if (doit && r != -1) @@ -725,9 +751,15 @@ static void send_pkt(struct trtstate *state) memset(&sin6copy, '\0', sizeof(sin6copy)); sin6copy.sin6_family= AF_INET6; sin6copy.sin6_addr= state->sin6.sin6_addr; - r= sendto(state->socket_icmp, base->packet, len, 0, - (struct sockaddr *)&sin6copy, - sizeof(sin6copy)); + + if (state->response_in) + r= 0; + else + { + r= sendto(state->socket_icmp, base->packet, + len, 0, (struct sockaddr *)&sin6copy, + sizeof(sin6copy)); + } #if 0 { static int doit=1; if (doit && r != -1) @@ -752,7 +784,12 @@ static void send_pkt(struct trtstate *state) } else if (state->do_udp) { - sock= socket(AF_INET6, SOCK_DGRAM, 0); + if (state->response_in) + sock= open("/dev/null", O_RDWR); + else + { + sock= socket(AF_INET6, SOCK_DGRAM, 0); + } if (sock == -1) { crondlog(DIE9 "socket failed"); @@ -774,9 +811,14 @@ static void send_pkt(struct trtstate *state) } /* Bind to source addr/port */ - r= bind(sock, - (struct sockaddr *)&state->loc_sin6, - state->loc_socklen); + if (state->response_in) + r= 0; /* No need to bind */ + else + { + r= bind(sock, + (struct sockaddr *)&state->loc_sin6, + state->loc_socklen); + } if (r == -1) { serrno= errno; @@ -840,9 +882,14 @@ static void send_pkt(struct trtstate *state) len= state->curpacksize; } - r= sendto(sock, base->packet, len, 0, - (struct sockaddr *)&state->sin6, - state->socklen); + if (state->response_in) + r= 0; /* No need to bind */ + else + { + r= sendto(sock, base->packet, len, 0, + (struct sockaddr *)&state->sin6, + state->socklen); + } #if 0 { static int doit=1; if (doit && r != -1) @@ -878,7 +925,12 @@ static void send_pkt(struct trtstate *state) if (state->do_tcp) { - sock= socket(AF_INET, SOCK_RAW, IPPROTO_TCP); + if (state->response_in) + sock= open("/dev/null", O_RDWR); + else + { + sock= socket(AF_INET, SOCK_RAW, IPPROTO_TCP); + } if (sock == -1) { crondlog(DIE9 "socket failed"); @@ -889,9 +941,14 @@ static void send_pkt(struct trtstate *state) sizeof(on)); /* Bind to source addr/port */ - r= bind(sock, - (struct sockaddr *)&state->loc_sin6, - state->loc_socklen); + if (state->response_in) + r= 0; + else + { + r= bind(sock, + (struct sockaddr *)&state->loc_sin6, + state->loc_socklen); + } #if 0 { static int doit=1; if (doit && r != -1) { errno= ENOSYS; r= -1; } doit= !doit; } @@ -986,9 +1043,14 @@ static void send_pkt(struct trtstate *state) setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &on, sizeof(on)); - r= sendto(sock, base->packet, len, 0, - (struct sockaddr *)&state->sin6, - state->socklen); + if (state->response_in) + r= 0; /* No need to send */ + else + { + r= sendto(sock, base->packet, len, 0, + (struct sockaddr *)&state->sin6, + state->socklen); + } #if 0 { static int doit=0; if (doit && r != -1) @@ -1071,9 +1133,14 @@ static void send_pkt(struct trtstate *state) setsockopt(state->socket_icmp, IPPROTO_IP, IP_MTU_DISCOVER, &on, sizeof(on)); - r= sendto(state->socket_icmp, base->packet, len, 0, - (struct sockaddr *)&state->sin6, - state->socklen); + if (state->response_in) + r= 0; /* No need to send packet */ + else + { + r= sendto(state->socket_icmp, base->packet, len, 0, + (struct sockaddr *)&state->sin6, + state->socklen); + } #if 0 { static int doit=1; if (doit && r != -1) @@ -1254,6 +1321,13 @@ static void send_pkt(struct trtstate *state) interval.tv_usec= state->timeout % 1000000; evtimer_add(&state->timer, &interval); + if (state->response_in) + { + if (state->sin6.sin6_family == AF_INET6) + ready_callback6(0, 0, state); + else + ready_callback4(0, 0, state); + } } static void do_mpls(struct trtstate *state, unsigned char *packet, @@ -1373,8 +1447,75 @@ static void ready_callback4(int __attribute((unused)) unused, base= state->base; slen= sizeof(remote); - nrecv= recvfrom(state->socket_icmp, base->packet, sizeof(base->packet), - MSG_DONTWAIT, (struct sockaddr *)&remote, &slen); + if (state->response_in) + { + uint8_t proto; + uint32_t len; + + if (read(state->socket_icmp, &proto, sizeof(proto)) != sizeof(proto)) + { + //printf("ready_callback4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback4: error reading from '%s'", + state->response_in); + } + if (proto == 0) + { + printf("ready_callback4: proto 0 -> timeout\n"); + return; /* Timeout */ + } + if (proto == 6) + { + printf("ready_callback4: proto 6 -> TCP\n"); + ready_tcp4(0, 0, s); + return; + } + if (proto != 1) + { + printf("ready_callback4: proto != 1\n"); + return; + } + + if (read(state->socket_icmp, &len, sizeof(len)) != sizeof(len)) + { + //printf("ready_callback4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback4: error reading from '%s'", + state->response_in); + } + if (len > sizeof(base->packet)) + { + //printf("ready_callback4: bad value for len: %u\n", len); + //abort(); + crondlog(DIE9 "ready_callback4: bad value for len: %u", + len); + } + if (read(state->socket_icmp, base->packet, len) != len) + { + //printf("ready_callback4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback4: error reading from '%s'", + state->response_in); + } + if (read(state->socket_icmp, &remote, sizeof(remote)) != + sizeof(remote)) + { + //printf("ready_callback4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback4: error reading from '%s'", + state->response_in); + } + nrecv= len; + } + else + { + nrecv= recvfrom(state->socket_icmp, base->packet, sizeof(base->packet), + MSG_DONTWAIT, (struct sockaddr *)&remote, &slen); + } if (nrecv == -1) { /* Strange, read error */ @@ -1383,6 +1524,17 @@ static void ready_callback4(int __attribute((unused)) unused, } // printf("ready_callback4: got packet\n"); + if (state->resp_file_out) + { + uint8_t proto= 1; + uint32_t len= nrecv; + + fwrite(&proto, sizeof(proto), 1, state->resp_file_out); + fwrite(&len, sizeof(len), 1, state->resp_file_out); + fwrite(base->packet, len, 1, state->resp_file_out); + fwrite(&remote, sizeof(remote), 1, state->resp_file_out); + } + ip= (struct ip *)base->packet; hlen= ip->ip_hl*4; @@ -1541,6 +1693,8 @@ static void ready_callback4(int __attribute((unused)) unused, { printf("ready_callback4: changed source %s\n", inet_ntoa(eip->ip_src)); + printf("ready_callback4: expected %s\n", + inet_ntoa(((struct sockaddr_in *)&state->loc_sin6)->sin_addr)); } if (memcmp(&eip->ip_dst, &((struct sockaddr_in *)&state->sin6)-> @@ -1607,7 +1761,6 @@ static void ready_callback4(int __attribute((unused)) unused, nextmtu; } } -printf("curpacksize: %d\n", state->curpacksize); if (!late) state->not_done= 1; break; @@ -1820,7 +1973,6 @@ printf("curpacksize: %d\n", state->curpacksize); nextmtu; } } -printf("curpacksize: %d\n", state->curpacksize); if (!late) state->not_done= 1; break; @@ -1903,7 +2055,6 @@ printf("curpacksize: %d\n", state->curpacksize); } if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf( "ready_callback4: index (%d) is not busy\n", ind); @@ -1983,6 +2134,8 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family { printf("ready_callback4: changed source %s\n", inet_ntoa(eip->ip_src)); + printf("ready_callback4: expected %s\n", + inet_ntoa(((struct sockaddr_in *)&state->loc_sin6)->sin_addr)); } if (memcmp(&eip->ip_dst, &((struct sockaddr_in *)&state->sin6)-> @@ -2179,7 +2332,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf( "ready_callback4: index (%d) is not busy\n", ind); @@ -2344,8 +2496,51 @@ static void ready_tcp4(int __attribute((unused)) unused, base= state->base; slen= sizeof(remote); - nrecv= recvfrom(state->socket_tcp, base->packet, sizeof(base->packet), - MSG_DONTWAIT, (struct sockaddr *)&remote, &slen); + + if (state->response_in) + { + uint32_t len; + + /* Proto is eaten by ready_callback4 */ + if (read(state->socket_icmp, &len, sizeof(len)) != sizeof(len)) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + if (len > sizeof(base->packet)) + { + //printf("ready_tcp4: bad value for len: %u\n", len); + //abort(); + crondlog(DIE9 "ready_tcp4: bad value for len: %u", + len); + } + if (read(state->socket_icmp, base->packet, len) != len) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + if (read(state->socket_icmp, &remote, sizeof(remote)) != + sizeof(remote)) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + nrecv= len; + } + else + { + nrecv= recvfrom(state->socket_tcp, base->packet, sizeof(base->packet), + MSG_DONTWAIT, (struct sockaddr *)&remote, &slen); + } if (nrecv == -1) { /* Strange, read error */ @@ -2353,6 +2548,17 @@ static void ready_tcp4(int __attribute((unused)) unused, return; } + if (state->resp_file_out) + { + uint8_t proto= 6; + uint32_t len= nrecv; + + fwrite(&proto, sizeof(proto), 1, state->resp_file_out); + fwrite(&len, sizeof(len), 1, state->resp_file_out); + fwrite(base->packet, len, 1, state->resp_file_out); + fwrite(&remote, sizeof(remote), 1, state->resp_file_out); + } + ip= (struct ip *)base->packet; hlen= ip->ip_hl*4; @@ -2399,7 +2605,6 @@ static void ready_tcp4(int __attribute((unused)) unused, if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf( "ready_callback4: index (%d) is not busy\n", ind); @@ -2416,7 +2621,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family seq= ntohl(tcphdr->ack_seq) & 0xffff; if (seq-state->seq > 0x2000) { -printf("got seq %d, expected %d\n", seq, state->seq); if (seq > state->seq) { #if 0 @@ -2537,7 +2741,47 @@ static void ready_tcp6(int __attribute((unused)) unused, msg.msg_controllen= sizeof(cmsgbuf); msg.msg_flags= 0; /* Not really needed */ - nrecv= recvmsg(state->socket_tcp, &msg, MSG_DONTWAIT); + if (state->response_in) + { + uint32_t len; + + /* Proto is eaten by ready_callback4 */ + if (read(state->socket_icmp, &len, sizeof(len)) != sizeof(len)) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + if (len > sizeof(base->packet)) + { + //printf("ready_tcp4: bad value for len: %u\n", len); + //abort(); + crondlog(DIE9 "ready_tcp4: bad value for len: %u", + len); + } + if (read(state->socket_icmp, base->packet, len) != len) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + if (read(state->socket_icmp, &remote, sizeof(remote)) != + sizeof(remote)) + { + //printf("ready_tcp4: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_tcp4: error reading from '%s'", + state->response_in); + } + nrecv= len; + } + else + nrecv= recvmsg(state->socket_tcp, &msg, MSG_DONTWAIT); if (nrecv == -1) { /* Strange, read error */ @@ -2545,6 +2789,17 @@ static void ready_tcp6(int __attribute((unused)) unused, return; } + if (state->resp_file_out) + { + uint8_t proto= 6; + uint32_t len= nrecv; + + fwrite(&proto, sizeof(proto), 1, state->resp_file_out); + fwrite(&len, sizeof(len), 1, state->resp_file_out); + fwrite(base->packet, len, 1, state->resp_file_out); + fwrite(&remote, sizeof(remote), 1, state->resp_file_out); + } + rcvdttl= -42; /* To spot problems */ memset(&dstaddr, '\0', sizeof(dstaddr)); for (cmsgptr= CMSG_FIRSTHDR(&msg); cmsgptr; @@ -2601,7 +2856,6 @@ static void ready_tcp6(int __attribute((unused)) unused, if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf("ready_tcp6: index (%d) is not busy\n", ind); return; } @@ -2616,7 +2870,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family seq= ntohl(tcphdr->ack_seq) & 0xffff; if (seq-state->seq > 0x2000) { -printf("got seq %d, expected %d\n", seq, state->seq); if (seq > state->seq) { #if 0 @@ -2717,7 +2970,7 @@ static void ready_callback6(int __attribute((unused)) unused, struct v6info *v6info; struct cmsghdr *cmsgptr; void *ptr; - double ms; + double ms= -42; /* lint, to spot problems */ struct timespec now; struct sockaddr_in6 remote; struct in6_addr dstaddr; @@ -2743,7 +2996,76 @@ static void ready_callback6(int __attribute((unused)) unused, msg.msg_controllen= sizeof(cmsgbuf); msg.msg_flags= 0; /* Not really needed */ - nrecv= recvmsg(state->socket_icmp, &msg, MSG_DONTWAIT); + /* Receive data from the network */ + if (state->response_in) + { + uint8_t proto; + uint32_t len; + + if (read(state->socket_icmp, &proto, sizeof(proto)) != sizeof(proto)) + { + crondlog(DIE9 "ready_callback6: error reading from '%s'", + state->response_in); + } + if (proto == 0) + { + printf("ready_callback6: proto 0 -> timeout\n"); + return; /* Timeout */ + } + if (proto == 6) + { + printf("ready_callback6: proto 6 -> TCP\n"); + ready_tcp6(0, 0, s); + return; + } + if (proto != 1) + { + printf("ready_callback6: proto != 1\n"); + return; + } + + if (read(state->socket_icmp, &len, sizeof(len)) != sizeof(len)) + { + //printf("ready_callback6: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback6: error reading from '%s'", + state->response_in); + } + if (len > sizeof(base->packet)) + { + //printf("ready_callback6: bad value for len: %u\n", len); + //abort(); + crondlog(DIE9 "ready_callback6: bad value for len: %u", + len); + } + if (read(state->socket_icmp, base->packet, len) != len) + { + //printf("ready_callback6: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback6: error reading from '%s'", + state->response_in); + } + if (read(state->socket_icmp, &remote, sizeof(remote)) != + sizeof(remote)) + { + //printf("ready_callback6: error reading from '%s'\n", + // state->response_in); + //abort(); + crondlog(DIE9 "ready_callback6: error reading from '%s'", + state->response_in); + } + + nrecv= len; + + /* Do not try to fuzz the cmsgbuf. We assume stuff returned by + * the kernel can be trusted. + */ + memset(cmsgbuf, '\0', sizeof(cmsgbuf)); + } + else + nrecv= recvmsg(state->socket_icmp, &msg, MSG_DONTWAIT); if (nrecv == -1) { /* Strange, read error */ @@ -2751,6 +3073,17 @@ static void ready_callback6(int __attribute((unused)) unused, return; } + if (state->response_out) + { + uint8_t proto= 1; + uint32_t len= nrecv; + + fwrite(&proto, sizeof(proto), 1, state->resp_file_out); + fwrite(&len, sizeof(len), 1, state->resp_file_out); + fwrite(base->packet, len, 1, state->resp_file_out); + fwrite(&remote, sizeof(remote), 1, state->resp_file_out); + } + rcvdttl= -42; /* To spot problems */ memset(&dstaddr, '\0', sizeof(dstaddr)); for (cmsgptr= CMSG_FIRSTHDR(&msg); cmsgptr; @@ -3003,7 +3336,6 @@ static void ready_callback6(int __attribute((unused)) unused, if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf( "ready_callback6: index (%d) is not busy\n", ind); @@ -3316,7 +3648,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family if (!state->busy) { -printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family); printf( "ready_callback6: index (%d) is not busy\n", ind); @@ -3452,8 +3783,7 @@ static void noreply_callback(int __attribute((unused)) unused, state= s; #if 0 - printf("noreply_callback: gotresp = %d\n", - state->gotresp); + printf("noreply_callback: gotresp = %d\n", state->gotresp); #endif if (!state->gotresp) @@ -3462,6 +3792,14 @@ static void noreply_callback(int __attribute((unused)) unused, add_str(state, " }, { "); add_str(state, DBQ(x) ":" DBQ(*)); state->open_result= 1; + + if (state->resp_file_out) + { + uint32_t len= 0; + + /* Use a zero length packet to signal a timeout */ + fwrite(&len, sizeof(len), 1, state->resp_file_out); + } } send_pkt(state); @@ -3481,6 +3819,7 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[], const char *hostname; char *out_filename; const char *destportstr; + char *response_in, *response_out; char *interface; char *check; struct trtstate *state; @@ -3511,6 +3850,8 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[], destoptsize= 0; str_Atlas= NULL; out_filename= NULL; + response_in= NULL; + response_out= NULL; opt_complementary = "=1:4--6:i--u:a+:b+:c+:f+:g+:m+:w+:z+:S+:H+:D+"; for (i= 0; argv[i] != NULL; i++) @@ -3521,7 +3862,7 @@ for (i= 0; argv[i] != NULL; i++) &firsthop, &gaplimit, &interface, &maxhops, &destportstr, &timeout, &duptimeout, &str_Atlas, &out_filename, &maxpacksize, - &hbhoptsize, &destoptsize); + &hbhoptsize, &destoptsize, &response_in, &response_out); hostname = argv[optind]; if (opt == 0xffffffff) @@ -3534,11 +3875,31 @@ for (i= 0; argv[i] != NULL; i++) do_v6= !!(opt & OPT_6); dont_fragment= !!(opt & OPT_F); delay_name_res= !!(opt & OPT_r); + delay_name_res= 1; /* Always enabled, leave the old code in + * place for now. + */ do_tcp= !!(opt & OPT_T); do_udp= !(do_icmp || do_tcp); if (maxpacksize > sizeof(trt_base->packet)) maxpacksize= sizeof(trt_base->packet); + if (response_in) + { + if (!validate_filename(response_in, ATLAS_FUZZING)) + { + crondlog(LVL8 "insecure fuzzing file '%s'", response_in); + return NULL; + } + } + if (response_out) + { + if (!validate_filename(response_out, ATLAS_FUZZING)) + { + crondlog(LVL8 "insecure fuzzing file '%s'", response_out); + return NULL; + } + } + if (out_filename) { if (!validate_filename(out_filename, SAFE_PREFIX)) @@ -3618,6 +3979,8 @@ for (i= 0; argv[i] != NULL; i++) state->hbhoptsize= hbhoptsize; state->destoptsize= destoptsize; state->out_filename= out_filename ? strdup(out_filename) : NULL; + state->response_in= response_in; + state->response_out= response_out; state->base= trt_base; state->paris= 0; state->busy= 0; @@ -3627,6 +3990,9 @@ for (i= 0; argv[i] != NULL; i++) state->socket_icmp= -1; state->socket_tcp= -1; + if (response_in || response_out) + trt_base->my_pid= 42; + for (i= 0; itabsiz; i++) { if (trt_base->table[i] == NULL) @@ -3772,7 +4138,17 @@ static int create_socket(struct trtstate *state, int do_tcp) type= SOCK_RAW; protocol= (af == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP); - state->socket_icmp= xsocket(af, type, protocol); + if (state->response_in) + { + state->socket_icmp= open(state->response_in, O_RDONLY); + if (state->socket_icmp == -1) + { + crondlog(DIE9 "unable to open '%s'", + state->response_in); + } + } + else + state->socket_icmp= xsocket(af, type, protocol); if (state->socket_icmp == -1) { serrno= errno; @@ -3798,9 +4174,14 @@ static int create_socket(struct trtstate *state, int do_tcp) } } - r= connect(state->socket_icmp, - (struct sockaddr *)&state->sin6, - state->socklen); + if (state->response_in) + r= 0; /* Don't try to connect when reading from a file */ + else + { + r= connect(state->socket_icmp, + (struct sockaddr *)&state->sin6, + state->socklen); + } #if 0 { errno= ENOSYS; r= -1; } #endif @@ -3816,7 +4197,7 @@ static int create_socket(struct trtstate *state, int do_tcp) return -1; } state->loc_socklen= sizeof(state->loc_sin6); - if (getsockname(state->socket_icmp, + if (!state->response_in && getsockname(state->socket_icmp, &state->loc_sin6, &state->loc_socklen) == -1) { @@ -3829,9 +4210,12 @@ static int create_socket(struct trtstate *state, int do_tcp) buf, sizeof(buf))); #endif - close(state->socket_icmp); - state->socket_icmp= xsocket(af, type, - protocol); + if (!state->response_in) + { + close(state->socket_icmp); + state->socket_icmp= xsocket(af, type, + protocol); + } if (state->socket_icmp == -1) { serrno= errno; @@ -3877,8 +4261,10 @@ static int create_socket(struct trtstate *state, int do_tcp) if (do_tcp) { - state->socket_tcp= xsocket(af, SOCK_RAW, - IPPROTO_TCP); + if (state->response_in) + state->socket_tcp= open("/dev/null", O_RDWR); + else + state->socket_tcp= xsocket(af, SOCK_RAW, IPPROTO_TCP); if (state->socket_tcp == -1) { serrno= errno; @@ -3911,9 +4297,14 @@ static int create_socket(struct trtstate *state, int do_tcp) } } - r= connect(state->socket_tcp, - (struct sockaddr *)&state->sin6, - state->socklen); + if (state->response_in) + r= 0; /* No need to connect */ + else + { + r= connect(state->socket_tcp, + (struct sockaddr *)&state->sin6, + state->socklen); + } #if 0 { errno= ENOSYS; r= -1; } #endif @@ -4038,6 +4429,17 @@ static void traceroute_start(void *state) trtstate= state; + if (trtstate->response_out) + { + trtstate->resp_file_out= fopen(trtstate->response_out, "w"); + if (!trtstate->resp_file_out) + { + crondlog(DIE9 "unable to write to '%s'", + trtstate->response_out); + } + } + + if (!trtstate->delay_name_res) { traceroute_start2(state); -- cgit v1.2.3