Socket code works in main but fails in other function - c

The first code snippet is just of main all I am doing is calling the outOfMain function
int main(int argc , char* argv[]) {
outOfMain();
}
The second is outOfMain - The code I want to work
void outOfMain() {
printf("%s\n", "project 2 started");
int mpSockDescriptor = mp_socket(AF_INET, SOCK_MPTCP, 0);
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(5233);
serverAddress.sin_addr.s_addr = inet_addr("xxx.xxx.xx.xx");
struct sockaddr* sAddr = (struct sockaddr*)&serverAddress;
int mpConn = mp_connect( mpSockDescriptor, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr));
if(mpConn) {
printf("failure to connect\n");
}
printf("adsf\n");
struct sockaddr_in clientAddress;
clientAddress.sin_family = AF_INET;
clientAddress.sin_port = htons(5233);
clientAddress.sin_addr.s_addr = inet_addr("localhost");
struct mptcp_header mpHeader;
mpHeader.seq_num = 1;
mpHeader.dest_addr = serverAddress;
mpHeader.src_addr = clientAddress;
mpHeader.total_bytes = sizeof("MPREQ 1");
mpHeader.ack_num = 1;
struct packet packing;
packing.header = &mpHeader;
char* sendReq = (char*) malloc(128*sizeof(char));
strcpy(sendReq, "MPREQ 1");
packing.data = (char*) malloc(128*sizeof(char));
strcpy(packing.data, sendReq);
printf("%s\n", packing.data);
printf("%d\n", mpSockDescriptor);
printf("%zu\n",mp_send(mpSockDescriptor, &packing, sizeof(packing), 0));
struct packet packRecv;
printf("adf\n");
printf("%d\n", mpSockDescriptor);
mp_recv(mpSockDescriptor, &packRecv, sizeof(struct packet), 0);
}
Then the third is the header file just to show that I am including outOfMain so the act of calling it isn't giving me the error
#ifndef MPTCP_H
#define MPTCP_H
// C libraries
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// MPTCP macros
#define SOCK_MPTCP 2 // socket type for mptcp connections
#define RWIN 2048 // maximum receiver window
#define MSS 128 // sender maximum segment size
/******************************************************************************
* TCP data structures *
******************************************************************************/
/******************************************************************************
* packet header holds information about the current packet + connection *
******************************************************************************/
void outOfMain();
struct mptcp_header {
struct sockaddr_in dest_addr; // remote destination address
struct sockaddr_in src_addr; // local sender address
int seq_num; // sequence number ( first data byte )
int ack_num; // ACK number ( next expected data byte )
int total_bytes; // total bytes of data to transmit
};
/******************************************************************************
* packet holds information about the data contained + connection *
******************************************************************************/
struct packet {
struct mptcp_header * header; // pointer to packet header
char * data; // segment of data
};
struct sendStruct {
char** buff;
int portNumber;
struct sockaddr_in* cInfo;
};
/******************************************************************************
* TCP wrapper functions *
******************************************************************************/
/******************************************************************************
* receive UDP datagram(s) as TCP packet *
* - returns total bytes of data received *
******************************************************************************/
ssize_t mp_recv ( int sockfd, struct packet * recv_pkt, size_t data_len, int flags );
/******************************************************************************
* send UDP datagram(s) as TCP packet *
* - returns total bytes of data sent *
******************************************************************************/
ssize_t mp_send ( int sockfd, const struct packet * send_pkt, size_t data_len, int flags );
/******************************************************************************
* create connection with hostname, port *
* - returns 0 on success *
******************************************************************************/
int mp_connect( int sockfd, const struct sockaddr * addr, socklen_t addrlen );
/******************************************************************************
* create MPTCP socket *
* - returns socket descriptor for new connection *
******************************************************************************/
int mp_socket ( int domain, int type, int protocol );
/******************************************************************************
* prints packet header information + data load *
* - returns nothing, prints to standard out *
******************************************************************************/
void print_pkt( const struct packet * );
void failSuccess();
#endif // MPTCP_H
What I am doing in order is:
creating a multi-thread socket
Connecting that socket to a specific port and server address.
Sending a specific string to the server
Waiting for a response using mp_recv
What I don't understand is that when this exact same code is inside of main (), it works perfectly. But, when it is not in main(), it has a segfault 11 at the mp_recv function call. So I feel like the solution must have more to do with how C works and not my specific code.
Also, I need to have it outside of main() because I need to be able to use multi-threading.
I feel like I must be missing some elementary lesson in C right now.

You got lucky once, unlucky the other time. You have not initialized struct packet packRecv;.

