FireBall
asked on
access structure from fork
when i add an ip to my hashtable from main process before start fork or in the forked process child it count independantly num_entries then the normal process in the program.
How should i solve to not behave them independently ?
How should i solve to not behave them independently ?
void child(){
int j = 0;
for (; j < 5000; ++j)
{
int num_entries = ip4map.size();
printf("%d \n",num_entries);
usleep(500000);
}
}
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip)
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
};
std::map<IP4, int> ip4map;
ASKER
if i use the std::map<IP4, int> ip4map; inside the main function this time other subprocesses can not access it :
so i put it to global before any code and resolved the errors in the program but not the independent behaviour
so i put it to global before any code and resolved the errors in the program but not the independent behaviour
dinleyici.c: In function ‘void processRingPacket(const pfring_pkthdr*, const u_char*, const u_char*)’:
dinleyici.c:56:6: error: ‘ip4map’ was not declared in this scope
ip4map[dot_dst_ip]++;
^
dinleyici.c: In function ‘void child()’:
dinleyici.c:68:25: error: ‘ip4map’ was not declared in this scope
int num_entries = ip4map.size();
^
dinleyici.c: In function ‘int main(int, char**)’:
dinleyici.c:100:29: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
if(device == NULL) device = DEFAULT_DEVICE;
^
dinleyici.c:101:14: warning: NULL used in arithmetic [-Wpointer-arith]
if(rate == NULL) rate = DEFAULT_RATE;
^
ASKER
one more strange thing i try to make traffic harder on the interface , there is sth really strange there should be somewhere empty the list when fork is work ?
1 Child counter
37.123.98.138 processRingPacket counter: 1
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
......................
37.123.98.138 processRingPacket counter: 2
2 Child counter
37.123.98.138 processRingPacket counter: 2
2 Child counter
78.175.202.247 processRingPacket counter: 2
2 Child counter
78.175.202.247 processRingPacket counter: 2
2 Child counter
78.175.202.247 processRingPacket counter: 2
2 Child counter
78.175.202.247 processRingPacket counter: 2
0 Child counter
0 Child counter
2 Child counter
37.123.98.138 processRingPacket counter: 2
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
ASKER
check this part please it is very strange :
78.175.202.247 ip has been added to the list and it count 2 on both process
then child returned to 0 , when 37.123.98.138 is incremented the ip4["37.123.98.138"]++ both process told 2 again with the 78.175.202.247
how that happens ?
there are actually 2 ip in the list after here :
but fork process counting 0 when there is no change :) i am really shocked now
78.175.202.247 ip has been added to the list and it count 2 on both process
then child returned to 0 , when 37.123.98.138 is incremented the ip4["37.123.98.138"]++ both process told 2 again with the 78.175.202.247
how that happens ?
78.175.202.247 processRingPacket counter: 2
0 Child counter
0 Child counter
2 Child counter
37.123.98.138 processRingPacket counter: 2
0 Child counter
0 Child counter
there are actually 2 ip in the list after here :
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
1 Child counter
37.123.98.138 processRingPacket counter: 1
2 Child counter
78.175.202.247 processRingPacket counter: 2
2 Child counter
37.123.98.138 processRingPacket counter: 2
2 Child counter
37.123.98.138 processRingPacket counter: 2
but fork process counting 0 when there is no change :) i am really shocked now
ASKER
I am sorry it was my mistake correct one this is still counting independently
i forget this code in the packet reader :
printf("%d Child counter \n",num_entries);
this is why it write as this sorry.
i forget this code in the packet reader :
printf("%d Child counter \n",num_entries);
this is why it write as this sorry.
37.123.98.138 processRingPacket counter: 2
37.123.98.138 processRingPacket counter: 2
37.123.98.138 processRingPacket counter: 2
37.123.98.138 processRingPacket counter: 2
0 Child counter
37.123.98.138 processRingPacket counter: 2
37.123.98.138 processRingPacket counter: 2
0 Child counter
0 Child counter
0 Child counter
37.123.98.138 processRingPacket counter: 2
0 Child counter
did you try passing the map as an argument to child?
you would do the same for function processRingPacket. then both Child and processRingPacket would access the same map.
this may crash. you definitively should only read in child function (not increment) and access only map items which you've found before. otherwise you would create members what most probably crashes,
Sara
you would do the same for function processRingPacket. then both Child and processRingPacket would access the same map.
this may crash. you definitively should only read in child function (not increment) and access only map items which you've found before. otherwise you would create members what most probably crashes,
Sara
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes i tryed :
result is same
if (pid == 0)
{
int count = 0;
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_set_sampling_rate(ring, rate) ;
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&count, 1);
return 0;
}
else if (pid > 0)
{
child(ip4map);
}
void child(std::map<IP4, int> ip4map){
int j = 0;
for (; j < 5000; ++j)
{
int num_entries = ip4map.size();
printf("%d Child counter \n",num_entries);
usleep(500000);
}
}
result is same
[root@localhost Project_V1_09.08.2017]# ./dinleyici
0 Child counter
Opening Device: p1p2
0 Child counter
37.123.98.138 processRingPacket counter: 1
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
0 Child counter
oh i missed the following code:
they moved the data to shared memory and that is why it worked.
Sara
void initialise_shared()
{
// place our shared data in shared memory
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED | MAP_ANONYMOUS;
data = mmap(NULL, sizeof(shared_data), prot, flags, -1, 0);
assert(data);
they moved the data to shared memory and that is why it worked.
Sara
ASKER
their code is working when it is single complied but not for my condition.
[root@localhost shared_data_mutex]# gcc share.c -o share -pthread
[root@localhost shared_data_mutex]# ls
share share.c
[root@localhost shared_data_mutex]# ./share
parent sleeping ..
child waiting. ..
child waiting. ..
child waiting. ..
child waiting. ..
setting done ..
got done!
child exiting ..
parent exiting ..
the problem is that they had a fixed sized structure while we have a dynamically c++ class object.
i need to think about a solution.
Sara
i need to think about a solution.
Sara
ASKER
Yes correct and also their code working good on compiled alone but in my code (mixed of libraries ) return error :
dinleyici.c: In function ‘void initialise_shared()’:
dinleyici.c:33:62: error: invalid conversion from ‘void*’ to ‘shared_data*’ [-fpermissive]
data = mmap(NULL, sizeof(shared_data), prot, flags, -1, 0);
we could make that there are two maps, one for child and one for parent and then synchronize the the maps when incrementing an ip via shared memory and mutex.
do you need to increment on both sides or only from parent?
Sara
do you need to increment on both sides or only from parent?
Sara
ASKER
Actually it is sth about listening the interface ports and box routing the traffic.
Router ----- eth0 BOX eth1 ---- Server
our aim has 4 steps :
1. to listen eth1 for SYN & ACK & UDP and other dos packets -> this is ok
2. there will be an independent process and control the counters on the hashtables periodically in every 200ms and detect the anomality depending on the limits that we create
3.detecting of attack structure -> this module written on perl and it is ok
4.push the drop rules to the netfilter directly on kernel -> this module is ok
actually we do it on perl the 2nd step but perl listening the eth very late and without pf_ring . and that cause the bypass attack for 3-4 seconds with millions of packet to the server. That makes huge problem on streams / games etc...
So we need to get the information directly from pf_ring drivers. and this is only available with c++ and we need to resolve now the issue on 2nd step
It's aim is the write on table destination address & packet type (SYN , ACK , UDP , ICMP etc) & check the previous table in periodically and clean them. This is not healty to control from packet trigged function. It need to process independently. Because when it is under attack kernel having some difficulties on process order of packets and that cause latency to check on it's own process.
Router ----- eth0 BOX eth1 ---- Server
our aim has 4 steps :
1. to listen eth1 for SYN & ACK & UDP and other dos packets -> this is ok
2. there will be an independent process and control the counters on the hashtables periodically in every 200ms and detect the anomality depending on the limits that we create
3.detecting of attack structure -> this module written on perl and it is ok
4.push the drop rules to the netfilter directly on kernel -> this module is ok
actually we do it on perl the 2nd step but perl listening the eth very late and without pf_ring . and that cause the bypass attack for 3-4 seconds with millions of packet to the server. That makes huge problem on streams / games etc...
So we need to get the information directly from pf_ring drivers. and this is only available with c++ and we need to resolve now the issue on 2nd step
It's aim is the write on table destination address & packet type (SYN , ACK , UDP , ICMP etc) & check the previous table in periodically and clean them. This is not healty to control from packet trigged function. It need to process independently. Because when it is under attack kernel having some difficulties on process order of packets and that cause latency to check on it's own process.
ASKER
what about the create threads and if the thread id is 1 then work the child if the thread id is 2 then work the packet control ?
is that do the same job with fork ? As far as i see pthread use global vars instead of duplicate them like fork
https://www.tutorialspoint.com/cplusplus/cpp_multithreading.htm
is that do the same job with fork ? As far as i see pthread use global vars instead of duplicate them like fork
https://www.tutorialspoint.com/cplusplus/cpp_multithreading.htm
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
SharedData() { memset(this, 0, sizeof(SharedData));
void incrementIp(unsigned int ip4)
{
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
//queue is full
pthread_mutex_unlock(&mutex);
usleep(500000);
// try again
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++:
}
pthread_mutex_unlock(&mutex);
}
};
SharedData shared_data;
static shared_data* data = NULL;
void initialise_shared()
{
// place our shared data in shared memory
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED | MAP_ANONYMOUS;
data = mmap(NULL, sizeof(shared_data), prot, flags, -1, 0);
assert(data);
data->done = false;
// initialise mutex so it works properly in shared memory
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&data->mutex, &attr);
}
we that we had a ring buffer for 100 ip address in the shared memory.
call the initial_shared in main like they did.
before you access the map in child you would call
data->synchronizeIps(ip4map);
after you incremented an ip in parent you would call
data->incrementIp(*(unsigned int*)&IP4("192.1.185.9").ip4[0]);
i hope it compiles because i cannot test it.
Sara
and struct IP4 must be defined above Shared_Data.
threads do not help cause each fork process shares its environment with its process, so we don't have shared data between threads of child and parent.
the only way when forking is p2p communication what i tried with shared memory. another way is pipes or udp. but the latter if you want to monitor udp.
threads would come into play if you actually don't need fork process but only threads. still we would need a mutex but we could use shared global maps.
Sara
what about the create threads
threads do not help cause each fork process shares its environment with its process, so we don't have shared data between threads of child and parent.
the only way when forking is p2p communication what i tried with shared memory. another way is pipes or udp. but the latter if you want to monitor udp.
threads would come into play if you actually don't need fork process but only threads. still we would need a mutex but we could use shared global maps.
Sara
ASKER
It returns the given error below, does not accepting the funciton in the place
SharedData()
{
memset(this, 0, sizeof(SharedData));
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
//queue is full
pthread_mutex_unlock(&mutex);
usleep(500000);
// try again
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++:
}
}
}
};
dinleyici.c:35:38: error: a function-definition is not allowed here before ‘{’ token
void incrementIp(unsigned int ip4){
^
dinleyici.c:63:2: error: expected ‘}’ at end of input
}
^
ASKER
ok i've correct the problem it is about { end of this line SharedData() { memset(this, 0, sizeof(SharedData));
now the error :
now the error :
dinleyici.c:86:21: error: in C++98 ‘ip’ must be initialized by constructor, not by ‘{...}’
IP4 ip = { 0 };
^
dinleyici.c:88:20: error: expected ‘;’ before ‘:’ token
ip4map[ip]++:
^
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip)
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
};
std::map<IP4, int> ip4map;
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
SharedData() { memset(this, 0, sizeof(SharedData));}
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
pthread_mutex_unlock(&mutex);
usleep(500000);
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++:
}
}
};
the constructor
must end with }
Sara
SharedData() { memset(this, 0, sizeof(SharedData));
must end with }
class SharedData
{
//--------------------------------------------------v
SharedData() { memset(this, 0, sizeof(SharedData)); }
Sara
ok.
remove the ' = { 0 }'. that can only be done if a struct or class has not a constructor.
add to constructor of struct IP4
now IP4 has a default constructor. do the same with struct IP4TTL but also usttl = 0 .
Sara
remove the ' = { 0 }'. that can only be done if a struct or class has not a constructor.
add to constructor of struct IP4
IP4(const char * szip = "0.0.0.0")
{
....
}
now IP4 has a default constructor. do the same with struct IP4TTL but also usttl = 0 .
Sara
ASKER
yes and the problem is about the compiler when i add this to end of compile string -std=c++11 it resolved nearly all the issues.
There is one last issue :
There is one last issue :
dinleyici.c:84:8: error: ‘shared_data’ does not name a type
static shared_data* data = NULL;
static shared_data* data = NULL;
should be
Shared_Data * data = NULL;
there is also an error in synchronizeIps
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++; // here is a semicolon
begin = n; // new begin
}
}
Sara
ASKER
all the errors still about data variable. this is not solved :
Shared_Data * data = NULL;
dinleyici.c: At global scope:
dinleyici.c:82:1: error: ‘Shared_Data’ does not name a type
Shared_Data * data = NULL;
^
dinleyici.c: In function ‘void initialise_shared()’:
dinleyici.c:89:5: error: ‘data’ was not declared in this scope
data = mmap(NULL, sizeof(shared_data), prot, flags, -1, 0);
^
dinleyici.c: In function ‘void processRingPacket(const pfring_pkthdr*, const u_char*, const u_char*)’:
dinleyici.c:120:3: error: ‘data’ was not declared in this scope
data->incrementIp(*(unsigned int*)&IP4(dot_dst_ip).ip4[0]);
ASKER
struct SharedData and the void shared_data() { memset(this, 0, sizeof(SharedData));}
was the same capital letters i change the given below form and the problems has been removed.
now there is only one last error :
was the same capital letters i change the given below form and the problems has been removed.
now there is only one last error :
dinleyici.c:86:61: error: invalid conversion from ‘void*’ to ‘SharedData*’ [-fpermissive]
data = mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
void shared_data() { memset(this, 0, sizeof(SharedData));}
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
pthread_mutex_unlock(&mutex);
usleep(500000);
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
begin = n;
}
}
};
static SharedData * data = NULL;
try
Sara
data = (Shared_Data *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
Sara
c++ needs an explicit cast while c is happy with a void pointer.
Sara
Sara
it is SharedData not Shared_Data.
ASKER
c++ needs an explicit cast while c is happy with a void pointer.
yes i realize it but c does not compile mixed map / string.h this kind of libraries. so i need to go on with c++ .
how should i do it on c++ ?
should compile if you do
that is an explicit cast from void* to SharedData*.
Sara
data = (SharedData *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
that is an explicit cast from void* to SharedData*.
Sara
ASKER
yes :)
but data->synchronizeIps(ip4ma p);
this line causing segmentation fault :D
but data->synchronizeIps(ip4ma
this line causing segmentation fault :D
did you define static std::map?
if yes, remove the static
if no, add static
the map must be defined outside of main below struct IP4.
Sara
if yes, remove the static
if no, add static
the map must be defined outside of main below struct IP4.
Sara
if that still crashes remove all global std::map and also from main and put them as static maps into the functions where you call data->IncrementIp or data->SynchronizeIps. check whether data is not NULL.
ASKER
static std::map<IP4, int> ip4map;
std::map<IP4, int> ip4map;
both the same causing segmentation fault on this part :
when i remove this lines it is ok but of course not sync this time
std::map<IP4, int> ip4map;
both the same causing segmentation fault on this part :
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
begin = n;
}
when i remove this lines it is ok but of course not sync this time
ASKER
I' ve removed from the global and put into the functions , still segmentation fault is going on on the same place
did you try
and
Sara
void processRingPacket(...)
{
static std::map<IP4, int> ip4map;
....
ip4map["132.5.185.2"]++;
data->IncrementIp(*(unsigned int*)&IP4("132.5.185.2").ip4[0]));
// and so on
...
and
void Child()
{
static std::map<IP4, int> ip4map;
data->SynchronizeIps();
....
Sara
ASKER
yes result is same
you can try to make the functions IncrementIp and SynchronizeIps static functions of struct SharedData
then call them SharedData::IncrementIp(.. .) and SharedData::SynchronizeIps (...)
i am now on the road home for some hours. post all your code i will check later.
static void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((data->end+1)%100 == data->begin)
{
pthread_mutex_unlock(&data->mutex);
usleep(500000);
incrementIp(ip4);
}
else
{
data->ip_ring[data->end] = ip4;
data->end = (++data->end)%100;
}
pthread_mutex_unlock(&data->mutex);
}
static void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&data->mutex);
for (int n = data->begin; n != (data->end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &data->ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
data->begin = n;
}
}
then call them SharedData::IncrementIp(..
i am now on the road home for some hours. post all your code i will check later.
ASKER
static SharedData * data = NULL;
data can not be used in the SharedData function because it must be declared already after the SharedData
ASKER
#include <pcap.h>
#include <pfring.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <byteswap.h>
#include <unistd.h>
#include <map>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip)
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
};
static std::map<IP4, int> ip4map;
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
void shared_data() { memset(this, 0, sizeof(SharedData));}
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
pthread_mutex_unlock(&mutex);
usleep(500000);
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
begin = n;
}
pthread_mutex_unlock(&mutex);
}
};
static SharedData * data = NULL;
void initialise_shared()
{
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED | MAP_ANONYMOUS;
//size_t abc =(size_t) malloc(sizeof(SharedData));
data = (SharedData *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
data->done = false;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&data->mutex, &attr);
}
// -std=c++11 ile derlenmesi gerekiyor
#define MAXBYTES2CAPTURE 100
#define DEFAULT_DEVICE "p1p2"
#define DEFAULT_RATE 100
void processRingPacket(const struct pfring_pkthdr* pkthdr, const u_char* packet, const u_char *arg)
{
memset((void*)&pkthdr->extended_hdr.parsed_pkt, 0, sizeof(pkthdr->extended_hdr.parsed_pkt));
pfring_parse_pkt((u_char*)packet, (struct pfring_pkthdr*)pkthdr, 4, 1, 0);
struct in_addr dst_addr;
dst_addr.s_addr = __bswap_32(pkthdr->extended_hdr.parsed_pkt.ip_dst.v4);
char *dot_dst_ip = inet_ntoa(dst_addr);
ip4map[dot_dst_ip]++;
data->incrementIp(*(unsigned int*)&IP4(dot_dst_ip).ip4[0]);
int num_entries = ip4map.size();
printf("%s processRingPacket counter: %d \n" ,dot_dst_ip,num_entries );
}
void child(){
int j = 0;
for (; j < 5000; ++j)
{
data->synchronizeIps(ip4map);
int num_entries = ip4map.size();
printf("%d Child counter \n",num_entries);
usleep(500000);
}
}
void printHelp(void) {
printf("SPDNet Anomality Detection Software \n\n");
printf("-h Yardım Menusu\n");
printf("-i <örn: eth0> Çıkış portunuzu seçiniz\n");
}
int main(int argc, char* argv[])
{
char *device = NULL, c;
int rate;
while((c = getopt(argc,argv,"hi")) != '?') {
if((c == 255) || (c == -1)) break;
switch(c) {
case 'h':
printHelp();
return(0);
break;
case 'i':
device = strdup(optarg);
break;
case 'r':
//rate = atoi(optarg); //Burası bozuyor incele
break;
}
}
printf(device);
if(device == NULL) device = DEFAULT_DEVICE;
if(rate == NULL) rate = DEFAULT_RATE;
pid_t pid = fork();
if (pid == 0)
{
int count = 0;
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_set_sampling_rate(ring, rate) ;
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&count, 1);
return 0;
}
else if (pid > 0)
{
child();
}
}
move the implementation of the static functions below the definition of data.
and in the struct SharedData only declare the functions:
Sara
....
static SharedData * data = NULL;
void SharedData::incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((data->end+1)%100 == data->begin)
{
pthread_mutex_unlock(&data->mutex);
usleep(500000);
incrementIp(ip4);
}
else
{
data->ip_ring[data->end] = ip4;
data->end = (++data->end)%100;
}
pthread_mutex_unlock(&data->mutex);
}
void SharedData::synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&data->mutex);
for (int n = data->begin; n != (data->end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &data->ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
data->begin = n;
}
}
and in the struct SharedData only declare the functions:
static void incrementIp(unsigned int ip4);
static void synchronizeIps(std::map<IP4, int> & ip4map);
Sara
ASKER
that made every thing more complicated. Here is the full code where i stay , i think it is better that you check from here because data is used in initalize and other places. if i make them SharedData::data that create new problems and also C++2011 see it as an illegal operation
#include <pcap.h>
#include <pfring.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <byteswap.h>
#include <unistd.h>
#include <map>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip)
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
};
static std::map<IP4, int> ip4map;
struct SharedData
{
static SharedData * data = NULL;
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
void shared_data() { memset(this, 0, sizeof(SharedData));}
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
pthread_mutex_unlock(&mutex);
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
begin = n;
}
pthread_mutex_unlock(&mutex);
}
};
static SharedData * data = NULL;
void initialise_shared()
{
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED | MAP_ANONYMOUS;
//size_t abc =(size_t) malloc(sizeof(SharedData));
data = (SharedData *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
data->done = false;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&data->mutex, &attr);
}
// -std=c++11 ile derlenmesi gerekiyor
#define MAXBYTES2CAPTURE 100
#define DEFAULT_DEVICE "p1p2"
#define DEFAULT_RATE 100
void processRingPacket(const struct pfring_pkthdr* pkthdr, const u_char* packet, const u_char *arg)
{
memset((void*)&pkthdr->extended_hdr.parsed_pkt, 0, sizeof(pkthdr->extended_hdr.parsed_pkt));
pfring_parse_pkt((u_char*)packet, (struct pfring_pkthdr*)pkthdr, 4, 1, 0);
struct in_addr dst_addr;
dst_addr.s_addr = __bswap_32(pkthdr->extended_hdr.parsed_pkt.ip_dst.v4);
char *dot_dst_ip = inet_ntoa(dst_addr);
ip4map[dot_dst_ip]++;
//
data->incrementIp(*(unsigned int*)&IP4(dot_dst_ip).ip4[0]);
int num_entries = ip4map.size();
printf("%s processRingPacket counter: %d \n" ,dot_dst_ip,num_entries );
}
void child(){
int j = 0;
for (; j < 5000; ++j)
{
data->synchronizeIps(ip4map);
int num_entries = ip4map.size();
printf("%d Child counter \n",num_entries);
usleep(500000);
}
}
void printHelp(void) {
printf("SPDNet Anomality Detection Software \n\n");
printf("-h Yardım Menusu\n");
printf("-i <örn: eth0> Çıkış portunuzu seçiniz\n");
}
int main(int argc, char* argv[])
{
initialise_shared();
char *device = NULL, c;
int rate;
while((c = getopt(argc,argv,"hi")) != '?') {
if((c == 255) || (c == -1)) break;
switch(c) {
case 'h':
printHelp();
return(0);
break;
case 'i':
device = strdup(optarg);
break;
case 'r':
//rate = atoi(optarg); //Burası bozuyor incele
break;
}
}
printf(device);
if(device == NULL) device = DEFAULT_DEVICE;
if(rate == NULL) rate = DEFAULT_RATE;
pid_t pid = fork();
if (pid == 0)
{
int count = 0;
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_set_sampling_rate(ring, rate) ;
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&count, 1);
return 0;
}
else if (pid > 0)
{
child();
}
}
ASKER
This part is causing the segment fault :
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
IP4 ip = { 0 };
memcpy(&ip.ip4, &ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
begin = n;
}
ASKER
I think the error is about that line : IP4 ip = { 0 };
ASKER
ok i think all the problem is about increment adding
data->incrementIp(*(unsign ed int*)&IP4(dot_dst_ip).ip4[ 0]);
because that try to sends unsigned int but we send dot_dst_ip "185.9.156.2" for ex. i think the problem is sth about the ip4 structure
data->incrementIp(*(unsign
because that try to sends unsigned int but we send dot_dst_ip "185.9.156.2" for ex. i think the problem is sth about the ip4 structure
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip)
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
};
static std::map<IP4, int> ip4map;
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
void shared_data() { memset(this, 0, sizeof(SharedData));}
void incrementIp(unsigned int ip4){
pthread_mutex_lock(&mutex);
if ((end+1)%100 == begin)
{
pthread_mutex_unlock(&mutex);
incrementIp(ip4);
}
else
{
ip_ring[end] = ip4;
printf ("added to list %c \n",ip4);
end = (++end)%100;
}
pthread_mutex_unlock(&mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&mutex);
printf(" here << --- ");
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
//IP4 ip={0};
char test;
memcpy(&test, &ip_ring[n], sizeof(unsigned int));
printf("%c ->> HERE ",test);
//ip4map[a]++;
begin = n;
}
pthread_mutex_unlock(&mutex);
}
};
here << --- ->> HERE 0 Child counter
added to list ?
37.123.98.138 processRingPacket counter: 1
here << --- ? ->> HERE ->> HERE 0 Child counter
here << --- ->> HERE 0 Child counter
here << --- ->> HERE 0 Child counter
ASKER
The problem is about :
&test -> is coming as decimal ip not the format like "185.9.156.4" so when i convert it to the decimal format it is ok now like the given below
but i did not used //IP4 ip={0}; i am still trying to understand what we do , so is that make sense ?
&test -> is coming as decimal ip not the format like "185.9.156.4" so when i convert it to the decimal format it is ok now like the given below
for (int n = begin; n != (end+1)%100; n = (n+1)%100)
{
//IP4 ip={0};
int test;
memcpy(&test, &ip_ring[n], sizeof(unsigned int));
struct in_addr dst_addr;
dst_addr.s_addr = test;
char *dot_dst_ip = inet_ntoa(dst_addr);
ip4map[dot_dst_ip]++;
begin = n;
}
but i did not used //IP4 ip={0}; i am still trying to understand what we do , so is that make sense ?
that made every thing more complicated.no, the problem is that shared memory only contains data. it is not a c++ object and therefore any call to member function crashes with segmentation fault.
so we need to make the incrementIp and synchronizeIps independent of the c++ object. one way is to making them a static member. another way is to making them global functions.
the unsigned int for the ip4 is ok. an int is 4 byte and IP4 struct exactly stores 4 contiguous bytes each from 0 to 255 as ip4 amd comverts them from string.
#include <pcap.h>
#include <pfring.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <byteswap.h>
#include <unistd.h>
#include <map>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
struct IP4
{
unsigned char ip4[4];
IP4(const char * szip = "0.0.0.0")
{
const char * psz = &szip[0]; int n = 4;
*((unsigned int *)&ip4[0]) = 0;
do
{
ip4[--n] = (unsigned char)atoi(psz);
psz = (const char*)strchr(psz, '.');
}
while (n > 0 && NULL != psz++);
}
friend bool operator<(const IP4 & ip1, const IP4 & ip2) { return *((unsigned int *)&ip1.ip4[0]) < *((unsigned int *)&ip2.ip4[0]); }
operator std::string()
{
std::ostringstream oss;
oss << (int)ip4[3] << '.' << (int)ip4[2] << '.' << (int)ip4[1] << '.' << (int)ip4[0];
return oss.str();
}
operator unsigned int() { return *((unsigned int*)&ip[0]); } // cast the pointer to low byte to unsigned int }
};
struct SharedData
{
bool done;
pthread_mutex_t mutex;
unsigned int ip_ring[100];
int begin;
int end;
void shared_data() { memset(this, 0, sizeof(SharedData));}
};
static SharedData * data = NULL;
void initialise_shared()
{
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED | MAP_ANONYMOUS;
//size_t abc =(size_t) malloc(sizeof(SharedData));
data = (SharedData *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);
data->done = false;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&data->mutex, &attr);
}
// -std=c++11 ile derlenmesi gerekiyor
#define MAXBYTES2CAPTURE 100
#define DEFAULT_DEVICE "p1p2"
#define DEFAULT_RATE 100
void incrementIp(unsigned int ip4)
{
pthread_mutex_lock(&data->mutex);
if ((data->end+1)%100 == data->begin)
{
pthread_mutex_unlock(&data->mutex);
usleep(500000);
incrementIp(ip4);
return;
}
else
{
data->ip_ring[data->end] = ip4;
data->end = (++data->end)%100;
}
pthread_mutex_unlock(&data->mutex);
}
void synchronizeIps(std::map<IP4, int> & ip4map)
{
pthread_mutex_lock(&data->mutex);
for (int n = data->begin; n != (data->end+1)%100; n = (n+1)%100)
{
IP4 ip;
// copy 4 bytes
memcpy(&ip.ip4[0], &data->ip_ring[n], sizeof(unsigned int));
ip4map[ip]++;
data->begin = n;
}
pthread_mutex_unlock(&data->mutex);
}
void processRingPacket(const struct pfring_pkthdr* pkthdr, const u_char* packet, const u_char *arg)
{
static std::map<IP4, int> ip4map:
memset((void*)&pkthdr->extended_hdr.parsed_pkt, 0, sizeof(pkthdr->extended_hdr.parsed_pkt));
pfring_parse_pkt((u_char*)packet, (struct pfring_pkthdr*)pkthdr, 4, 1, 0);
struct in_addr dst_addr;
dst_addr.s_addr = __bswap_32(pkthdr->extended_hdr.parsed_pkt.ip_dst.v4);
char *dot_dst_ip = inet_ntoa(dst_addr);
IP4 ip = dot_dst_ip;
ip4map[ip]++;
// we cast the IP4 to unsigned int
data->incrementIp((unsigned int)ip);
int num_entries = ip4map[dot_dst_ip];
printf("%s processRingPacket counter: %d \n" ,dot_dst_ip, num_entries );
}
void child()
{
static std::map<IP4, int> ip4map:
int j = 0;
synchronizeIps(ip4map);
std::map<IP4, int>::iterator it;
for (it = mapip4.begin(); j < 5000; ++j)
{
int num_entries = ip4map.size();
printf("%d Child counter \n",num_entries);
usleep(500000);
}
}
void printHelp(void) {
printf("SPDNet Anomality Detection Software \n\n");
printf("-h Yardım Menusu\n");
printf("-i <örn: eth0> Çıkış portunuzu seçiniz\n");
}
int main(int argc, char* argv[])
{
initialise_shared();
char *device = NULL, c;
int rate;
while((c = getopt(argc,argv,"hi")) != '?') {
if((c == 255) || (c == -1)) break;
switch(c) {
case 'h':
printHelp();
return(0);
break;
case 'i':
device = strdup(optarg);
break;
case 'r':
//rate = atoi(optarg); //Burası bozuyor incele
break;
}
}
printf(device);
if(device == NULL) device = DEFAULT_DEVICE;
if(rate == NULL) rate = DEFAULT_RATE;
pid_t pid = fork();
if (pid == 0)
{
int count = 0;
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_set_sampling_rate(ring, rate) ;
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&count, 1);
return 0;
}
else if (pid > 0)
{
child();
}
}
Open in new window
and and instead of calling child put the code of child into main function directly.
if that doesn't help you may restore the child function but pass the map (defined in main) by reference
Open in new window
and call child withOpen in new window
Sara