int main()
{
int servsocket,clientsocket;
struct sockaddr_in server,client;
FILE *file;
char filename[100];
char buf[1024];
servsocket=socket(AF_INET,SOCK_DGRAM,0);
server.sin_addr.s_addr=htonl(INADDR_ANY);
server.sin_port=htons(6003);
server.sin_family=AF_INET;
bind(servsocket,(struct sockaddr *) &server,sizeof(server) );
while(1){
int clientsize=0;
printf("Waiting for file requests \n");
recvfrom(servsocket,filename,sizeof(filename),0,(struct sockaddr *)&client,&clientsize);
file=fopen(filename,"r");
int size=0;
do
{
size=fread(buf,1,sizeof(buf),file);
printf("%d bytes read \n",size);
int sentbytes= sendto(servsocket,(const char *)buf,size,0, (struct sockaddr *) &client,sizeof(client));
printf("%d bytes sent ",sentbytes);
}while(size==sizeof(buf));
}
}
I am trying to make a simple program for file transfer using UDP. The problem is that sendto() always returns -1. This is the code for server.
There are quite a few issues with your code. The one you're seeing is that you're not filling in the variable client properly: the clientsize parameter is used for both input and output by the recvfrom system call, so you need to initialise it to the size of the client structure:
int clientsize = sizeof(struct sockaddr_in);
Another issue is that you're not 0-terminating the filename string:
n = recvfrom(...);
filename[n] = '\0';
Finally, you're not testing for errors (bind, recvfrom, sendto, etc.). This will get you into trouble, I promise.
Related
I have a code something like this.
where recvfrom works fine if i run the code normally. but when i run the code with GDB, recvfrom doesn't wait for 2 seconds and instantly throwing errno 14.
==
char buf[sizeof(FSME_START)] = { 0 };
/* open socket */
fsm_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fsm_fd < 0)
{
perror("socket");
exit(1);
}
const struct sockaddr_in remote_addr = { .sin_family = AF_INET };
//socklen_t addrlen = sizeof(struct sockaddr);
socklen_t addrlen = sizeof(client_addr);
struct timeval tv = { .tv_sec = 2,
.tv_usec = 0};
/* set initial 1s recv timeout */
int ret = setsockopt(fsm_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if (ret < 0)
{
perror("setsockopt");
exit(1);
}
while (1)
{
const struct iovec iov = { .iov_base = (void*)FSME_START,
.iov_len = sizeof(FSME_START) };
// Send the START packet (once/sec) to the FSM-E until we get
// receive a START message back based on 1sec timeout set above.
fsm_dp_send(&iov,1,0);
ret = recvfrom(fsm_fd, (char *)buf, MAX_BUFSIZE,
MSG_WAITALL, (struct sockaddr *)&client_addr, &addrlen);
====
I tried passing client_addr and addrlen both parameters as NULL but no success. But strangely this code works if run without GDB.
Any suggestions
looks like there is an error with the size of msg i was passing with recvfrom but it was weird that one version of gdb and and even compiler was hiding this error. This error was visible only with older gdb version. Later on when i passed the correct size of the buffer, it was passing.
I send udp request to stun.l.google.com:19305, but I don't get any response from google stun server. I omit all of the error check in this piece of code. My program hang in recvfrom.
int stun_socket = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in stun_client;
memset(&stun_client, 0, sizeof(stun_client));
stun_client.sin_family = AF_INET;
stun_client.sin_port = htons(local_port);
int rc = bind(stun_socket, (struct sockaddr *)&stun_client, sizeof(stun_client));
struct sockaddr_in stun_server;
memset(&stun_server, 0, sizeof(stun_server));
stun_server.sin_family = AF_INET;
stun_server.sin_port = htons(remote_port);
inet_pton(AF_INET, server, &stun_server.sin_addr);
typedef struct stun_header_tag {
uint16_t message_type;
uint16_t message_length;
unsigned char transaction_id[16];
} stun_header_t;
stun_header_t header;
header.message_type = htons(0x0001); /* Binding Request */
header.message_length = htons(0);
*(int *)(&header.transaction_id[8]) = 0xFFEEFFEE; /* transaction id in the response should keep consistent with this one */
rc = sendto(stun_socket, (void *)&header, sizeof(header), 0, (struct sockaddr *)&stun_server, sizeof(stun_server));
char response[64];
rc = recvfrom(stun_socket, response, 64, 0, NULL, 0);
I'm guessing you are doing something similar to this or equivalent for sending the data:
sendto(sock, &header, sizeof(header), (sockaddr*)&addr, addrlen);
If that's the case, you likely forgot to convert your message_type value to network byte order (big-endian).
Try this:
header.message_type = htons(0x0001);
But if you want a better solution, and you can use C++, use the client library built into Stuntman. You can generate a binding request as follows with the C++ class, CStunMessageBuilder, declared in the stuncore/stunbuilder.h file.
CStunMessageBuilder builder;
StunTransactionId transId;
builder.AddBindingRequestHeader();
builder.AddRandomTransactionId(&transID);
unsigned char* msg = builder.GetStream().GetDataPointerUnsafe();
size_t len = builder.GetStream().GetSize();
sendto(sock, msg, len, (sockaddr*)&addr, addrlen);
I am trying to do basic socket calls, and trying to connect to google.com but the connect call always fails and returns -1. Any reason why it must be failing
int main()
{
int sockfd;
struct addrinfo *ai;
char port[4];
if(sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0) {
printf("socket return -1");
}
sprintf(port, "%d", 80);
if(getaddrinfo("www.google.com", port, NULL, &ai) < 0)
printf("-2\n");
if(connect(sockfd, ai->ai_addr, sizeof(*ai->ai_addr)) < 0)
printf("connect failed -1");
}
I believe the problem is with the parameter sizeof(*ai->ai_addr). ai->ai_addr returns a pointer to a sockaddr struct, and dereferencing brings you to the struct itself.
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
sizeof is returning the size of the entire struct, not the length of the address.
Try making the argument ai->ai_addrlen instead.
What's up guys, hope you are ok !
well, the problem is that I'm doing a chat client/server aplication but doing some tests with the server, I found out that I have a problem sending messages. I'm using a struct, sockets and DWORD WINAPI threads...
So the code in the struct is:
DWORD WINAPI threadSendMessages(LPVOID vpParam); //THREAD
typedef struct messagesServerChat{ //STRUCT
const char *messageServEnv;
}MESSAGE, *SMESSAGES;
then in the main method I call the struct to use the const char messageServEnv, a HeapAlloc to give some memory to the thread that is going to send the message and a char variable that I use to store the message
char mServer[1024] = ""; //variable to pre-store the message
SMESSAGES messages; //call the struct
messages = (SMESSAGES) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MESSAGE));
in the main method, I ask the user to insert the message that he wants to send and I use the struct to store the message and send it to the thread as a parameter:
cout<<"Dear user, please insert your message: ";
setbuf(stdin, NULL);
fgets(mServer, 1024, stdin);
messages->messageServEnv = mServer;
DWORD hSend; //send the parameters to the thread function
HANDLE sendThread = CreateThread(0, 0, threadSendMessages, mServer, 0, &hSend);
and finally the thread code function
DWORD WINAPI threadSendMessages(LPVOID lpParam){
SMESSAGES messages;
messages = (SMESSAGES)lpParam;
int mesa;
mesa = send(sConnect, (char *)messages->messageServEnv, sizeof messages->messageServEnv, 0);
//sConnect is the socket
//messages = to use the struct, and messageServEnv is the struct data that should contain the message
return 0;
}
--Edit-- I fix a lot of problems using Remy's solution but maybe I'm missing something... in the Thread threadSendMessages(SMESSAGES lpMessage)
char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);
I get and error that says messages is undifined, then, I changed to:
SMESSAGES messages;
char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);
now I can use messages and struct value messageServEnv but if I start debugging visual studio and I try to send a message, I get an error that says messages is used without being initialized, then I change that part to
SMESSAGES messages = new MESSAGE;
and now I can send messages to client but only characters and garbage code
You need to dynamically allocate the memory for each message's string data and then have the thread free the memory when finished sending it.
You are also passing the wrong pointer to the lpParameter parameter of CreateThread(), you are passing your char[] buffer instead of your allocated MESSAGE struct.
You are also using sizeof() when calling send(). Since your messageServEnv is a char* pointer, sizeof() will return 4 (32-bit) or 8 (64-bit) instead of the actual size of the string that is being pointed at.
I would suggest moving the char[] buffer directly into the struct instead of using a pointer to an external buffer, eg:
typedef struct messagesServerChat
{
char messageServEnv[1024];
}
MESSAGE, *SMESSAGES;
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);
.
cout << "Dear user, please insert your message: ";
setbuf(stdin, NULL);
SMESSAGES message = new MESSAGE;
fgets(message->messageServEnv, sizeof(message->messageServEnv), stdin);
DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend);
if (!sendThread)
delete message;
.
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{
// send() is not guaranteed to send the entire message
// in one go, so call it in a loop...
char *ptr = lpMessage->messageServEnv;
int len = strlen(lpMessage->messageServEnv); // or sizeof() if you really want to send all 1024 bytes instead
while (len > 0)
{
int mesa = send(sConnect, ptr, len, 0);
if (mesa > 0)
{
ptr += mesa;
len -= mesa;
continue;
}
// this is only needed if you are using a non-blocking socket...
if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sConnect, &fd);
timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, NULL, &fd, NULL, &tv) > 0)
continue;
}
... error handling ...
break;
}
delete message;
return 0;
}
If you want to pass a dynamically-lengthed string instead, you are better off using a std::string instead of a char[]:
typedef struct messagesServerChat
{
std::string messageServEnv;
}
MESSAGE, *SMESSAGES;
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);
.
cout << "Dear user, please insert your message: ";
setbuf(stdin, NULL);
SMESSAGES message = new MESSAGE;
getline(stdin, message->messageServEnv);
DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend);
if (!sendThread)
delete message;
.
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{
// send() is not guaranteed to send the entire message
// in one go, so call it in a loop...
char *ptr = lpMessage->messageServEnv.c_str();
int len = lpMessage->messageServEnv.length(); // or sizeof() if you really want to send all 1024 bytes instead
while (len > 0)
{
int mesa = send(sConnect, ptr, len, 0);
if (mesa > 0)
{
ptr += mesa;
len -= mesa;
continue;
}
// this is only needed if you are using a non-blocking socket...
if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sConnect, &fd);
timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, NULL, &fd, NULL, &tv) > 0)
continue;
}
... error handling ...
break;
}
delete message;
return 0;
}
I am working on IPv6 and need to craft an IPv6 packet from scratch and put it into a buffer. Unfortunately I do not have much experience with C. From a tutorial I have successfully done the same thing with IPv4 by defining
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;
};
/* Structure of a TCP header */
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 char tcph_flags;
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;
};
and fill the packet content in like this:
// IP structure
ip->iph_ihl = 5;
ip->iph_ver = 6;
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("1922.168.1.128");
// Destination IP, modify as needed, but here we accept through command line argument
ip->iph_destip = inet_addr(1922.168.1.1);
// The TCP structure. The source port, spoofed, we accept through the command line
tcp->tcph_srcport = htons(atoi("1024"));
// The destination port, we accept through command line
tcp->tcph_destport = htons(atoi("4201"));
tcp->tcph_seqnum = htons(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)));
However for IPv6 I have not find a similar way. What I already found is this struct from IETF,
struct ip6_hdr {
union {
struct ip6_hdrctl {
uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits
flow-ID */
uint16_t ip6_un1_plen; /* payload length */
uint8_t ip6_un1_nxt; /* next header */
uint8_t ip6_un1_hlim; /* hop limit */
} ip6_un1;
uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits
tclass */
} ip6_ctlun;
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
};
But I did not know how to fill in the information, for example, how to send a TCP/SYN from 2001:220:806:22:aacc:ff:fe00:1 port 1024 to 2001:220:806:21::4 port 1025?
Could anybody help me or is there any references?
Thank you vere much then.
this is what I have done so far, however there are mismatch between the code and the real packet captured by Wireshark (as discussed in comments below). I'm not sure it is possible to post a long code in comment section, so I just edit my question.
Anyone can help?
#define PCKT_LEN 2000
int main(void) {
unsigned char buffer[PCKT_LEN];
int s;
struct sockaddr_in6 din;
struct ipv6_header *ip = (struct ipv6_header *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof (struct ipv6_header));
memset(buffer, 0, PCKT_LEN);
din.sin6_family = AF_INET6;
din.sin6_port = htons(0);
inet_pton(AF_INET6, "::1", &(din.sin6_addr)); // For routing
ip->version = 6;
ip->traffic_class = 0;
ip->flow_label = 0;
ip->length = 40;
ip->next_header = 6;
ip->hop_limit = 64;
inet_pton(AF_INET6, "::1", &(ip->dst)); // IPv6
inet_pton(AF_INET6, "::1", &(ip->src)); // IPv6
tcp->tcph_srcport = htons(atoi("11111"));
tcp->tcph_destport = htons(atoi("13"));
tcp->tcph_seqnum = htons(0);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32752);
tcp->tcph_chksum = 0; // Done by kernel
tcp->tcph_urgptr = 0;
s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s < 0) {
perror("socket()");
return 1;
}
unsigned short int packet_len = sizeof (struct ipv6_header) + sizeof (struct tcpheader);
if (sendto(s, buffer, packet_len, 0, (struct sockaddr*) &din, sizeof (din)) == -1) {
perror("sendto()");
close(s);
return 1;
}
close(s);
return 0;
}
Maybe this article can help you getting started?
Edit:
Using the wikipedia article linked above I made this structure (without knowing what some of the fields means):
struct ipv6_header
{
unsigned int
version : 4,
traffic_class : 8,
flow_label : 20;
uint16_t length;
uint8_t next_header;
uint8_t hop_limit;
struct in6_addr src;
struct in6_addr dst;
};
It's no different than how the header-struct was made for IPv4 in your example. Just create a struct containing the fields, in the right order and in the right size, and fill it with the right values.
Just do the same for the TCP headers.
Unfortunately the ipv6 RFCs don't provide the same raw socket interface that you get with ipv4. From what i've seen to create ipv6 packets you have to go a level deeper and use an AF_PACKET socket to send an ethernet frame including your ipv6 packet.