Related

C Socket sendto Invalid argument error

My router.c file creates 2 sockets
the first is to bind to a port and answer clients
the second is to connect to an already bound port (by the server.c file)
and send messages to.
for some reason the sendto line return an Invalid argument error.
please help.
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
/* The Rounter represents through the server file(recv_udp.c).It transmitting from/to A(client) and C(another client)
by specific criteria (given in the assignment). */
int main(int argc, char *argv[])
{
/* Adding values that`ll be used for Q5*/
char serMsg [] = "Nice to hear from you,I am the server\n";
// char serMsg [] = "Good morning sun shine\n";
int serMsgLeng = strlen(serMsg)+1;
int error = -1;
char buff_A[200] = {'\0'};
char buff_C[200] = {'\0'};
// A value we get from the command prompt
float x;
float random, rand_num;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/* Values that`ll receive for the socket I`ll open (as socket descriptor(an int) etc.) */
int socket_fd1,socket_fd2, cc, addrLenA, s_in2Size;
/* Randome number Raffled between the range of[0,1] */
double randNum;
/* Defining Structures for decleration of the server s_in= as serverAddr(local ip,and local port),
from_A = the address that the datagram was received from client A,
from_C-the address that the datagram was received from client C . */
struct sockaddr_in s_in1, s_in2;
// Defining Structures for handling the clients address(client A and client C)
// Client A address structure
struct sockaddr_in client_A_addr;
//Client C address structure
struct sockaddr_in client_C_addr;
x = atof(argv[1]);
// Creating UDPsocket-(it`s a system call)-the socket()function opens a local socket and saves it`s number in socket_fd value. */
socket_fd1 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
socket_fd2 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/*set the socket options*/
setsockopt(socket_fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
setsockopt(socket_fd2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
// Binary cleaning /
bzero((char *) &s_in1, sizeof(s_in1)); /* They say you must do this */
bzero((char *) &s_in2, sizeof(s_in2));
/* Configure settings in address struct
"s_in.sin_family"-set the address family to be "AF_INET
"s_in.sin_addr.s_addr"- the htonl function converts host's to network's long
"s_in.sin_port" -the htons function converts regular form port to binary form.*/
s_in1.sin_family = (short)AF_INET;//host byte order
s_in1.sin_addr.s_addr = htonl(INADDR_ANY); // WILDCARD //
s_in1.sin_port = htons(1337);
s_in2.sin_family = (short)AF_INET;//host byte order
s_in2.sin_addr.s_addr = inet_addr("172.17.0.15"); // WILDCARD //
s_in2.sin_port = htons(1338);
// printsin( &s_in, "RECV_UDP", "Local socket is:");
fflush(stdout);
/* The bind function assigns a local protocol address to a socket(and another system call).
The purpose of sin here is to tell bind which local address to assign.
bind method input:the sock_fd and the stuctur that handels the address and it`s length*/
bind(socket_fd1, (struct sockaddr *)&s_in1, sizeof(s_in1));
printf("After binding,waiting to hear from clients!\n");
addrLenA = sizeof(client_A_addr);
s_in2Size = sizeof(s_in2);
connect(socket_fd2, (struct sockaddr *) &s_in2, s_in2Size);
printf("After connect to server!\n");
// Keep listenning
for(;;) {
// Check from who we recive the message - if from cilent A
// Check for errors
//recfrom() returns the length of the message that it receives,so if the client message length that the method returns is
//equal to the message length of client A - we raffel a number between[0,1].
if( (cc = recvfrom(socket_fd1,&buff_A,sizeof(buff_A),0,(struct sockaddr*)&client_A_addr,&addrLenA))== error){
printf("No message for now, waiting...\n");
}
// For self-check ,no error occured
if (strlen(buff_A) > 0) {
printf("Client A says: %s\n", buff_A);
// Than raffel a randNum and decide what to do with it(send or delete it)
srand(time(NULL));
random = rand();
rand_num = random / RAND_MAX;
printf("rand_num: %f\n", rand_num);
printf("x: %f\n", x);
// Greater than X send it
if(rand_num > x) {
printf("Sending message From A to C\n");
// Pass the message to C
if(sendto(socket_fd2, &buff_A, sizeof(buff_A),0,(struct sockaddr*)&client_C_addr,sizeof(client_C_addr))== error){
printf("sendto()- Client C failes to send message\n");
printf("%s\n", strerror(errno));
exit(1);
}
} else {
// Drop the message
}
// Clearing the message buffer
memset(buff_A, '\0', sizeof buff_A);
}
} //end for
return 0;
}
You never fill in client_C_addr. You must tell sendto where to send the data, like:
client_C_addr.sin_family = AF_INET;
client_C_addr.sin_port = htons(port);
client_C_addr.sin_addr.s_addr = inet_addr("192.168.1.1");

Socket programming C - bind error

I try to create a function to open a socket (i will have multiple socket in the future) called libf_build_udp_socket. But when it comes to bind i got the error cannot assign requested address and if i bypass this bind i got an error when sending a cmd.
If i don't use my function and integrate directly the code in my main, it works perfectly.
For the explanation i have a computer under linux that have to send cmd and received log from different equipment such as signal receiver...
Here is my full code, so maybe you will better understand my goals.
/* Standard Linux headers */
#include <stdio.h> //printf
#include <string.h> //memset
#include <stdlib.h> //exit(0);
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/times.h>
#include <unistd.h>
#include <errno.h>
/* DEFINE */
#define IP_RX "192.168.0.10" //notre IP=192.168.0.5
#define BUFFLEN 1024 //Max length of buffer
#define PORT_RX 3000 //The port on which to send data
unsigned short int libf_build_udp_socket(int * udp_socket, char * server_address, unsigned short int udp_port);
int main (void)
{
/*
** Definition of the local variables.
*/
//SOCKET
struct sockaddr_in addr_rx;
int serv_len_rx=sizeof(addr_rx);
int socket_fd_rx;
unsigned short int socketStatus; /* Socket return status */
//FD
fd_set readfds;
//BUFFER & CMD
char recepbuff[BUFFLEN];
char cmd[BUFFLEN], cmd_final[BUFFLEN];
//OTHER
int i, recv;
char choice;
int loop=1;
//TIMEOUT STRUCT
struct timeval tv;
tv.tv_sec=0; /*timeout de 0sec*/
tv.tv_usec=1000; //NE MARCHE PAS SI =0
/*
** Initialisation of the local variables.
*/
memset(recepbuff, '0' ,sizeof(recepbuff)); /*pareil que bzero*/
i=0;
/*
** Creating the socket
** call socket (it creates an endpoint for communication and
** returns the socket descriptor.
** To create an UDP socket here are the param
** The protocol family should be AF_INET
** The protocol type is SOCK_DGRAM
** The protocol should beset to default ie
** DEF_PROTOCOL wich is default so 0. );
*/
//OPENING AND SETTING SOCKET RX
socketStatus = libf_build_udp_socket(&socket_fd_rx, IP_RX, PORT_RX);
if (socketStatus>0)
{
printf("Could not create the socket, code error %d\n", socketStatus);
return 0;
}
/* Messaging*/
while(1)
{
printf ("\n//Boucle %d\n", i);
//clear the buffer by filling null, it might have previously received data
memset(recepbuff, '\0' ,sizeof(recepbuff));
loop=1;
//preparing cmd
printf("Enter command :");
fgets(cmd, sizeof(cmd) , stdin);
snprintf(cmd_final, sizeof (cmd_final), cmd, "\r\n"); /*adding 0d 0a to the cmd*/
//send cmd
if ( (sendto(socket_fd_rx , cmd_final, BUFFLEN , 0 , (struct sockaddr *)&addr_rx, serv_len_rx) ) < 0 )
{
perror("ERROR > send cmd failed to wass : ");
return 0;
}
else
{
printf( "cmd send to %s:%d\n" ,inet_ntoa(addr_rx.sin_addr), ntohs(addr_rx.sin_port) );
}
//printf("\n... waiting answer from %s:%d ... \n" ,inet_ntoa(addr_rx.sin_addr), ntohs(addr_rx.sin_port) );
//strcpy(recepbuff, "whileloop");
//try to receive some data, this is a blocking call
while(loop)
{
memset(recepbuff, '\0' ,sizeof(recepbuff)); //empty buffer
FD_ZERO(&readfds);
FD_SET(socket_fd_rx, &readfds); //set testing for rx
select(socket_fd_rx+1, &readfds, NULL, NULL, &tv); //block until cmd becomes available
if(FD_ISSET(socket_fd_rx, &readfds)) //input rx available
{
//printf("Data to be read \n");
recvfrom( socket_fd_rx, recepbuff , BUFFLEN, 0, (struct sockaddr *)&addr_rx, &serv_len_rx); //recep
printf("[=> RĂ©ponse : %s\n", recepbuff);
}
else
{
loop=0;
}
}
printf(".... RĂ©ponse done from %s:%d .... \n",inet_ntoa(addr_rx.sin_addr),ntohs(addr_rx.sin_port) );
i++;
}
close(socket_fd_rx);
return 0;
}
//FONCTIONS
//OPENING 1 SETTING A SOCKET
/** libf_build_udp_socket
*
* This function creates an UDP socket.
*
* \param udp_socket socket identifier
* \param server_address IP destination address
* \param udp_port Destination UDP port
* \param server_flag TRUE to bind socket on UDP port
*
* \return 0 if successful; error code otherwise
*/
unsigned short int libf_build_udp_socket(int * udp_socket, char * server_address, unsigned short int udp_port)
{
/*
** Defining of the local variables.
*/
struct sockaddr_in serv_addr; /* Server Socket address structure*/
short int status = 0; /* internal status return*/
unsigned short int return_status = 0; /* the returnes status value */
/*
** creating the socket ;
** call socket (it creates an endpoint for communication and
** returns the socket
** descriptor. To create an UDP socket
** the parameter family is set
** to AF_INET, the type to SOCK_DGRAM, and
** the protocol to
** DEF_PROTOCOL. The socket is a global variable.);
*/
*udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (*udp_socket < 0)
{
return_status = 1;
}
else
{
status = 1; //for future check
if (status >= 0)
{
/*
** reset the serv_addr variable
*/
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
/*
** set the sockname.sin_addr.s_addr to server address;
** sockname.sin_addr.s_addr = htonl(server address);
** set the sockname field sockname.sin_port to the used port number;
** sockname.sin_port = htons (udp port);
*/
serv_addr.sin_addr.s_addr = inet_addr(server_address);
serv_addr.sin_port = htons(udp_port);
/*
** Bind this socket to a name;
** call bind (it assigns a name or address to an unnamed socket.
** When a socket is created with socket it exists in
** a name space (address family) but has no name assigned.
** The bind requests the name, be assigned to the socket);
** If (return status signal an error)
** {
** set to return variable to error
** }
*/
status = bind(*udp_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (status < 0)
{
printf("bind failed with %s", strerror(errno));
return_status = 2;
}
}
else
{
return_status = 3;
}
}
/*
** return status;
*/
return return_status;
}
Maybe i'm missing something essential in socket programming, i made a lot of research and try different things but it still doesn't want to work ! I would appreciate some help ! Thank you !

ICMP Reply will not send

I am working on a sniffing and spoofing project using C and the pcap library. I have to admit, I am still learning this library and it is taking me forever. That being said, I am having some issues with my program. I cannot get it to properly send my ICMP reply. The idea of the program is that it sniffs for any ICMP requests on its network and sends a reply. Currently, the program executes but I cannot seem to get the reply to actually send correctly. I am fairly certain that the error is in the "SpoofReply()" function or the "Send_Raw_Packet()". Here is code:
*EDIT FOR CLARITY: The program should send an ICMP Reply to any ICMP request. Test using a ping command to any non functional IP desitination (1.1.1.1). Without program, there should be no response. If program is running on same network as ping request, (I just run from the same machine) then it should create an ICMP reply from "1.1.1.1". Spoofing. However, my reply never actually sends when I run the program. It detects the request and attemps to create a response, but the logic is wrong somewhere.
#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <unistd.h>
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
#define PACKET_LEN 1500
#define BUFSIZE 1500
/* Ethernet header */
struct ethheader {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP Header */
struct ipheader {
unsigned char iph_ihl:4, iph_ver:4; //IP Header length & Version.
unsigned char iph_tos; //Type of service
unsigned short int iph_len; //IP Packet length (Both data and header)
unsigned short int iph_ident; //Identification
unsigned short int iph_flag:3, iph_offset:13; //Flags and Fragmentation offset
unsigned char iph_ttl; //Time to Live
unsigned char iph_protocol; //Type of the upper-level protocol
unsigned short int iph_chksum; //IP datagram checksum
struct in_addr iph_sourceip; //IP Source address (In network byte order)
struct in_addr iph_destip;//IP Destination address (In network byte order)
};
/* ICMP Header */
struct icmpheader {
unsigned char icmp_type; //ICMP message type
unsigned char icmp_code; //Error code
unsigned short int icmp_chksum; //Checksum for ICMP Header and data
unsigned short int icmp_id; //Used in echo request/reply to identify request
unsigned short int icmp_seq;//Identifies the sequence of echo messages,
//if more than one is sent.
};
/* TCP Header */
struct tcpheader {
u_short tcp_sport; /* source port */
u_short tcp_dport; /* destination port */
u_int tcp_seq; /* sequence number */
u_int tcp_ack; /* acknowledgement number */
u_char tcp_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->tcp_offx2 & 0xf0) >> 4)
u_char tcp_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short tcp_win; /* window */
u_short tcp_sum; /* checksum */
u_short tcp_urp; /* urgent pointer */
};
/* UDP Header */
struct udpheader
{
u_int16_t udp_sport; /* source port */
u_int16_t udp_dport; /* destination port */
u_int16_t udp_ulen; /* udp length */
u_int16_t udp_sum; /* udp checksum */
};
struct pseudo_tcp
{
unsigned saddr, daddr;
unsigned char mbz;
unsigned char ptcl;
unsigned short tcpl;
struct tcpheader tcp;
char payload[PACKET_LEN];
};
// DNS layer header's structure
struct dnsheader {
unsigned short int query_id;
unsigned short int flags;
unsigned short int QDCOUNT;
unsigned short int ANCOUNT;
unsigned short int NSCOUNT;
unsigned short int ARCOUNT;
};
unsigned short in_cksum(unsigned short *buf,int length)
{
unsigned short *w = buf;
int nleft = length;
int sum = 0;
unsigned short temp=0;
/*
* The algorithm uses a 32 bit accumulator (sum), adds
* sequential 16 bit words to it, and at the end, folds back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* treat the odd byte at the end, if any */
if (nleft == 1) {
*(u_char *)(&temp) = *(u_char *)w ;
sum += temp;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); // add hi 16 to low 16
sum += (sum >> 16); // add carry
return (unsigned short)(~sum);
}
/****************************************************************************
TCP checksum is calculated on the pseudo header, which includes the
the TCP header and data, plus some part of the IP header. Therefore,
we need to construct the pseudo header first.
*****************************************************************************/
unsigned short calculate_tcp_checksum(struct ipheader *ip)
{
struct tcpheader *tcp = (struct tcpheader *)((u_char *)ip +
sizeof(struct ipheader));
int tcp_len = ntohs(ip->iph_len) - sizeof(struct ipheader);
/* pseudo tcp header for the checksum computation */
struct pseudo_tcp p_tcp;
memset(&p_tcp, 0x0, sizeof(struct pseudo_tcp));
p_tcp.saddr = ip->iph_sourceip.s_addr;
p_tcp.daddr = ip->iph_destip.s_addr;
p_tcp.mbz = 0;
p_tcp.ptcl = IPPROTO_TCP;
p_tcp.tcpl = htons(tcp_len);
memcpy(&p_tcp.tcp, tcp, tcp_len);
return (unsigned short)in_cksum((unsigned short *)&p_tcp, tcp_len + 12);
}
/****************************************************************************
Function to actually send the spoofed IP reply.
*****************************************************************************/
void send_raw_packet (struct ipheader* ip)
{
int n = 0;
struct sockaddr_in dest_info;
int enable = 1;
//create a raw network socket and set its options.
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable));
//provide needed information about destination
dest_info.sin_family = AF_INET;
dest_info.sin_addr = ip->iph_destip;
//dest_info.sin_addr.s_addr = ip->iph_sourceip.s_addr;
//send out the packet
printf("Attmpting to send a spoofed ICMP packet! \n");
printf("......................................\n");
/*print the source and destination IP Addresses*/
printf(" From: %s\n", inet_ntoa(ip->iph_sourceip));
printf(" To: %s\n", inet_ntoa(ip->iph_destip));
printf("......................................\n");
while (n<2){
sendto(sock, ip, ntohs(ip->iph_len), 0, (struct sockaddr *)&dest_info, sizeof(dest_info));
printf("Oooooo....a spoofed ICMP packet has successfully been sent! \n");
n++;
}
close(sock);
}
/****************************************************************************
Function designed to spoof the ICMP reply
*****************************************************************************/
void spoofReply(struct ipheader* ip)
{
int ip_header_len = ip->iph_ihl * 4;
const char buffer[BUFSIZE];
struct icmpheader* icmp = (struct icmpheader *) ((u_char *)ip + ip_header_len);
if (icmp->icmp_type != 8) //this is not a reply, this is a request
{
printf("Packet received was not an ICMP request. Nothing sent.\n");
return;
}
//copy the original packet to a buffer
memset((char*)buffer, 0, BUFSIZE);
memset((char*)buffer, (int) ip, ntohs(ip->iph_len));
struct ipheader * newip = (struct ipheader *) buffer; //check this line for an error!!!
struct icmpheader * newicmp = (struct icmpheader *) ((u_char *)buffer + ip_header_len);
//new IP construction
newip->iph_sourceip.s_addr = ip->iph_destip.s_addr;
newip->iph_destip.s_addr = ip->iph_sourceip.s_addr;
newip->iph_ttl = 20;
newip->iph_protocol = IPPROTO_ICMP;
//fill ICMP info
newicmp->icmp_type = 0;
//checksum
newicmp->icmp_chksum = 0;
newicmp->icmp_chksum = in_cksum((unsigned short *)newicmp, ntohs(ip->iph_len) - ip_header_len);
printf("Packet is for sure an ICMP Request. Lets send a raw packet!\n");
send_raw_packet(newip);
}
/****************************************************************************
Packet Handler- This function handles incoming packets and checks for ICMP
protocol. Calls spoofReply() if the packet is an ICMP Request.
spoofed ICMP reply if the incoming packet is an ICMP request.
*****************************************************************************/
void gotPacket (u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
struct ethheader *eth = (struct ethheader *) packet;
if (eth->ether_type != ntohs(0x0800)) return; //this is not an IP packet
struct ipheader* ip = (struct ipheader*)(packet + SIZE_ETHERNET);
int ip_header_len = ip->iph_ihl * 4;
printf("......................................\n");
/*print the source and destination IP Addresses*/
printf(" From: %s\n", inet_ntoa(ip->iph_sourceip));
printf(" To: %s\n", inet_ntoa(ip->iph_destip));
if (ip->iph_protocol == IPPROTO_ICMP)
{
printf("Whoa! An ICMP packet has been found! Lets check it out.\n");
spoofReply(ip);
}
}
int main()
{
pcap_t *handle;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
char filter_exp[] = "";
bpf_u_int32 net;
//Print name of program and its filter:
printf("Sniff...Sniff...Sniff...\n");
printf("Cole Sniffer Started. Filtering %s \n", filter_exp);
//open the live session using the pcap_open function
handle = pcap_open_live("eth13", BUFSIZ, 1, 1000, errbuf);
//set the filter for whichever type of traffic you would like to receive
pcap_compile(handle, &fp, filter_exp, 0, net);
//set filter (continued)
pcap_setfilter(handle, &fp);
pcap_loop(handle, 100, gotPacket, NULL); // captures the packets
pcap_close(handle);
return 0;
};

