Raw socket in Linux Kernel - sockets

I have an issue with this code:
bool send_packet(uint8_t *frame, const uint32_t size)
{
int len, ret;
struct iphdr *ip;
struct msghdr msg;
struct kvec vec;
ip = (struct iphdr*)(frame + ETH_HLEN); // Align ip header with buffer
tgb_pr_debug("packet ip version : %d\n",ip->version);
tgb_pr_debug("packet from %pI4 to %pI4\n",&ip->saddr, &ip->daddr);
tgb_pr_debug("packet ip protocol : %d\n",ip->protocol);
memset(&msg,0,sizeof(msg));
len = size - ETH_HLEN;
vec.iov_base = ip;
vec.iov_len = len;
ret = kernel_sendmsg(sock,&msg,&vec,1,len);
if (ret < 0) {
pr_err("sendmsg return code %d\n",ret);
return false;
}
kfree(frame);
return true;
}
With high rate it's freeze the computer. Is socket right way to send packet in Linux Kernel?

With this implémention i have no issue, it's work perfectly, if someone know why i'm interested
struct sk_buff* skb, *trailer;
struct net_device *dev;
dev = dev_get_by_name(&init_net,"enp0s5");
skb = alloc_skb(size+ETH_HLEN+2,GFP_ATOMIC);
memcpy(skb_put(skb, size), frame, size);
kfree(frame); //free buffer get from ipseclib
skb_reset_network_header(skb);
skb->dev = dev;
skb->pkt_type = PACKET_OUTGOING;
skb_cow_data(skb,1,&trailer);
dev_queue_xmit(skb);

Related

linux device driver - ADS1292R problem in reading chip id on spi

I am novice to Linux device driver and writing driver module for TI-ADS1292R chip. This driver is loading without any error, creates character device entry in /dev directory. I am also able to transfer data on SPI bus (verified it on logic analyzer and DSO).
There are two problems here.
(1) in logic analyzer it shows that chip is responding with correct chip id (0x73) on read id command, but in my driver I am getting incorrect value (0x80). Why this is happening and where the problem is?
(2) As far as I understood, my driver should automatically loaded if I have configured it through defconfig file, which is not happening in my case. Right now, I am loading it as a built-in module with obj-y option.
My code has following snippets through which I am trying to read the chip id.
static int ads_send_byte(struct ads1292_chip *dev, int data)
{
int status;
struct spi_message msg = { };
struct spi_transfer transfer = { };
dev->tx_buff[0] = data;
transfer.tx_buf = dev->tx_buff;
transfer.rx_buf = dev->rx_buff;
transfer.len = 1;
transfer.speed_hz = SPI_BUS_SPEED;
spi_message_init(&msg);
spi_message_add_tail(&transfer, &msg);
status = spi_sync(dev->spi, &msg);
printk(KERN_DEBUG "ecg: %s (%#x) %d\n", __func__, data, status);
return status;
};
static int ads_send_RREG(struct ads1292_chip *dev, char __user * buf, u8 reg, u8 size)
{
struct spi_message msg = { };
struct spi_transfer transfer = { };
int ret;
dev->tx_buff[0] = ADS1292_RREG | reg;
dev->tx_buff[1] = size - 1; // datasheet: no of regs - 1
memset(dev->rx_buff, 0, size);
memset(dev->tx_buff + 2, 0, size);
transfer.speed_hz = SPI_BUS_SPEED;
transfer.tx_buf = dev->tx_buff;
transfer.rx_buf = dev->rx_buff;
transfer.len = size + 2; // 2 is for command tx
transfer.delay_usecs = 40; // datasheet: 4 clocks after each message
transfer.cs_change = 1; // Always toggle CS line after transfer
spi_message_init(&msg);
spi_message_add_tail(&transfer, &msg);
ret = spi_sync(dev->spi, &msg);
//printk(KERN_DEBUG "ecg: %s %x\n", __func__, dev->rx_buff[0]);
if (unlikely(ret))
return ret;
ret = copy_to_user(buf, dev->rx_buff, size);
return ret;
}
static int ads_cdev_open(struct inode *inode, struct file *filp)
{
struct ads1292_dev *ads = container_of(inode->i_cdev, struct ads1292_dev, dev);
char buff[1];
printk(KERN_DEBUG "ecg: %s\n", __func__);
filp->private_data = ads;
gpio_set_value_cansleep(ads1292_gpio_start.gpio, 0);
ads_send_byte(&ads->chip, ADS1292_RESET);
mdelay(1);
ads_send_byte(&ads->chip, ADS1292_SDATAC);
mdelay(10);
ads_send_RREG(&ads->chip, buff, ADS1292_ID, 1);
printk(KERN_DEBUG "ecg: ID - %x\n", buff[0]);
return 0;
}

