Inotify et /proc/net/tcp ?

Hello

J’essaye de d’obtenir une notification du modification du fichier /proc/net/tcp avec inotify

mai sa ne marche pas malgrer le code que voici en c++ (ça compile)
sauf si vous faite un simple

je vous met les 3 fichier

#include <iostream>
#include <string>
#include "cNotify.hpp"

int main()
{
	cNotify cN;
	std::cout << "Start notify tcp" << std::endl;
	int buff = cN.start_notify("/proc/net/tcp");
	std::cout << "End notify valeur:" << buff << std::endl;
	return 0;
}
#ifndef DEF_ME_NOTIFY
#define DEF_ME_NOTIFY
#include <iostream>
#include <sys/select.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
class cNotify
{
	public:
		cNotify();
		//renvoie 0 si tout ce termine normalment -1 si erreur
		// 1 si le changement a été detecter et s'arrete.
		int start_notify(const std::string & my_path);
	private:
		/* 
		 *Prise en charge du code C . comme c est priver on peux 
		 *changer facilment sans mofier l'application parente,
		 *sinon c est pas utile, utilise le code C directement est mieux
		 */
		int afficher_masque(int mask);
};
#endif 
#include "cNotify.hpp"
cNotify::cNotify(){}

//int fd, wd;


int cNotify::afficher_masque(int mask)
{
    if (mask & IN_CREATE)			{ return 1; }
    else if (mask & IN_DELETE)		{ return 2; }
    else if (mask & IN_DELETE_SELF)	{ return 3; }
    else if (mask & IN_UNMOUNT)		{ return 4; }
    else if (mask & IN_MOVED_FROM)	{ return 5; }
    else if (mask & IN_MOVED_TO)	{ return 6; }
    else if (mask & IN_MOVE_SELF)	{ return 7; }
    else if (mask & IN_Q_OVERFLOW)	{ return 8; }
    else if (mask & IN_IGNORED)		{ return 9; }
	else if (mask & IN_MODIFY)		{ return 10; }
    else if (mask & IN_ATTRIB)		{ return 11; }
    else if (mask & IN_CLOSE)		{ return 12; }
    else if (mask & IN_OPEN)		{ return 13; }
    else if (mask & IN_ISDIR)		{ return 14; }
    else if (mask & IN_ACCESS)		{ return 15; }
    else { return -1; }
}


