I've come across the code below that'll make and send a TCP packet. It's not just creating a socket, connecting to a port, and using buffers to read/write data, it actually allows creation of the IP header and TCP header. The codes works as I've checked it on WireShark, but it doesn't send any data within the packet. I want to add some data to the packet but I don't know how to.
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define PCKT_LEN 8192
struct ipheader {
unsigned char iph_ihl :5, /* Little-endian */
iph_ver :4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved :4, tcph_offset :4;
unsigned int tcp_res1 :4, /*little-endian*/
tcph_hlen :4, /*length of tcp header in 32-bit words*/
tcph_fin :1, /*Finish flag "fin"*/
tcph_syn :1, /*Synchronize sequence numbers to start a connection*/
tcph_rst :1, /*Reset flag */
tcph_psh :1, /*Push, sends data to the application*/
tcph_ack :1, /*acknowledge*/
tcph_urg :1, /*urgent pointer*/
tcph_res2 :2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
unsigned short csum(unsigned short *buf, int len) {
unsigned long sum;
for (sum = 0; len > 0; len--){
sum += *buf++;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short) (~sum);
}
int main(int argc, char *argv[]) {
int sd;
[B] // No data, just datagram
char buffer[PCKT_LEN];[/B]
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
if (argc != 5) {
printf("- Invalid parameters!!!\n");
printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}
sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sd < 0) {
perror("socket() error");
exit(-1);
} else {
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
}
// The source is redundant, may be used later if needed
// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// IP structure
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_ident = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6; // TCP
ip->iph_chksum = 0; // Done by kernel
// Source IP, modify as needed, spoofed, we accept through command line argument
ip->iph_sourceip = inet_addr(argv[1]);
// Destination IP, modify as needed, but here we accept through command line argument
ip->iph_destip = inet_addr(argv[3]);
// The TCP structure. The source port, spoofed, we accept through the command line
tcp->tcph_srcport = htons(atoi(argv[2]));
// The destination port, we accept through command line
tcp->tcph_destport = htons(atoi(argv[4]));
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0; // Done by kernel
tcp->tcph_urgptr = 0;
// IP checksum calculation
ip->iph_chksum = csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct tcpheader)));
// Inform the kernel do not fill up the headers' structure, we fabricated our own
if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
perror("setsockopt() error");
exit(-1);
} else {
printf("setsockopt() is OK\n");
}
printf("Using:::::Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
// sendto() loop, send every 2 second for 50 counts
unsigned int count;
for (count = 0; count < 20; count++) {
if (sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0){ // Verify
perror("sendto() error");
exit(-1);
} else {
printf("Count #%u - sendto() is OK\n", count);
}
sleep(2);
}
close(sd);
return 0;
}
I was able to use this C code to send a MULTICAST packet that had data within it. It takes a destination IP and a destination port as the arguments. Then it asks for the message. It works as I have verified via WireShark. I want to do this but with TCP, and then with UDP.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_LEN 1024
int main(int argc, char *argv[]) {
int sock;
char message_to_send[MAX_LEN];
unsigned int send_len;
char* multicast_ip;
unsigned short multicast_port;
unsigned char multicast_ttl = 1;
struct sockaddr_in multicast_addr;
if (argc != 3) {
fprintf(stderr, "Usage: %s Multicast_IP Multicast_Port\n", argv[0]);
exit(1);
}
multicast_ip = argv[1]; /* arg 1: multicast IP address */
multicast_port = atoi(argv[2]); /* arg 2: multicast port number */
/* create a socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("Socket creation failed");
exit(1);
}
/* set the TTL (time to live/hop count) for the send */
if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &multicast_ttl, sizeof(multicast_ttl))) < 0) {
perror("setsockopt() failed");
exit(1);
}
memset(&multicast_addr, 0, sizeof(multicast_addr));
multicast_addr.sin_family = AF_INET;
multicast_addr.sin_addr.s_addr = inet_addr(multicast_ip);
multicast_addr.sin_port = htons(multicast_port);
printf("Type the message below (Press Enter to send, ctrl-C to quit):\n");
memset(message_to_send, 0, sizeof(message_to_send));
while (fgets(message_to_send, MAX_LEN, stdin)) {
send_len = strlen(message_to_send);
if ((sendto(sock, message_to_send, send_len, 0, (struct sockaddr *) &multicast_addr, sizeof(multicast_addr))) != send_len) {
perror("Error in number of bytes");
exit(1);
}
memset(message_to_send, 0, sizeof(message_to_send));
}
close(sock);
exit(0);
}
How can I do this?