Ich muss c Programm schreiben, die ICMP ECHO REQUEST von Telefon senden (es ist durch Mobile ISP verbunden und es ist hinter NAT) zu Server mit IP PUBLIC. Ich schrieb ein einfaches Programm, das Echo-Anfrage sendet und Echo-Antwort empfängt, aber jetzt möchte ich ECHO REQUEST von Client zu Server senden und ECHO REPLY mit einigen Daten (eine IP PUBLIC und ICMP ID) von Server zu Client erhalten. Wie kann ich das machen?bekommen ECHO REPLY mit Daten vom Server zum Client hinter nat
Herres meinen Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
typedef unsigned char u8;
typedef unsigned short int u16;
struct icmp_header{
unsigned char type;
unsigned char code;
unsigned short checksum;
unsigned short id;
unsigned short seq;
};
unsigned short in_cksum(unsigned short *ptr, int nbytes);
int main(int argc, char **argv){
int c=100;
int ls;//lunghezza struct sockaddr_in serveraddr
int rf;//receive from
unsigned long daddr;
unsigned long saddr;
int payload_size = 0, sent = 0, sent_size;
saddr = inet_addr("IP PRIVATE");
daddr = inet_addr("IP PUBLIC");
//Raw socket - if you use IPPROTO_ICMP, then kernel will fill in the correct ICMP header checksum, if IPPROTO_RAW, then it wont
int sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0){
perror("could not create socket");
return (0);
}
int on = 1;
// We shall provide IP headers
if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, (const char*)&on, sizeof (on)) == -1){
perror("setsockopt");
return (0);
}
//allow socket to send datagrams to broadcast addresses
if (setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof (on)) == -1){
perror("setsockopt");
return (0);
}
//Calculate total packet size
int packet_size = sizeof (struct iphdr) + sizeof (struct icmp_header) + payload_size;
char *buffer = (char *) malloc (packet_size);
char *packet = (char *) malloc (packet_size);
if (!packet){
perror("out of memory");
close(sockfd);
return (0);
}
//ip header
struct iphdr *ip = (struct iphdr *) packet;
//struct icmphdr *icmp = (struct icmphdr *) (packet + sizeof (struct iphdr));
struct icmp_header *icmphdr = (struct icmp_header *) (packet + sizeof(struct iphdr));
//zero out the packet buffer
memset (packet, 0, packet_size);
memset (buffer, 0, packet_size);
ip->version = 4;
ip->ihl = 5;
ip->tos = 0;
ip->tot_len = htons (packet_size);
ip->id = rand();
ip->frag_off = 0;
ip->ttl = 255;
ip->protocol = IPPROTO_ICMP;
ip->saddr = saddr;
ip->daddr = daddr;
//ip->check = in_cksum ((u16 *) ip, sizeof (struct iphdr));
//icmp->type = ICMP_ECHO significa ECHO REQUEST
//icmp->code = 0 è il codice dei ECHO REQUEST
icmphdr->type = ICMP_ECHO;
icmphdr->code = 0;
icmphdr->id = 5;
icmphdr->seq = 66;
//checksum
icmphdr->checksum = 0;
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = daddr;
memset(&servaddr.sin_zero, 0, sizeof (servaddr.sin_zero));
puts("flooding...");
//while (1)
while(c>0){
memset(packet + sizeof(struct iphdr) + sizeof(struct icmp_header), rand() % 255, payload_size);
//memset(buffer + sizeof(struct iphdr) + sizeof(struct icmphdr), rand() % 255, payload_size);
//recalculate the icmp header checksum since we are filling the payload with random characters everytime
icmphdr->checksum = 0;
icmphdr->checksum = in_cksum((unsigned short *)icmphdr, sizeof(struct icmp_header) + payload_size);
if ((sent_size = sendto(sockfd, packet, packet_size, 0, (struct sockaddr*) &servaddr, sizeof (servaddr))) < 1){
perror("send failed\n");
break;
}
++sent;
printf("%d packets sent\r", sent);
fflush(stdout);
ls = sizeof(servaddr);
//rf = recvfrom(sockfd, buffer, 42, 0, (struct sockaddr *)&servaddr, &ls);
rf = recvfrom(sockfd, buffer, packet_size, 0, (struct sockaddr *)&servaddr, &ls);
if(rf < 0){
perror("Errore recvfrom\n");
break;
}
else{
char *cp;
struct iphdr *ip_reply = (struct iphdr *)buffer;
cp = (char *)&ip_reply->saddr;
printf("Received %d byte reply from %u.%u.%u.%u:\n", ntohs(ip_reply->tot_len), cp[0]&0xff,cp[1]&0xff,cp[2]&0xff,cp[3]&0xff);
printf("ID: %d\n", ntohs(ip_reply->id));
printf("TTL: %d\n", ip_reply->ttl);
}
usleep(10000); //microseconds
c--;
}
free (buffer);
free(packet);
close(sockfd);
return (0);
}
/*
Function calculate checksum
*/
unsigned short in_cksum(unsigned short *ptr, int nbytes){
register long sum;
u_short oddbyte;
register u_short answer;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char *) & oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
Ich bin mir nicht sicher, ob ich Ihre Frage verstehe? Erzeugt der Code, den Sie freigegeben haben, einen Fehler? – user590028
mein Code ist gut, kein Fehler. In diesem Code sende ich ECHO REQUEST an Server und bekomme ECHO REPLY zurück, kein Problem. Ich möchte wissen, wie kann ich ECHO REQUEST an Server senden und ECHO REPLY (vom Server) mit Daten wie eine IP PUBLIC ADRESSE und zwei Nummer – EmanueleRiso
zurück Sie sollten Ping-Antwort mit 'sysctl' zuerst auf dem Server deaktivieren. Dann ist es eine leichte Aufgabe. Formatieren Sie Ihren Code und geben Sie den Code der Serverseite ein. – jfly