int cNotify::start_notify(const std::string & my_path)
{
	size_t r;
    fd_set fds;
    char buffer[8192];
    struct inotify_event *event;
    int fd, wd;
    int change=0;

    /* Initialisation d'inotify */
    fd = inotify_init();

    if (fd < 0) {
        perror("inotify_init");
        return -1;
    }

    /* Surveillance du fichier/répertoire passé en paramètre
     * On accepte tous les évènements possibles */
    wd = inotify_add_watch(fd, my_path.c_str(), IN_ALL_EVENTS);
    if (wd < 0) {
        perror("inotify_add_watch");
       return -1;
    }

    while (1) {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        if (select(fd + 1, &fds, NULL, NULL, 0) <= 0) {
            continue;
        }

        /* Obtention des informations sur l'évènement qui vient de se produire */

        r = read(fd, buffer, sizeof(buffer));
        if (r <= 0) {
            perror("read");
       return -1;
        }
        event = (struct inotify_event *) buffer;
        change=afficher_masque(event->mask);
        //if ((change == 12) || (change == 10) || (change == 15))
        if ((change > 0) && (change < 15)) //adapter le teste a vos besoins etc.
        {
            inotify_rm_watch(fd, wd);
            close(fd);
			return 1;
		}
		else
		{
			std::cout << "Notify valeur en dehord de la plage" << change << std::endl;
		}
    }
           inotify_rm_watch(fd, wd);
           close(fd);
           return 0; 

donc est-ce possible d’avoir autre chose qu’une boucle qui va lire systématiquement dans /proc/net/tcp toute les x secondes ? car la les disque ssd vont pas apprécier :frowning: sans parler de la charge cpu.

aux pire je peux loguer la sortie d’iptable et utiliser inotify dessu … mai bon sa va poser souci aux moment le paquet arrive . le premier sera dropper. a partir de la je peux aller re-lire le fichier /proc/net/tcp mai sa reste pas propre :\

Merci d’avance

J’ai pas regardé la doc d’inotify mais je suis à peut près sur que tu ne peux pas t’en servir sur procfs ni sur sysfs. Ce sont des systèmes de fichiers virtuels et le contenu des fichiers virtuel qu’ils contiennent sont générer au moment de la lecture. Donc il n’y a pas d’évènement inotify (tout du moins il n’y a pas ceux que tu attends).

Donc si tu veux passer par ces systèmes de fichiers, tu pas le choix tu doit faire du polling (le fait d’avoir une boucle d’attente).

Avec netfilter tu peut créer une règle qui va appeler du code au moment que tu souhaite (tu as tout le loisir d’utiliser les conditions classiques de nf). Tu peut même avec ce code accepter ou refuser le paquet (je ne sais pas ce que tu veux faire). Si tu veux passer par du log un paquet peut générer un log sans être dropé.

Pour appeler du code à partir de règles netfilter, il faut chercher les nfqueue (le linuxmag hs n°41 était pas mal pour ça : rendre un service accessible uniquement en cas de beau temps annoncé à la météo).

[quote=“MisterFreez”]J’ai pas regardé la doc d’inotify mais je suis à peut près sur que tu ne peux pas t’en servir sur procfs ni sur sysfs. Ce sont des systèmes de fichiers virtuels et le contenu des fichiers virtuel qu’ils contiennent sont générer au moment de la lecture. Donc il n’y a pas d’évènement inotify (tout du moins il n’y a pas ceux que tu attends).

Donc si tu veux passer par ces systèmes de fichiers, tu pas le choix tu doit faire du polling (le fait d’avoir une boucle d’attente).

Avec netfilter tu peut créer une règle qui va appeler du code au moment que tu souhaite (tu as tout le loisir d’utiliser les conditions classiques de nf). Tu peut même avec ce code accepter ou refuser le paquet (je ne sais pas ce que tu veux faire). Si tu veux passer par du log un paquet peut générer un log sans être dropé.

Pour appeler du code à partir de règles netfilter, il faut chercher les nfqueue (le linuxmag hs n°41 était pas mal pour ça : rendre un service accessible uniquement en cas de beau temps annoncé à la météo).[/quote]
Merci pour les information et la piste

nfqueue , je cherche effectivement a avoir quelque chose de ce type.

voila le lien que j’ai trouver et commencer a lire. :doh:
unixgarden.com/index.php/gnu … plications

bon j’ai trouver un peux de doc ,
Mai petit souci :
la doc netfilter.org/projects/libnetfil … ource.html l’ip source / destination /port n’est pas disponible ou c’est moi ??
j’ai pas trouve de man sur ce type d’information.

voici le code que j’ai trouver avec google:

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2007 Joe Kopena, Drexel University
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors: Joe Kopena <tjkopena@cs.drexel.edu>
 */

#include <iostream>
#include <iomanip>

#include <time.h>

#include <netinet/in.h>
extern "C" {
//#include <libipq.h>
  #include <linux/netfilter.h>  /* Defines verdicts (NF_ACCEPT, etc) */
  #include <libnetfilter_queue/libnetfilter_queue.h>
}

using namespace std;

//----------------------------------------------------------------------
//------------------------------------------------------
static int Callback(nfq_q_handle *myQueue, struct nfgenmsg *msg,
                    nfq_data *pkt, void *cbData) {
  uint32_t id = 0;
  nfqnl_msg_packet_hdr *header;

  cout << "pkt recvd: ";
  if ((header = nfq_get_msg_packet_hdr(pkt))) {
    id = ntohl(header->packet_id);
    cout << "id " << id << "; hw_protocol " << setfill('0') << setw(4) <<
      hex << ntohs(header->hw_protocol) << "; hook " << ('0'+header->hook)
         << " ; ";
  }

  // The HW address is only fetchable at certain hook points
  nfqnl_msg_packet_hw *macAddr = nfq_get_packet_hw(pkt);
  if (macAddr) {
    cout << "mac len " << ntohs(macAddr->hw_addrlen) << " addr ";
    for (int i = 0; i < 8; i++) {
      cout << setfill('0') << setw(2) << hex << macAddr->hw_addr;
    }
    // end if macAddr
  } else {
    cout << "no MAC addr";
  }

  timeval tv;
  if (!nfq_get_timestamp(pkt, &tv)) {
    cout << "; tstamp " << tv.tv_sec << "." << tv.tv_usec;
  } else {
    cout << "; no tstamp";
  }

  cout << "; mark " << nfq_get_nfmark(pkt);

  // Note that you can also get the physical devices
  cout << "; indev " << nfq_get_indev(pkt);
  cout << "; outdev " << nfq_get_outdev(pkt);

  cout << endl;

  // Print the payload; in copy meta mode, only headers will be included;
  // in copy packet mode, whole packet will be returned.
  char *pktData;
  int len = nfq_get_payload(pkt, &pktData);
  if (len) {
    cout << "data[" << len << "]: '";
    for (int i = 0; i < len; i++) {
      if (isprint(pktData[i]))
        cout << pktData[i];
      else cout << " ";
    }
    cout << "'" << endl;
    // end data found
  }
cout << "Debug" << endl;
  // For this program we'll always accept the packet...
  return nfq_set_verdict(myQueue, id, NF_ACCEPT, 0, NULL);

  // end Callback
}

//----------------------------------------------------------------------
//------------------------------------------------------
int main(int argc, char **argv) {
  struct nfq_handle *nfqHandle;

  struct nfq_q_handle *myQueue;
  struct nfnl_handle *netlinkHandle;

  int fd, res;
  char buf[4096];

  // Get a queue connection handle from the module
  if (!(nfqHandle = nfq_open())) {
    cerr << "Error in nfq_open()" << endl;
    //exit(-1);
  }

  // Unbind the handler from processing any IP packets
  // Not totally sure why this is done, or if it's necessary...
  if (nfq_unbind_pf(nfqHandle, AF_INET) < 0) {
    cerr << "Error in nfq_unbind_pf()" << endl;
    //exit(1);
  }

  // Bind this handler to process IP packets...
  if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
    cerr << "Error in nfq_bind_pf()" << endl;
    //exit(1);
  }

  // Install a callback on queue 0
  if (!(myQueue = nfq_create_queue(nfqHandle,  0, &Callback, NULL))) {
    cerr << "Error in nfq_create_queue()" << endl;
    //exit(1);
  }

  // Turn on packet copy mode
  if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
    cerr << "Could not set packet copy mode" << endl;
    //exit(1);
  }

  netlinkHandle = nfq_nfnlh(nfqHandle);
  fd = nfnl_fd(netlinkHandle);
  nfnl_fd;
  while ((res = recv(fd, buf, sizeof(buf), 0)) && res >= 0) {
    // I am not totally sure why a callback mechanism is used
    // rather than just handling it directly here, but that
    // seems to be the convention...
    nfq_handle_packet(nfqHandle, buf, res);
    // end while receiving traffic
  }

  nfq_destroy_queue(myQueue);

  nfq_close(nfqHandle);
std::cout << "terminer ?" << std::endl;
  return 0;

  // end main
}

compiler avec le makefile.

SRC=$(wildcard *.cpp)
#SRC=main.cpp
OBJ=${SRC:.cpp=.o}
OUT=main

CXX=c++
CXXFLAGS=-Wall -Wextra -pedantic -lnfnetlink -lnetfilter_queue
#CXXFLAGS=-lsqlite3 -Wall -Wextra -pedantic -static


all: $(OUT)

$(OUT): $(OBJ)
	$(CXX) $^ -o $@ $(CXXFLAGS)

.cpp.o:

exe: all
	./$(OUT) "sqlite3.sql"

clean:
	@rm -v *.o
	true

mrproper: clean
	@rm $(OUT)

il faut que les paquet soit installer

libnetfilter-queue-dev
//peut etre :
libpq-dev

voila
pour utilise ce code (attention root mode…)

iptables -A OUTPUT -p icmp -j NFQUEUE --queue-num 0 

ensuite un simple ./main
puis un ping quelque part donne des resulta (pas terrible pour le moment) mai je trouve pas comment avoir l’ip et le port dans la doc citée plus haut, c’est peut être avec autre chose ???
merci d’avance et merci a l’auteur de l’exemple :slightly_smiling: