Link to home
Start Free TrialLog in
Avatar of FireBall
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 ?

	void child(){
		int j = 0;
		for (; j < 5000; ++j)
		{
		    int num_entries = ip4map.size();
		    printf("%d   \n",num_entries);
			usleep(500000);
	            
		}
	}

Open in new window


	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;

Open in new window

Avatar of sarabande
sarabande
Flag of Luxembourg image

first you may try to move definition of map ip4map into main function.

int main(int nargs, char * szargs[])
{
      std::map<IP4, int> ip4map;

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

void child(std::map<IP4, int> & ip4map)
{
      ....
}

Open in new window

and call child with

 
child(ip4map)

Open in new window


Sara
Avatar of FireBall
FireBall

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

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;
              ^

Open in new window

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  

Open in new window

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 ?

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  

Open in new window




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 

Open in new window



but fork process counting 0  when there is no change :) i am really shocked now
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.

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  

Open in new window

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
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes i tryed :

		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);
	    }

Open in new window



	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);
	            
		}
	}

Open in new window



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 

Open in new window

oh i missed the following code:

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);

Open in new window


they moved the data to shared memory and that is why it worked.

Sara
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 ..

Open in new window

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
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);

Open in new window

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
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.
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
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);
}

Open in new window


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);

Open in new window


after you incremented an ip in parent you would call
data->incrementIp(*(unsigned int*)&IP4("192.1.185.9").ip4[0]);

Open in new window


i hope it compiles because i cannot test it.

Sara
and struct IP4 must be defined above Shared_Data.

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
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]++:      
	        }
	    }
	    
	}
};

Open in new window



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
  }
  ^

Open in new window

ok i've correct the problem it is about {  end of this line       SharedData() { memset(this, 0, sizeof(SharedData));
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]++:   
                    ^

Open in new window




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]++:			
		}
	}
};

Open in new window

the constructor
SharedData() { memset(this, 0, sizeof(SharedData));

Open in new window


must end with }

class SharedData
{
       //--------------------------------------------------v
       SharedData() { memset(this, 0, sizeof(SharedData)); }

Open in new window


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

IP4(const char * szip = "0.0.0.0")
{
     ....
}

Open in new window


now IP4 has a default constructor. do the same with struct IP4TTL but also usttl = 0 .

Sara
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 :


dinleyici.c:84:8: error: ‘shared_data’ does not name a type
 static shared_data* data = NULL;

Open in new window

static shared_data* data = NULL;

should be

Shared_Data * data = NULL;

Open in new window


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
		}
	}

Open in new window


Sara
all the errors still about data variable. this is not solved :

Shared_Data * data = NULL;

Open in new window



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]);

Open in new window

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 :

dinleyici.c:86:61: error: invalid conversion from ‘void*’ to ‘SharedData*’ [-fpermissive]
     data = mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);

Open in new window



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;

Open in new window

try

data = (Shared_Data *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);

Open in new window


Sara
c++ needs an explicit cast while c is happy with a void pointer.

Sara
it is SharedData not Shared_Data.
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

data = (SharedData *)mmap(NULL, sizeof(SharedData), prot, flags, -1, 0);

Open in new window


that is an explicit cast from void* to SharedData*.

Sara
yes :)

but                   data->synchronizeIps(ip4map);
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 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.
static std::map<IP4, int> ip4map;
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;		
		}

Open in new window



when i remove this lines it is ok but of course not sync this time
I' ve removed from the global and put into the functions , still segmentation fault is going on on the same place
did you try

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
     ...

Open in new window


and

void Child()
{
      static std::map<IP4, int> ip4map;
      data->SynchronizeIps();
      ....

Open in new window


Sara
yes result is same
you can try to make the functions IncrementIp and SynchronizeIps static functions of struct SharedData

	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;		
		}
	}

Open in new window


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 SharedData * data = NULL;

Open in new window


data can not be used in the SharedData function because it must be declared already after the SharedData
#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();
			}
		
	}
	

Open in new window

move the implementation of the static functions below the definition of data.

....
           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;		
		}
	}

Open in new window


and in the struct SharedData only declare the functions:

	static void incrementIp(unsigned int ip4);
	static void synchronizeIps(std::map<IP4, int> & ip4map);

Open in new window


Sara
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();
			}
		
	}
	

Open in new window

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;		
		}

Open in new window

I think the error is about that line :                   IP4 ip = { 0 };
ok i think all the problem is about increment adding

            data->incrementIp(*(unsigned 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


		
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);

	}
};

Open in new window



 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

Open in new window

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

		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;		
		}

Open in new window



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