How to use pthreads for sending and receiving in a udpclient in C

I'm trying to modify a client program that my professor supplied so that it will use pthreads for the functions sendto() and recvFrom(). I was able to timetag it and have the client receive as well as send messages and have my udpserver.c echo back messages. But I can't get my pthreads to work. I'm kinda new to pthreads. This is the error I got:
/tmp/cciYoHsc.o:udpclient.c:(.text+0x253): undefined reference to `_sendMessage'
/tmp/cciYoHsc.o:udpclient.c:(.text+0x2f2): undefined reference to `_recvMessage'
collect2: ld returned 1 exit status
I think it might have something to do with all the ifdef/endif keywords. I'm not really sure what all they do. This is my program udpclient.c
/*UPDATED*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
/* Here are some details of the sockaddr_in structure and the sockaddr structure
These declarations are copied from winsock.h
struct in_addr { this struct holds a 32 bit IP address
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
struct sockaddr_in { notice this structure is 16 bytes long
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr { this generic address structure is 16 bytes long, too!
u_short sa_family;
char sa_data[14];
};
*/
/* we have to send on the same port the server is listening on */
#define PORT 20009
/* simple upd client */
//prototypes
void *sendMessage( void *ptr );
void *recvMessage( void *ptr );
typedef struct info {
int size;
char buffer[100];
int nbytes,flags,addrlen;
} info;
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
int main()
{
#ifdef WIN
SOCKET sock;
#else
static int sock;
#endif
static int size;
static int nbytes, flags;
static int i;
static char * cp;
#ifdef WIN
WSADATA wsaData;
int nCode;
#endif
static char buffer[100];
static char str_addr[20]; /* holds the chars of an IP address */
static struct sockaddr_in target_pc, me;
/* magic call to initialize the network I/O code - only Microsoft requires this */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0)
{
printf("Opps! WSA error %d\n",nCode);
return -1;
}
#endif
/* create a socket to send on */
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
/* we fill in the address family and port, but we do not know the destination IP address yet */
target_pc.sin_family = PF_INET;
target_pc.sin_port = htons(PORT);
/* fill in my address and port */
me.sin_family = PF_INET;
me.sin_port = htons(0);
me.sin_addr.s_addr = htonl(INADDR_ANY);
i = bind(sock, (struct sockaddr *) &me, sizeof(me));
if( i < 0)
{
printf("bind result: %d\n", i);
return -1;
}
nbytes = 99;
//create threads
pthread_t sendT;
pthread_t recvT;
while(1)
{
struct timeval te;
struct timeval te2;
info *sendInfo;
info *recvInfo;
printf("Enter the target IP address: ");
cp = fgets(str_addr,19,stdin);
/* remove the \n */
str_addr[strlen(str_addr)-1] = '\0';
/* the inet_addr function converts a string form of IP address to a 32 binary integer */
target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]);
printf("Enter your message: ");
cp = fgets(buffer,99,stdin);
/* get the string length so we send exactly this many characters */
nbytes = strlen(buffer);
flags = 0;
int addrlen = sizeof(target_pc);
sendInfo->size = size;
sendInfo->buffer = buffer;
sendInfo->nbytes = nbytes;
sendInfo->flags = flags;
sendInfo->addrlen = addrlen;
pthread_create( &sendT, NULL, sendMessage, (void*) addrlen);
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
//time
gettimeofday(&te, NULL);
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
printf("[Time Sent: %lld]", milliseconds);
printf("[msg size = %d size = %d]\n", nbytes, size);
//added
pthread_create( &sendT, NULL, recvMessage, (void*) addrlen);
//size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
printf("Echo message: ");
if((size > 0) && (size < 99))
{
buffer[size] = '\0'; //add the null byte so buffer now holds a string
i = puts((char *) buffer); // write this string to the display
}
//time
gettimeofday(&te2, NULL); // get current time
milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // caculate milliseconds
printf("[Time Received: %lld]\n", milliseconds);
pthread_join(sendT,NULL);
pthread_join(recvT,NULL);
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
void *sendMessage( void *ptr ){
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
}
void *recvMessage( void *ptr ){
//size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,(int*)ptr);
}
Here is udpserver.c for reference:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
#define PORT 20009
/* simple upd server
this program receives short messages (<99 characters) from any IP address
and writes them to the display
be sure to use the linker line option "-l wsock32"
*/
int main()
{
/* first define a socket
a socket is an I/O port like a file descriptor
*/
#ifdef WIN
SOCKET sock; /* SOCKET is a typedef for a structure */
#else
int sock;
#endif
int size;
int nbytes, flags;
#ifdef WIN
int addrlen;
#else
socklen_t addrlen;
#endif
int i;
/* char loopback[20]="127.0.0.1"; */
#ifdef WIN
WSADATA wsaData; /* This is struct holds Windows required data */
int nCode;
#endif
char buffer[100];
struct sockaddr_in server; /* this holds my IP address and port info */
struct sockaddr_in from; /* this holds the same info for the sender of the packet
I received */
/* the call to WSAStartup is Windows magic */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0){
printf("Opps! WSA error %d\n",nCode);
exit;
}
#endif
/* create a socket called sock. It is a datagram socket */
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0){
printf("socket error = %d\n", sock);
return -1;
}
server.sin_family = AF_INET; /* initialize the server address family */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* notice this struct within a struct */
/* printf("%x\n",server.sin_addr.s_addr); */
server.sin_port = htons(PORT);
/* associate the socket with the address structure - this is called binding */
i = bind(sock, (struct sockaddr *) &server, sizeof(server));
if( i < 0) {
printf("bind result: %d\n", i);
return -1;
} else
printf("Simple UDP server is ready!\n\n");
nbytes = 99; /* receive packets up to 99 bytes long */
flags = 0; /* must be zero or this will not work! */
while(1){
/* the recvfrom function is a read and the arguments are:
sock - the socket we are reading
buffer - array into which to read the data
nbytes - read up to this many bytes
flags - used for special purposes - not needed here
from - sockaddr struct to hold the IP address and port of the sender of the packet
addrlen - the size of the sockaddr struct written by this function
*/
addrlen = sizeof(from);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);
if((size > 0) && (size < 99)){
buffer[size] = '\0'; /* add the null byte so buffer now holds a string */
i = puts((char *) buffer); /* write this string to the display */
}
//echo message back to client
if(sock < 0) {//
printf("socket error = %d\n", sock);//
return -1;//
}//
sendto(sock, buffer, nbytes, flags, (struct sockaddr *)&from,addrlen); //
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
Ithink i found the problem. Im not sure, im typing and reading on a iPad.
In the end of your main function, you have placed the declaration of
void *sendMessage( void *ptr )
void *recvMessage( void *ptr )
inside of the main. Move them outside.
/tmp/cciYoHsc.o:udpclient.c:(.text+0x253): undefined reference to `_sendMessage'
/tmp/cciYoHsc.o:udpclient.c:(.text+0x2f2): undefined reference to `_recvMessage'
collect2: ld returned 1 exit status
I believe that this will solve the problem.
As i said, im not able to test the code myself.
Good luck
void *sendMessage( void *ptr ){
size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
}
void *recvMessage( void *ptr ){
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,(int*)ptr);
}
you define size in main then try and use it in your threaded functions, you cant do that...