How to receive high Speed UDP Packets completely?

I have a UDP Server which sends data continuously. I want to receive all the packets sent by the server.
On server side I have two threads. One thread continuously reads data from the file and puts into deque. Another thread reads data from the deque and sends to the UDP client continuously. The client code continuously receives data from the server.
I have variables to keep the count of the number of bytes sent in server code and the number of bytes received in client code.
There is huge difference between the two. The server sends about 93 MB but the client receives only 3 - 5 MB.
How can I receive all the data sent by the Server?
Please find the server and client code below.
Server Code:
#define MAX_BUFFER_SIZE 1400
typedef struct
{
T_UCHAR buffer[MAX_BUFFER_SIZE];
DWORD buf_size;
}RAWDATA_LOG;
deque<RAWDATA_LOG> m_RawdataLog;
void TransmitContinuous()
{
if (m_sock_type_tcp == SOCK_UDP)
{
fileReadComplete=false;
//start data transmission thread
pWin_thread=AfxBeginThread(StartDataTransmitThread, (LPVOID) this);
ReadFromFile();
}
}
void ReadFromFile()
{
int bytesRead=0;
m_no_of_bytes = MAX_BUFFER_SIZE;
BYTE input_buf[MAX_BUFFER_SIZE]={'\0'};
GetDlgItemText(IDEBC_FILENAME,m_fileInput);
m_InputFile=NULL;
/*opening the file to read*/
m_InputFile = _tfopen(m_fileInput,L"rb");
if(m_InputFile == NULL)
{
AfxMessageBox(L"Unable to open the Input file");
}
else
{
while(!feof(m_InputFile))
{
bytesRead=fread(input_buf,1,m_no_of_bytes,m_InputFile);
writeRawdataToDeque(input_buf,m_no_of_bytes);
noofBytesReadfromFile+=bytesRead;
}
fileReadComplete=true;
}
}
void writeRawdataToDeque(T_UCHAR *buffer,T_S32 size)
{
T_S32 temp_size = size;
T_S32 size_counter = 0;
RAWDATA_LOG temp_rawDataStruct;
while(temp_size>0)
{
if(temp_size <= MAX_BUFFER_SIZE)
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],temp_size);
temp_rawDataStruct.buf_size = temp_size;
noofBytesWrittentoDeque+=temp_size;
}
else
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],sizeof(temp_rawDataStruct.buffer));
temp_rawDataStruct.buf_size = MAX_BUFFER_SIZE;
noofBytesWrittentoDeque+=MAX_BUFFER_SIZE;
}
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
m_RawdataLog.push_back(temp_rawDataStruct);
datalock.Unlock();
memset(&temp_rawDataStruct,0,sizeof(temp_rawDataStruct));
size_counter += MAX_BUFFER_SIZE;
temp_size = temp_size - MAX_BUFFER_SIZE;
}
}
unsigned int StartDataTransmitThread (LPVOID param)
{
RAWDATA_LOG temp_rawDataBuf;
int byesWritten=0;
CString tmpStr;
while(1)
{
if(!m_RawdataLog.empty())
{
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
temp_rawDataBuf = m_RawdataLog.front();
m_RawdataLog.pop_front();
datalock.Unlock();
//transmit the data through socket
byesWritten=WritetoClient(clientIp,clientPort,(const LPBYTE)&temp_rawDataBuf, MAX_BUFFER_SIZE);
noofBytesTransmitted+=byesWritten;
}
else
{
if(fileReadComplete == true)
{
break;
}
}
}
return true;
}
bool CreateServer(char ipaddr[],int port)
{
sockaddr_in ServerSockAddr;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
ServerSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
ServerSockAddr.sin_family = AF_INET;
ServerSockAddr.sin_port = htons(2011);
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
MessageBox(L"WSAStartup failed with error:" + m_wsaErr);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (INVALID_SOCKET != sock)
{
if ( SOCKET_ERROR == bind(sock,(struct sockaddr *) & ServerSockAddr, sizeof(ServerSockAddr)))
{
int b= GetLastError();
closesocket( sock );
return false;
}
}
else
{
closesocket( sock );
return false;
}
m_hComm = (HANDLE) sock;
}
int WritetoClient(char ipaddr[],int port,BYTE buf[],int len)
{
sockaddr_in clientSockAddr;
int res=0;
SOCKET s = (SOCKET) m_hComm;
clientSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
clientSockAddr.sin_family = AF_INET;
clientSockAddr.sin_port = htons(port);
res = sendto( s, (const char *)buf, len, 0, (SOCKADDR *) &clientSockAddr, sizeof(clientSockAddr));
return res;
}
Client Code:
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32")
#define BUFSIZE 1000000
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET sockfd;
int portno, n;
int serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
char *hostname;
char buf[BUFSIZE];
int BytesReceived=0;
int buff_size=1000000;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error:");
return 1;
}
/* socket: create the socket */
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sockfd < 0)
{
printf("ERROR opening socket");
}
else
{
/* build the server's Internet address */
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(2010);
serveraddr.sin_addr.s_addr=inet_addr("192.168.11.80");
/* send the message to the server */
serverlen = sizeof(serveraddr);
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char *)(&buff_size), sizeof(buff_size));
if ( SOCKET_ERROR == bind(sockfd,(struct sockaddr *) & serveraddr, sizeof(serveraddr)))
{
printf("Bind Error");
int a = GetLastError();
printf("Error ID:%d",a);
}
else
{
printf("Reading From Server:\n");
while(1)
{
n = recvfrom(sockfd, buf, sizeof(buf), 0,(struct sockaddr *) &serveraddr, &serverlen);
if (n < 0)
{
printf("ERROR in recvfrom\n");
int b = GetLastError();
printf("Error ID:%d\n",b);
}
else
{
BytesReceived+=n;
TRACE("\nTotal Bytes Received:%d\n",BytesReceived);
}
}
}
}
getchar();
return 0;
}
I see a couple of issues with your code.
On the server side, you are binding the server's socket to 192.168.11.80 AND you are sending packets to 192.168.11.80 as well, instead of sending them to whichever IP address is specified in the ipaddr parameter of the WritetoClient() function.
On the client side, you are bind()'ing the client's socket to the server's IP address.
This setup will only work if the client and server are running on the same machine. It will not work between multiple machines connected through a network.
You need to bind the client to an IP address that is local to the client's own machine, not to the server's IP address. And your server needs to send packets to the IP address that the client is actually bound to.
If you want to ensure that your client receives data only from the server's IP address, and not from other machines that may happen to be sending data over the same network, you can optionally connect() the client's socket to the server's IP address (yes, you can use connect() with UDP).
bind() is for establishing a socket's local IP address. connect() is for establishing a socket's remote/peer IP address.
Since you are (potentially) not binding the client's socket correctly, and/or (potentially) not sending to the correct IP, you are likely receiving data that you are not expecting from somewhere else. That could explain the large discrepancy you are seeing. I would suggest having your client output the data it actually receives, so you can make sure it is receiving what you are expecting, eg:
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR)
{
int b = WSAGetLastError();
printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
BytesReceived += n;
TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}

