Я создаю небольшое приложение для протокола ICMP (ping), используя эхо-запрос и ответ. Время жизни (TTL) по умолчанию установлено на TTL получателя, и мне было интересно, могу ли я получить помощь в настройке собственного TTL в качестве аргумента при компиляции кода. Заранее благодарю за ценную помощь.
TO COMPILE:
g cc -o MyPing имя_файла. c
sudo ./myping www.google.com
Код начинается здесь:
Цитата
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#define BUFFER_SIZE 1024
#define ICMP_HEADER_LENGTH 8
#define DATA_LENGTH (64 - ICMP_HEADER_LENGTH)
int msg_count;
int msg_received_count;
int seq = 0;
pid_t pid;
int sock;
struct addrinfo *host;
int get_addrinfo_v4(const char *host, struct addrinfo **result) {
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_flags = AI_CANONNAME;
return getaddrinfo(host, NULL, &hints, result);
}
const char *get_sockaddr_text(
const struct sockaddr *address,
char *text, socklen_t text_length
) {
return inet_ntop(
address->sa_family,
&(((struct sockaddr_in *)address)->sin_addr),
text,
text_length
);
}
double timeval_to_ms(const struct timeval *time) {
return (time->tv_sec * 1000.0) + (time->tv_usec / 1000.0);
}
u_short checksum(u_short *data, int length) {
register int data_left = length;
register u_short *p = data;
register int sum = 0;
u_short answer = 0;
while (data_left > 1) {
sum += *p;
p++;
data_left -= 2;
}
if (data_left == 1) {
*(u_char *)(&answer) = *(u_char *)p;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
void alarm_handler(int signal_number) {
int icmp_packet_length = DATA_LENGTH + ICMP_HEADER_LENGTH;
char send_buffer[BUFFER_SIZE];
memset(send_buffer + ICMP_HEADER_LENGTH, 0, DATA_LENGTH);
struct icmp *icmp_packet = (struct icmp *)send_buffer;
icmp_packet->icmp_type = ICMP_ECHO;
icmp_packet->icmp_code = 0;
icmp_packet->icmp_id = pid;
icmp_packet->icmp_seq = seq++;
gettimeofday((struct timeval *)icmp_packet->icmp_data, NULL);
icmp_packet->icmp_cksum = 0;
icmp_packet->icmp_cksum = checksum((u_short *)icmp_packet, icmp_packet_length);
sendto(sock, send_buffer, icmp_packet_length, 0, host->ai_addr, host->ai_addrlen);
alarm(1);
msg_count++;
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("usage: %s host\n", argv[0]);
exit(EXIT_FAILURE);
}
pid = getpid() & 0xffff;
int status = get_addrinfo_v4(argv[1], &host);
if (status != 0) {
printf("error: %s\n", gai_strerror(status));
exit(EXIT_FAILURE);
}
sock = socket(host->ai_family, SOCK_RAW, IPPROTO_ICMP);
if (sock < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
setuid(getuid());
struct sigaction action;
action.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &action, NULL) < 0) {
perror("signal");
exit(EXIT_FAILURE);
}
char send_ip[INET_ADDRSTRLEN];
get_sockaddr_text(host->ai_addr, send_ip, sizeof(send_ip));
printf(
"PING %s (%s): %d data bytes\n",
host->ai_canonname,
send_ip,
DATA_LENGTH
);
alarm_handler(SIGALRM);
char receive_buffer[BUFFER_SIZE];
struct sockaddr receive_address;
char control_buffer[BUFFER_SIZE];
struct iovec iov;
iov.iov_base = receive_buffer;
iov.iov_len = sizeof(receive_buffer);
struct msghdr msg;
msg.msg_name = &receive_address;
msg.msg_namelen = sizeof(receive_address);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control_buffer;
msg.msg_controllen = sizeof(control_buffer);
struct timeval receive_time;
char receive_ip[INET_ADDRSTRLEN];
for ( ; ; ) {
ssize_t n = recvmsg(sock, &msg, 0);
if (n > 0) {
struct ip *ip_packet = (struct ip *)receive_buffer;
if (ip_packet->ip_p == IPPROTO_ICMP) {
int ip_header_length = ip_packet->ip_hl << 2;
int icmp_packet_length = n - ip_header_length;
if (icmp_packet_length >= 16) {
struct icmp *icmp_packet = (struct icmp *)(receive_buffer + ip_header_length);
if (
icmp_packet->icmp_type == ICMP_ECHOREPLY &&
icmp_packet->icmp_id == pid
) {
gettimeofday(&receive_time, NULL);
struct timeval *send_time = (struct timeval *)icmp_packet->icmp_data;
msg_received_count++;
printf(
"%d bytes from %s: icmp_seq=%u ttl=%d time=%.3f ms\n",
icmp_packet_length,
get_sockaddr_text(&receive_address, receive_ip, sizeof(receive_ip)),
icmp_packet->icmp_seq,
ip_packet->ip_ttl,
timeval_to_ms(&receive_time) - timeval_to_ms(send_time) );
}
printf("\n%d packets sent, %d packets received, %f percent packet loss. \n\n",
msg_count, msg_received_count, ((msg_count - msg_received_count)/msg_count) * 100.0);
}
}
}
}
return EXIT_SUCCESS;
}