I've been trying and trying to fragment my TCP packets but I havent found any helpful implementation of it. I am familiar with the theory and concepts of fragmentation, have even come across some flags such as IP_PMTUDISC_DONT, IP_PMTUDISC_WANT, and IP_PMTUDISC_DO and set them but the wireshark's capture always showed DF Flag as on.
I've set the MTU of my 'lo' Network Interface to 1500 since I'm using LoopBack Address on both, the server and the client. And I thought that fragmentation will be handled by the Network Layer, but thats not the case I guess...
Please help me with fragmentation of the packet.Here's my code...
Server.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netdb.h>
int main(){
struct sockaddr_in serv_addr, cli_addr;
char buff[255];
int FileDesc = socket(AF_INET,SOCK_STREAM, 0);
if(FileDesc < 0){
perror("Socket Creation Failed. ");
exit(EXIT_FAILURE);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(5455);
if (bind(FileDesc, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
perror("Bind Failed.");
exit(EXIT_FAILURE);
}
if (listen(FileDesc, 6) < 0){
perror("Listen Failed.");
exit(EXIT_FAILURE);
}
socklen_t cliLen;
int AcceptFD = accept(FileDesc, (sockaddr*)&cli_addr, &cliLen);
if(AcceptFD < 0){
perror("Accept Failed.");
exit(EXIT_FAILURE);
}
//Setting the MTU
struct ifreq ifr;
ifr.ifr_addr.sa_family = AF_INET;//address family
strncpy(ifr.ifr_name, "lo", sizeof(ifr.ifr_name));//interface name where you want to set the MTU
ifr.ifr_mtu = 1500; //your MTU size here
if (ioctl(FileDesc, SIOCGIFMTU, (caddr_t)&ifr) < 0){
perror("ioctl error.");
exit(1);
}
std::cout << ifr.ifr_ifru.ifru_mtu;
while(1){
//File Transfer
}
close(AcceptFD);
close(FileDesc);
return 0;
}
Client.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
int main(){
struct sockaddr_in serv_addr;
char buffer[255];
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0){
perror("Socket Creation Failed.");
exit(EXIT_FAILURE);
}
FILE *fp;
char *filename = "File.txt";
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
inet_aton("127.0.0.1", &serv_addr.sin_addr);
serv_addr.sin_port = htons(5455);
int conn = connect(fd, (const sockaddr*)&serv_addr, sizeof(serv_addr));
if (conn < 0){
perror("Connect Failed. ");
exit(EXIT_FAILURE);
}
while(1){
//File Recieve
}
close(fd);
return 0;
}
This also begs the question, how would I re-assemble my packet back in the same order?
Thank youu.
I coded a program in C of a tcp socket but once executed, the server returns an error from the accept function but i can't find out why..
If you guys can help me, that would be appreciated. Also, if you have any advice on the way i programmed this, please feel free to tell me.
Here is my code :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
int listenSocket, status, socketClient;
unsigned short int msgLength;
struct addrinfo hints, *servinfo;
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof clientAddress;
char msg[101];
//Test port number
if (argc != 2) {
fprintf(stderr,"Usage : %s [NUMERO_PORT]\n",argv[0]);
return 2;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // IPv4
hints.ai_socktype = SOCK_DGRAM; // UDP
hints.ai_flags = 0; //Car on fait le test sur la meme machine
if ((status = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 3;
}
if ((listenSocket = socket(servinfo->ai_family, servinfo-
>ai_socktype, servinfo->ai_protocol)) == -1) {
perror("socket:");
return 4;
}
if (bind(listenSocket, servinfo->ai_addr, servinfo->ai_addrlen) ==
-1) {
close(listenSocket);
perror("bind:");
return 5;
}
listen(listenSocket,5);
int sizeOfSockAddr = sizeof(clientAddress);
socketClient= accept(listenSocket, NULL, NULL);
if (socketClient < 0) {
fprintf(stderr,"Erreur accept\n");
return 6;
}
freeaddrinfo(servinfo);
printf("Waiting for a client's request %s\n", argv[1]);
while (1) {
//some things
}
}`
I wanted to compile sample code for a UDP client on a Mac OS X, but got a following error:
client.c:91:9: error: use of undeclared identifier 'MSG_CONFIRM'
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
^
I googled for the error for several hours but couldn't find anything related to this problem. Does anybody know what is the issue and how to fix it?
The code for UDP client is below
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
int n, len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
while (1)
{
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &servaddr,
&len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
}
close(sockfd);
return 0;
}
My friend suggest me to define MSG_CONFIRM as 0. He said search what is use for it. You also research it.
#define MSG_CONFIRM 0
I referenced C code on this website: https://gist.github.com/austinmarton/2862515
Here is a image to explain:
I edit it at two parts, one pat is for ethertype(change 0x0800 to a custom-protocol 0x1234)
and another part is deleting code for IP header processing (because original code is based on IP, but I need a raw ethernet frame).
I used wireshark to detect packets, and I can receive the packets I sent(in left of image),and I can see send.out exactly sending packets(bottom right of image). But recv.out cannot receive packet !?(upper right of image).
However, if I use 0x0800 for protocol, recv.out can receive packets from outside, but still cannot receive the packets I sent.
Is there any mistake for setting socket
Here is my code:
send.c
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#define MY_DEST_MAC0 0xbc
#define MY_DEST_MAC1 0xee
#define MY_DEST_MAC2 0x7b
#define MY_DEST_MAC3 0x75
#define MY_DEST_MAC4 0x56
#define MY_DEST_MAC5 0x2a
#define DEFAULT_IF "eth0"
#define BUF_SIZ 1024
int main(int argc, char *argv[])
{
int sockfd;
struct ifreq if_idx;
struct ifreq if_mac;
int tx_len = 0;
char sendbuf[BUF_SIZ];
struct ether_header *eh = (struct ether_header *) sendbuf; /*structure*/
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
struct sockaddr_ll socket_address;
char ifName[IFNAMSIZ];
unsigned short proto = 0x1234;
/* Get interface name *//*eth0*/
if (argc > 1)
strcpy(ifName, argv[1]);
else
strcpy(ifName, DEFAULT_IF);
/* Open RAW socket to send on *//*IPv4*/
if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(proto))) == -1) {
perror("socket");
}
/* Get the index of the interface to send on *//*0*/
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)/*save INDEX info into if_idx*/
perror("SIOCGIFINDEX");
/* Get the MAC address of the interface to send on *//*local*//*save MAC info into if_mac*/
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR");
/* Construct the Ethernet header */
memset(sendbuf, 0, BUF_SIZ);
/* Ethernet header */
eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0];
eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1];
eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2];
eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3];
eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4];
eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5];
eh->ether_dhost[0] = MY_DEST_MAC0;
eh->ether_dhost[1] = MY_DEST_MAC1;
eh->ether_dhost[2] = MY_DEST_MAC2;
eh->ether_dhost[3] = MY_DEST_MAC3;
eh->ether_dhost[4] = MY_DEST_MAC4;
eh->ether_dhost[5] = MY_DEST_MAC5;
/* Ethertype field */
eh->ether_type = htons(proto);
tx_len += sizeof(struct ether_header);
/* Packet data */
sendbuf[tx_len++] = "h";
sendbuf[tx_len++] = "e";
sendbuf[tx_len++] = "l";
sendbuf[tx_len++] = "l";
sendbuf[tx_len++] = "o";
/* Index of the network device */
socket_address.sll_ifindex = if_idx.ifr_ifindex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = MY_DEST_MAC0;
socket_address.sll_addr[1] = MY_DEST_MAC1;
socket_address.sll_addr[2] = MY_DEST_MAC2;
socket_address.sll_addr[3] = MY_DEST_MAC3;
socket_address.sll_addr[4] = MY_DEST_MAC4;
socket_address.sll_addr[5] = MY_DEST_MAC5;
/* Send packet */
int cnt=0;
while(cnt<5){
if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)
printf("Send failed\n");
else
printf("success!\n");
cnt++;
}
return 0;
}
recv.c
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#define DEST_MAC0 0xbc
#define DEST_MAC1 0xee
#define DEST_MAC2 0x7b
#define DEST_MAC3 0x75
#define DEST_MAC4 0x56
#define DEST_MAC5 0x2a
#define ETHER_TYPE 0x1234
#define DEFAULT_IF "eth0"
#define BUF_SIZ 1024
int main(int argc, char *argv[])
{
char sender[INET6_ADDRSTRLEN];
int sockfd, ret, i;
int sockopt;
ssize_t numbytes;
struct ifreq ifopts; /* set promiscuous mode */
struct sockaddr_storage their_addr;
uint8_t buf[BUF_SIZ];
char ifName[IFNAMSIZ];
/* Get interface name *//*eth0*/
if (argc > 1)
strcpy(ifName, argv[1]);
else
strcpy(ifName, DEFAULT_IF);
/* Header structures */
struct ether_header *eh = (struct ether_header *) buf;
/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE *//*0x1234*/
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
perror("listener: socket");
return -1;
}
/* Set interface to promiscuous mode - do we need to do this every time? *//*cpy ifname into ifr_name*/
strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1);
ioctl(sockfd, SIOCGIFFLAGS, &ifopts); /*set promisc mode*/
ifopts.ifr_flags |= IFF_PROMISC;
ioctl(sockfd, SIOCSIFFLAGS, &ifopts);
/* Allow the socket to be reused - incase connection is closed prematurely */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
perror("setsockopt");
close(sockfd);
exit(EXIT_FAILURE);
}
/* Bind to device */
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1) {
perror("SO_BINDTODEVICE");
close(sockfd);
exit(EXIT_FAILURE);
}
repeat: printf("listener: Waiting to recvfrom...\n");
numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
printf("listener: got packet %lu bytes\n", numbytes);
/* Check the packet is for me */
if (eh->ether_dhost[0] == DEST_MAC0 &&
eh->ether_dhost[1] == DEST_MAC1 &&
eh->ether_dhost[2] == DEST_MAC2 &&
eh->ether_dhost[3] == DEST_MAC3 &&
eh->ether_dhost[4] == DEST_MAC4 &&
eh->ether_dhost[5] == DEST_MAC5) {
printf("Correct destination MAC address\n");
} else {
printf("Wrong destination MAC: %x:%x:%x:%x:%x:%x\n",
eh->ether_dhost[0],
eh->ether_dhost[1],
eh->ether_dhost[2],
eh->ether_dhost[3],
eh->ether_dhost[4],
eh->ether_dhost[5]);
ret = -1;
goto done;
}
/* Print packet */
printf("\tData:");
for (i=0; i<numbytes; i++) printf("%02x:", buf[i]);
printf("\n");
done: goto repeat;
close(sockfd);
return ret;
}
you can get All frames from your target with below changes in your receive code :
please replace line :
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
with this line :
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
Because in your original code you changed normal ethernet header type then OS can not detect its process listener(your program) and get it to you but when you set this line, OS can get you all results so you can get your special answers.
I'm starting to do socket programming so someone should confirm this.
I'm pretty sure the interface will drop the packet because the source and destination mac are the same... try using another PC and change the destination mac on each side to confirm this (virtual machines work as well)
I have also used a similar code to transfer Ethernet frames. This type of socket does not work locally. As #Goncalo suggested use a different PC or if you have two NICs on your PC you should use them. Here is the Code I used to receive Frames.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
union ethframe
{
struct
{
struct ethhdr header;
unsigned char data[ETH_DATA_LEN];
} field;
unsigned char buffer[ETH_FRAME_LEN];
};
int main(int argc, char **argv) {
char *iface = "eth1";
unsigned char dest[ETH_ALEN]
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned short proto = 0x1234;
int recv_result,i;
char buff[ETH_FRAME_LEN];
unsigned short data_len;
int s;
if ((s = socket(AF_PACKET, SOCK_RAW, htons(proto))) < 0) {
printf("Error: could not open socket\n");
return -1;
}
struct ifreq buffer;
int ifindex;
memset(&buffer, 0x00, sizeof(buffer));
strncpy(buffer.ifr_name, iface, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &buffer) < 0) {
printf("Error: could not get interface index\n");
close(s);
return -1;
}
ifindex = buffer.ifr_ifindex;
unsigned char source[ETH_ALEN];
if (ioctl(s, SIOCGIFHWADDR, &buffer) < 0) {
printf("Error: could not get interface address\n");
close(s);
return -1;
}
memcpy((void*)source, (void*)(buffer.ifr_hwaddr.sa_data),
ETH_ALEN);
struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
socklen_t sll_len = (socklen_t)sizeof(saddrll);
if (recv_result = recvfrom(s, buff, ETH_FRAME_LEN, 0,
(struct sockaddr *)&saddrll, &sll_len) > 0)
printf("Success!\n");
else
printf("Error, could not send\n");
data_len=sizeof(buff);
printf("\tData:");
for (i=0; i<data_len; i++) printf("%c", buff[i]);
printf("\tDone: \n");
close(s);
return 0;
}
I am writing a CLIENT/SERVER program and I have a problem with the client part.
In the client part, I start by receiving messages from the server but when I want to send a message to the server, I have a problem - how can I get the server socket that I can use as first parameter in the send function?
Function: int connect (int socket, struct sockaddr *addr, socklen_t length)
this is a part of the client code :
#if defined (WIN32)
#include <winsock2.h>
typedef int socklen_t;
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
#include <stdio.h>
#include <stdlib.h>
#define PORT 23
int main(void)
{
#if defined (WIN32)
WSADATA WSAData;
int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
#else
int erreur = 0;
#endif
SOCKET csock;
SOCKADDR_IN sin;
char buffer[32] = "";
if(!erreur)
{
csock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
if(connect(csock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
//
if(recv(csock, buffer, 32, 0) != SOCKET_ERROR)
printf("Recu : %s\n", buffer);
char buffer1[32] = "how are you !";
send( ?sock?, buffer1, 32, 0); // here is my problem , so what is the first parameter(?sock?) in the "send" function that i need to send message to the server ?
.......
......
.....
You already have it: it is your csock variable. TCP Connections are established both ways. When you connected to your sever you got value for your csock: you can use it for both sending and receiving data.