How to resolve the Mac address for an IP address under kernel module developing?

I want to build a tcp package in a kernel module and send it to another host by IP address using function dev_queue_xmit(skb). But I don't want to fill the Mac address manually by hand. The following is code for package producing.
Some kernel functions call eth_rebuild_header(skb) to rebuild Mac header. However, in my case, it hangs my computer after being called. Google results answers that arp_find will crash the OS if the arp cache contains not entry for that IP address. But I'm sure the it exists in the arp cache as printed by shell command "arp -v".
static int build_and_xmit_tcp(char * eth, u_char * smac, u_char * dmac,
u_long sip, u_long dip,
u_short sport, u_short dport,
u_char * pkt, int pkt_len,
int syn, int ack, int fin,
__be32 seq, __be32 seq_ack)
{
struct sk_buff * skb = NULL;
struct net_device * dev = NULL;
struct ethhdr * ethdr = NULL;
struct iphdr * iph = NULL;
struct tcphdr * tcph = NULL;
u_char * pdata = NULL;
if(NULL == smac || NULL == dmac)
goto out;
if(NULL == (dev= dev_get_by_name(&init_net, eth)))
goto out;
skb = alloc_skb(pkt_len + sizeof(struct iphdr) + sizeof(struct tcphdr) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
if(NULL == skb)
goto out;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->priority = 0;
skb_set_network_header(skb, 0);
skb_put(skb, sizeof(struct iphdr));
skb_set_transport_header(skb, sizeof(struct iphdr));
skb_put(skb, sizeof(struct tcphdr));
pdata = skb_put(skb, pkt_len);
{
if(NULL != pkt)
memcpy(pdata, pkt, pkt_len);
}
tcph = tcp_hdr(skb);
memset(tcph, 0, sizeof(struct tcphdr));
tcph->source = sport;
tcph->dest = dport;
tcph->doff=5;
tcph->seq = htonl(seq);
tcph-> ack_seq= htonl( seq_ack);
tcph->psh = pkt_len>0? 1:0;
tcph ->fin = fin;
tcph->ack = ack;
tcph->syn=syn;
tcph->window=__constant_htons (65535);
skb->csum = 0;
tcph->check = 0;
iph = ip_hdr(skb);
iph->version = 4;
iph->ihl = sizeof(struct iphdr)>>2;
iph->frag_off = 0;
iph->protocol = IPPROTO_TCP;
iph->tos = 0;
iph->daddr = dip;
iph->saddr = sip;
iph->ttl = 0x40;
iph->tot_len = __constant_htons(skb->len);
iph->check = 0;
iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);
skb->csum = skb_checksum(skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);
tcph->check = csum_tcpudp_magic(sip, dip, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
skb_push(skb, 14);
skb_set_mac_header(skb, 0);
ethdr = (struct ethhdr *)eth_hdr(skb);
// memcpy(ethdr->h_dest, dmac, ETH_ALEN);
// memcpy(ethdr->h_source, smac, ETH_ALEN);
ethdr->h_proto = __constant_htons(ETH_P_IP);
// arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
// dst_ha, dev->dev_addr, NULL);
eth_rebuild_header(skb); // kernel hang....
if(0 > dev_queue_xmit(skb)) {
dev_put (dev);
kfree_skb (skb);
}
return(NF_ACCEPT);
out:
dev_put (dev);
kfree_skb (skb);
return(NF_ACCEPT);
}
static int __init myhook_init(void)
{
printk("=========insert module......\n");
build_and_xmit_tcp(ETH_O, GWMAC_O, DMAC, in_aton(GWIP_O), in_aton(DIP), htons(8888), htons(DPORT),
"", 0,
1, 0, 0, 0, 0);
}
static void __exit myhook_fini(void)
{
printk("=========rmmod ......\n");
}
module_init(myhook_init);
module_exit(myhook_fini);
Google gives me some other solution. They say arp_ioctl can resolve the Mac address. However, the fact is that, arp_ioctl is compiled statically into vmlinuz, which is not exported as a symbol to other modules.
int arp_get(char *ifname, char *ipStr)
{
struct arpreq req;
struct sockaddr_in *sin;
int ret = 0;
int sock_fd = 0;
struct net_device * dev = NULL;
printk("arp ---- \n");
if(NULL == (dev= dev_get_by_name(&init_net, ifname))){
dev_put (dev);
printk("error dev get \n");
return -1;
}
struct net *net_arp = dev_net(dev);
memset(&req, 0, sizeof(struct arpreq));
sin = (struct sockaddr_in *)&req.arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in_aton(ipStr);
strncpy(req.arp_dev, ifname, 15);
ret = arp_ioctl(net_arp, SIOCGARP, &req); // can't be called
unsigned char *hw = (unsigned char *)req.arp_ha.sa_data;
printk("%#x-%#x-%#x-%#x-%#x-%#x\n", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
return 0;
}
Maybe I need make a socket structure, and try some upper functions based on a socket. But how to do it...
kernel version : 2.6.32
os version: ubuntu 9.10
gcc version : 4.41
int ip_xmit(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
struct tcphdr *tcph = tcp_hdr(skb);
printk("dst is %d\n", skb->_skb_dst);
int err;
// err = ip_route_input(skb, iph->daddr, iph->saddr, 0, skb->dev);
struct rtalbe *rt;
{
struct flowi fl = { .oif = 0,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr,
.tos = 0 } },
.proto = IPPROTO_TCP,
.flags = 0,
.uli_u = { .ports =
{ .sport = tcph->source,
.dport = tcph->dest } } };
if (err = ip_route_output_key(&init_net, &rt, &fl))
return err;
printk("err is %d\n", err);
}
skb_dst_set(skb, rt);
if(0 > ip_local_out(skb)) {
printk("dev error\n");
kfree_skb (skb);
return -1;
}
return 0;
}
function ip_route_output_key can obtain the route destination, and ip_local_out deliver the skb out.