Why is my packet reading program returning incorrect data?

I have written a packet reader that uses libpcap to read a capture file. It reads the capture file and uploads captured data to a MySQL database. Sometimes it seems to work fine and others it returns invalid data (e.g. the source and destination ip will be the same, the tcp ports are all junk). I'm running this under a virtual RHEL 5. Here is my code (sorry if it's rather long or unnecessarily convoluted, this is my first attempt at this).
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include "npc_tcp.h"
#include "npc_udp.h"
#include <ftw.h>
#include <pcap.h>
#include <stdio.h>
#include <sys/stat.h>
#include <regex.h>
#include <string.h>
#include <time.h>
const int IPTYPE_TCP = 6;
const int IPTYPE_UDP = 17;
struct cap_data {
char ts[64];
u_int16_t ether_type;
u_int16_t proto;
char *srcip;
char *dstip;
char *srcmac;
u_int16_t srcport;
u_int16_t dstport;
u_int8_t flags;
u_int capsize;
};
int main(int argc, char **argv) {
//pcap
struct cap_data data;
struct pcap_pkthdr pkthdr;
const u_char *packet;
pcap_t *handle;
char *fname = argv[1];
printf("%s\n", fname);
char errbuf[PCAP_ERRBUF_SIZE];
handle = pcap_open_offline(fname, errbuf);
char buf[1000];
while (packet = pcap_next(handle, &pkthdr)) {
int ether_flag;
struct ether_header *ether;
u_short ether_type;
ether = (struct ether_header *) packet;
data.ether_type = ntohs(ether->ether_type);
ether_flag = 1;
if (ether_flag) {
if (data.ether_type == ETHERTYPE_IP) {
struct ip *ip_hdr;
u_int length = pkthdr.len;
ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));
data.proto = ip_hdr->ip_p;
data.dstip = inet_ntoa(ip_hdr->ip_dst);
data.srcip = inet_ntoa(ip_hdr->ip_src);
if (data.proto == IPTYPE_TCP) {
struct tcphdr *tcp;
tcp = (struct tcphdr*)(packet + sizeof(struct ether_header) +
sizeof(struct ip));
data.srcport = tcp->th_sport;
data.dstport = tcp->th_dport;
printf("%s %u %s %u\n\n", inet_ntoa(ip_hdr->ip_src), tcp->th_sport, inet_ntoa(ip_hdr->ip_dst), tcp->th_dport);
} else if (data.proto == IPTYPE_UDP) {
struct udphdr *udp;
udp = (struct udphdr *)(packet + sizeof(struct ether_header) +
sizeof(struct ip));
data.srcport = udp->uh_sport;
data.dstport = udp->uh_dport;
printf("%s %u %s %u\n\n", inet_ntoa(ip_hdr->ip_src), udp->uh_sport, inet_ntoa(ip_hdr->ip_dst), udp->uh_dport);
}
}
}
}//while
pcap_close(handle);
return 0;
}
UPDATE:
This outputs..
source ip port dest ip port
66.68.236.207 30151 66.68.236.207 47873
172.22.162.235 60920 172.22.162.235 36175
67.207.28.150 23007 67.207.28.150 22038
172.22.162.235 60920 172.22.162.235 36175
67.207.28.151 22038 67.207.28.151 23007
65.55.87.43 20480 65.55.87.43 21764
67.207.28.150 23007 67.207.28.150 22038
The addresses should not be the same and the port numbers are wrong as well.
I have no idea where to even start looking for errors as my code (at least to me) looks correct. Any help, tips, or advice would be greatly appreciated. Thanks :)
Two problems:
inet_ntoa returns a pointer to a static buffer.
When calling it twice within the same printf, it overwrites the same buffer. So you end up printing the same data.
Use inet_ntop instead, and give each call a separate buffer.
You should use ntohs() to convert the ports to host-order before printing.
What happens if, right after calling pcap_open_offline(), you do
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "This program handles only Ethernet captures\n");
return 2;
}

Resources