static
void construct_ip4_header(
const struct net_state_t *net_state,
+ const struct probe_t *probe,
char *packet_buffer,
int packet_size,
- const struct sockaddr_storage *srcaddr,
- const struct sockaddr_storage *destaddr,
const struct probe_param_t *param)
{
struct IPHeader *ip;
- struct sockaddr_in *srcaddr4 = (struct sockaddr_in *) srcaddr;
- struct sockaddr_in *destaddr4 = (struct sockaddr_in *) destaddr;
ip = (struct IPHeader *) &packet_buffer[0];
ip->len = length_byte_swap(net_state, packet_size);
ip->ttl = param->ttl;
ip->protocol = param->protocol;
- memcpy(&ip->saddr, &srcaddr4->sin_addr, sizeof(uint32_t));
- memcpy(&ip->daddr, &destaddr4->sin_addr, sizeof(uint32_t));
+// ip->id = htons(getpid());
+ memcpy(&ip->saddr,
+ sockaddr_addr_offset(&probe->local_addr),
+ sockaddr_addr_size(&probe->local_addr));
+ memcpy(&ip->daddr,
+ sockaddr_addr_offset(&probe->remote_addr),
+ sockaddr_addr_size(&probe->remote_addr));
}
/* Construct an ICMP header for IPv4 */
static
void construct_icmp4_header(
const struct net_state_t *net_state,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
const struct probe_param_t *param)
icmp->type = ICMP_ECHO;
icmp->id = htons(getpid());
- icmp->sequence = htons(sequence);
+ icmp->sequence = htons(probe->sequence);
icmp->checksum = htons(compute_checksum(icmp, icmp_size));
}
static
int construct_icmp6_packet(
const struct net_state_t *net_state,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
const struct probe_param_t *param)
icmp->type = ICMP6_ECHO;
icmp->id = htons(getpid());
- icmp->sequence = htons(sequence);
+ icmp->sequence = htons(probe->sequence);
return 0;
}
static
void set_udp_ports(
struct UDPHeader *udp,
- int sequence,
+ struct probe_t *probe,
const struct probe_param_t *param)
{
if (param->dest_port) {
if (param->local_port) {
udp->srcport = htons(param->local_port);
- udp->checksum = htons(sequence);
+ udp->checksum = htons(probe->sequence);
} else {
- udp->srcport = htons(sequence);
+ udp->srcport = htons(probe->sequence);
udp->checksum = 0;
}
} else {
- udp->dstport = htons(sequence);
+ udp->dstport = htons(probe->sequence);
if (param->local_port) {
udp->srcport = htons(param->local_port);
udp->checksum = 0;
}
+ *(uint16_t *)sockaddr_port_offset(&probe->local_addr) = udp->srcport;
+ *(uint16_t *)sockaddr_port_offset(&probe->remote_addr) = udp->dstport;
}
/* Prepend pseudoheader to the udp datagram and calculate checksum */
static
void construct_udp4_header(
const struct net_state_t *net_state,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
- const struct sockaddr_in *src_addr,
- const struct sockaddr_in *dst_addr,
const struct probe_param_t *param)
{
struct UDPHeader *udp;
memset(udp, 0, sizeof(struct UDPHeader));
- set_udp_ports(udp, sequence, param);
+ set_udp_ports(udp, probe, param);
udp->length = htons(udp_size);
/* calculate udp checksum */
struct UDPPseudoHeader udph = {
- .saddr = src_addr->sin_addr.s_addr,
- .daddr = dst_addr->sin_addr.s_addr,
+ .saddr = *(uint32_t *)sockaddr_addr_offset(&probe->local_addr),
+ .daddr = *(uint32_t *)sockaddr_addr_offset(&probe->remote_addr),
.zero = 0,
.protocol = 17,
.len = udp->length
static
int construct_udp6_packet(
const struct net_state_t *net_state,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
const struct probe_param_t *param)
memset(udp, 0, sizeof(struct UDPHeader));
- set_udp_ports(udp, sequence, param);
+ set_udp_ports(udp, probe, param);
udp->length = htons(udp_size);
if (net_state->platform.ip6_socket_raw) {
int construct_ip4_packet(
const struct net_state_t *net_state,
int *packet_socket,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
- const struct sockaddr_storage *src_sockaddr,
- const struct sockaddr_storage *dest_sockaddr,
const struct probe_param_t *param)
{
int send_socket = net_state->platform.ip4_send_socket;
#endif
} else {
if (net_state->platform.ip4_socket_raw) {
- construct_ip4_header(net_state, packet_buffer, packet_size,
- src_sockaddr, dest_sockaddr, param);
+ construct_ip4_header(net_state, probe, packet_buffer, packet_size,
+ param);
}
if (param->protocol == IPPROTO_ICMP) {
- construct_icmp4_header(net_state, sequence, packet_buffer,
+ construct_icmp4_header(net_state, probe, packet_buffer,
packet_size, param);
} else if (param->protocol == IPPROTO_UDP) {
- construct_udp4_header(net_state, sequence, packet_buffer,
- packet_size,
- (struct sockaddr_in *)src_sockaddr,
- (struct sockaddr_in *)dest_sockaddr,
- param);
+ construct_udp4_header(net_state, probe, packet_buffer,
+ packet_size, param);
} else {
errno = EINVAL;
return -1;
if (is_stream_protocol) {
send_socket =
- open_stream_socket(net_state, param->protocol, sequence,
- src_sockaddr, dest_sockaddr, param);
+ open_stream_socket(net_state, param->protocol, probe->sequence,
+ &probe->local_addr, &probe->remote_addr, param);
if (send_socket == -1) {
return -1;
}
/* Bind to our local address */
- if (bind_send_socket && bind(socket, (struct sockaddr *)src_sockaddr,
+ if (bind_send_socket && bind(socket, (struct sockaddr *)&probe->local_addr,
sizeof(struct sockaddr_in))) {
return -1;
}
int construct_ip6_packet(
const struct net_state_t *net_state,
int *packet_socket,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_size,
- const struct sockaddr_storage *src_sockaddr,
- const struct sockaddr_storage *dest_sockaddr,
const struct probe_param_t *param)
{
int send_socket;
}
if (construct_icmp6_packet
- (net_state, sequence, packet_buffer, packet_size, param)) {
+ (net_state, probe, packet_buffer, packet_size, param)) {
return -1;
}
} else if (param->protocol == IPPROTO_UDP) {
}
if (construct_udp6_packet
- (net_state, sequence, packet_buffer, packet_size, param)) {
+ (net_state, probe, packet_buffer, packet_size, param)) {
return -1;
}
} else {
if (is_stream_protocol) {
send_socket =
- open_stream_socket(net_state, param->protocol, sequence,
- src_sockaddr, dest_sockaddr, param);
+ open_stream_socket(net_state, param->protocol, probe->sequence,
+ &probe->local_addr, &probe->remote_addr, param);
if (send_socket == -1) {
return -1;
if (net_state->platform.ip6_socket_raw) {
if (memcmp(¤t_sockaddr,
- src_sockaddr, sizeof(struct sockaddr_in6)) == 0) {
+ &probe->local_addr, sizeof(struct sockaddr_in6)) == 0) {
bind_send_socket = false;
}
} else {
/* Bind to our local address */
if (bind_send_socket) {
- if (bind(send_socket, (struct sockaddr *) src_sockaddr,
+ if (bind(send_socket, (struct sockaddr *) &probe->local_addr,
sizeof(struct sockaddr_in6))) {
return -1;
}
int construct_packet(
const struct net_state_t *net_state,
int *packet_socket,
- int sequence,
+ struct probe_t *probe,
char *packet_buffer,
int packet_buffer_size,
- const struct sockaddr_storage *dest_sockaddr,
- const struct sockaddr_storage *src_sockaddr,
const struct probe_param_t *param)
{
int packet_size;
memset(packet_buffer, param->bit_pattern, packet_size);
if (param->ip_version == 6) {
- if (construct_ip6_packet(net_state, packet_socket, sequence,
+ if (construct_ip6_packet(net_state, packet_socket, probe,
packet_buffer, packet_size,
- src_sockaddr, dest_sockaddr, param)) {
+ param)) {
return -1;
}
} else if (param->ip_version == 4) {
- if (construct_ip4_packet(net_state, packet_socket, sequence,
+ if (construct_ip4_packet(net_state, packet_socket, probe,
packet_buffer, packet_size,
- src_sockaddr, dest_sockaddr, param)) {
+ param)) {
return -1;
}
} else {
#include <string.h>
#include "protocols.h"
+#include "sockaddr.h"
#define MAX_MPLS_LABELS 8
struct net_state_t *net_state,
const struct sockaddr_storage *remote_addr,
int icmp_result,
+ int af,
+ const void *ip,
const struct UDPHeader *udp,
int udp_length,
struct timeval *timestamp,
if (probe == NULL) {
probe = find_probe(net_state, IPPROTO_UDP, 0, udp->checksum);
}
+ if (probe == NULL)
+ return;
- if (probe != NULL) {
- receive_probe(net_state, probe, icmp_result,
- remote_addr, timestamp, mpls_count, mpls);
+ if (probe->remote_addr.ss_family != remote_addr->ss_family)
+ return;
+
+ if (udp->dstport != *(uint16_t *)sockaddr_port_offset(&probe->remote_addr) )
+ return;
+
+ if (udp->srcport != *(uint16_t *)sockaddr_port_offset(&probe->local_addr) )
+ return;
+
+ void *saddr, *daddr;
+ if (af == AF_INET)
+ {
+ saddr = &((struct IPHeader *)ip)->saddr;
+ daddr = &((struct IPHeader *)ip)->daddr;
+ }else
+ if (af == AF_INET6)
+ {
+ daddr = &((struct IP6Header *)ip)->daddr;
+ saddr = &((struct IP6Header *)ip)->saddr;
+ }else
+ {
+ return;
}
+
+ if( memcmp(sockaddr_addr_offset(&probe->remote_addr),
+ daddr,
+ sockaddr_addr_size(&probe->remote_addr)) != 0 )
+ return;
+
+ if( memcmp(sockaddr_addr_offset(&probe->local_addr),
+ saddr,
+ sockaddr_addr_size(&probe->local_addr)) != 0)
+ return;
+
+ /* probe is not null */
+ receive_probe(net_state, probe, icmp_result,
+ remote_addr, timestamp, mpls_count, mpls);
}
void handle_error_queue_packet(
struct timeval *timestamp)
{
if (proto == IPPROTO_UDP) {
- handle_inner_udp_packet(net_state, remote_addr, ICMP_TIME_EXCEEDED,
+ handle_inner_udp_packet(net_state, remote_addr, ICMP_TIME_EXCEEDED, 0, NULL,
(struct UDPHeader *)packet, packet_length, timestamp, 0, NULL);
} else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
const struct ICMPHeader *icmp = (struct ICMPHeader *)packet;
udp = (struct UDPHeader *) (ip + 1);
udp_length = packet_length - sizeof(struct IPHeader);
- handle_inner_udp_packet(net_state, remote_addr, icmp_result, udp,
+ handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET, ip, udp,
udp_length, timestamp, mpls_count, mpls);
} else if (ip->protocol == IPPROTO_TCP) {
if (packet_length < ip_tcp_size) {
udp = (struct UDPHeader *) (ip + 1);
udp_length = packet_length - sizeof(struct IP6Header);
- handle_inner_udp_packet(net_state, remote_addr, icmp_result, udp,
+ handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET6, ip, udp,
udp_length, timestamp, mpls_count, mpls);
} else if (ip->protocol == IPPROTO_TCP) {
if (packet_length < ip_tcp_size) {
{
char packet[PACKET_BUFFER_SIZE];
struct probe_param_t param;
- struct sockaddr_storage dest_sockaddr;
- struct sockaddr_storage src_sockaddr;
+ struct probe_t p0 = {.sequence = MIN_PORT };
ssize_t bytes_sent;
int packet_size;
param.remote_address = "127.0.0.1";
param.is_probing_byte_order = true;
- if (resolve_probe_addresses(net_state, ¶m, &dest_sockaddr,
- &src_sockaddr)) {
+
+ if (resolve_probe_addresses(net_state, ¶m, &p0.remote_addr,
+ &p0.local_addr)) {
fprintf(stderr, "Error decoding localhost address\n");
exit(EXIT_FAILURE);
}
/* First attempt to ping the localhost with network byte order */
net_state->platform.ip_length_host_order = false;
- packet_size = construct_packet(net_state, NULL, MIN_PORT,
+ packet_size = construct_packet(net_state, NULL, &p0,
packet, PACKET_BUFFER_SIZE,
- &dest_sockaddr, &src_sockaddr, ¶m);
+ ¶m);
if (packet_size < 0) {
perror("Unable to send to localhost");
exit(EXIT_FAILURE);
bytes_sent =
send_packet(net_state, ¶m, MIN_PORT, packet, packet_size,
- &dest_sockaddr);
+ &p0.remote_addr);
if (bytes_sent > 0) {
return;
}
/* Since network byte order failed, try host byte order */
net_state->platform.ip_length_host_order = true;
- packet_size = construct_packet(net_state, NULL, MIN_PORT,
+ packet_size = construct_packet(net_state, NULL, &p0,
packet, PACKET_BUFFER_SIZE,
- &dest_sockaddr, &src_sockaddr, ¶m);
+ ¶m);
if (packet_size < 0) {
perror("Unable to send to localhost");
exit(EXIT_FAILURE);
bytes_sent =
send_packet(net_state, ¶m, MIN_PORT, packet, packet_size,
- &dest_sockaddr);
+ &p0.remote_addr);
if (bytes_sent < 0) {
perror("Unable to send with swapped length");
exit(EXIT_FAILURE);
{
char packet[PACKET_BUFFER_SIZE];
struct probe_t *probe;
- struct sockaddr_storage src_sockaddr;
int trytimes;
int packet_size;
}
if (resolve_probe_addresses(net_state, param, &probe->remote_addr,
- &src_sockaddr)) {
+ &probe->local_addr)) {
printf("%d invalid-argument\n", param->command_token);
free_probe(net_state, probe);
return;
for (trytimes=MIN_PORT; trytimes < MAX_PORT; trytimes++) {
packet_size = construct_packet(net_state, &probe->platform.socket,
- probe->sequence, packet, PACKET_BUFFER_SIZE,
- &probe->remote_addr, &src_sockaddr, param);
-
+ probe, packet, PACKET_BUFFER_SIZE,
+ param);
+
if (packet_size > 0) break; // no retry if we succeed.
if ((param->protocol != IPPROTO_TCP) &&