Non-blocking sock_recvmsg() - is it possible?

I have the following function calling it out of a kernel thread in a kernel module:
static int ksocket_receive(struct socket* sock, struct sockaddr_in* addr, unsigned char* buf, int len)
{
struct msghdr msg;
mm_segment_t oldfs;
int size = 0;
if (sock->sk == NULL) return 0;
msg.msg_flags = 0;
msg.msg_name = addr;
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iocb = NULL;
oldfs = get_fs();
set_fs(KERNEL_DS);
size = sock_recvmsg(sock,&msg,len,msg.msg_flags);
set_fs(oldfs);
return size;
}
It blocks inside in sock_recvmsg(). Is there a way to have non-blocking version of sock_recvmsg()?
Something similar to MSG_DONTWAIT and O_NONBLOCK flags for the equivalent in User Space - recvmsg()...

I'm not sure if my netfilter is working or not

I'm trying to make a LKM netfilter that drops incoming packets if the number of packets arrived exceeds a certain limit.
There are five ports that the packets comes through, and netfiltering is done for each of those ports.
Here's part of my LKM netfilter (it uses procfs to write from user program):
#define MAX_PORT 5
static unsigned short int port[MAX_PORT];
static unsigned long limit;
static char char_limit[256];
static unsigned long data_count[MAX_PORT];
bool check_port(unsigned short int);
static unsigned int my_hook_fn( void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct iphdr *ip = ip_hdr(skb);
struct tcphdr *th = tcp_hdr(skb);
unsigned int source, dest;
if(!skb) return NF_ACCEPT;
if(ip->protocol==IPPROTO_TCP)
{
source = htons((unsigned short int) th->source);
dest = htons((unsigned short int) th->dest);
printk(KERN_ALERT "source: %u, destination: %u\n", source, dest);
if(!check_port(source))
{
printk(KERN_ALERT "packet dropped!\n");
return NF_DROP;
}
}
return NF_ACCEPT;
}
bool check_port(unsigned short int source)
{
int i = 0;
bool found = false;
while(!found && i < MAX_PORT)
{
if(port[i] == source)
found = true;
else if(port[i] == 0)
{
port[i] = source;
found = true;
}
i++;
}
i--;
data_count[i]++;
if(data_count[i] >= limit)
{
data_count[i] = limit;
printk(KERN_ALERT "port %hu has reached the limit!\n", port[i]);
return false;
}
return true;
}
static struct nf_hook_ops my_nf_ops = {
.hook = my_hook_fn,
.pf = PF_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
};
In my hook function, the NF_DROP seems to be correctly returned.
However, the result in my user space program shows that it's not.
Next is my user space program; this produces results in txt files.
void *thread_recv(void *arg);
#define MAX_CON 5
#define BUF_SIZE 200
int port[MAX_CON];
char ip[20];
int sock[MAX_CON];
void error_handling(char *msg);
void main(){
int i;
unsigned long limit;
char char_limit[256];
FILE *fp;
printf("packet limit : ");
scanf("%lu", &limit);
sprintf(char_limit, "%lu", limit);
fp = fopen("/proc/myproc/myproc", "w");
if(fp == NULL)
printf("unable to open myproc\n");
else
fprintf(fp, "%s", char_limit);
fclose(fp);
struct sockaddr_in serv_adr;
pthread_t thread_id[MAX_CON];
printf("ip :\n");
scanf("%s",ip);
printf("<port> <port> <port> <port> <port>\n");
scanf("%d %d %d %d %d", &(port[0]), &(port[1]), &(port[2]), &(port[3]), &(port[4]));
printf("%s %d\n", ip, port[0]);
for(i=0;i<5;i++){
sock[i]=socket(PF_INET, SOCK_STREAM, 0);
if(sock[i]==-1)
error_handling("socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=inet_addr(ip);
serv_adr.sin_port=htons(port[i]);
if(connect(sock[i], (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("connect() error");
else
printf("port %d connected\n", port[i]);
pthread_create(&(thread_id[i]),NULL, thread_recv,(void*)&(sock[i]));
}
while(1); // do infinitely, so user should end by their own. Ctrl + C
}
void *thread_recv(void *arg){
int clnt_sock= *(int*)arg; // get socketnumber from main
int str_len=0, i; // recv byte length
int tport=0; // portnumber matching socketnumber
char msg[BUF_SIZE];
time_t timer;
struct tm *t;
struct timespec spec;
unsigned long ms;
FILE *fp;
char filename[20]={NULL};
for(i=0;i<5;i++)
if(sock[i]==clnt_sock)
tport=port[i];
sprintf(filename,"%d.txt",tport);
fp=fopen(filename,"w+");
printf("%d port thread run\n", tport);
while((str_len=read(clnt_sock, msg, sizeof(msg)))){
msg[str_len]=NULL;
timer= time(NULL);
t= localtime(&timer);
clock_gettime(CLOCK_REALTIME, &spec);
ms = round(spec.tv_nsec / 1.0e6);
fprintf(fp,"%d:%d:%d.%lu %d %s\n",t->tm_hour,t->tm_min,t->tm_sec,ms,str_len,msg);
}
fclose(fp);
}
void error_handling(char *msg){
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
Within the thread_recv function, a txt file is created with its name as the matching port number.
What I was expecting from this was that once packet is dropped, the resulting txt file will stop being updated.
For example, if the limit is 10, then only 10 socket information will be written to the file.
But even when the ports have reached the limit, they keep updating the resulting txt files.
Does that mean that the packets have not been dropped properly?