Listening for queued packets over netlink

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I wrote a small dumb program that listens for packet messages from ip_queue module. But the program is not working as I expect it to work. It receives an infinite flow of trash packets from kernel. Please help! I need a clue. The program text is below.

#include <asm/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_queue.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <signal.h>

static int done = 0;

void sigint(int signum)
{
   done = 1;
}

int main(int argc, char *argv[])
{
   int fd;
   struct sockaddr_nl a;
   size_t alen;
   struct sockaddr_nl ra;
   size_t ralen;
   struct nlmsghdr *h;
   struct ipq_mode_msg *m;
   struct ipq_packet_msg *p;
   struct ipq_verdict_msg *v;
   char dbuf[20];
   unsigned char obuf[128];
   unsigned char ibuf[128];
   size_t nsent, nrecv;
   int seq = 0;

   /* Create the socket */
   fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_FIREWALL);
   if (fd == -1) {
      perror("socket");
      return EXIT_FAILURE;
   }

/* Bind local end of the socket to the pid of current process */
memset(&a, 0, sizeof(struct sockaddr_nl));
a.nl_family = AF_NETLINK;
a.nl_pid = getpid();
a.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&a, sizeof(struct sockaddr_nl)) == -1) {
perror("bind");
return EXIT_FAILURE;
}


   /* Remote end of the socket is in kernel */
   memset(&a, 0, sizeof(struct sockaddr_nl));
   a.nl_family = AF_NETLINK;
   a.nl_pid = 0;
   a.nl_groups = 0;

   /* Send a mode message to register for packet messages */
   h = (struct nlmsghdr *)obuf;
   h->nlmsg_type = IPQM_MODE;
   h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_mode_msg));
   h->nlmsg_flags = 0; /* NLM_F_REQUEST; */
   h->nlmsg_pid = getpid();
   h->nlmsg_seq = seq++;

   m = NLMSG_DATA(h);
   m->value = IPQ_COPY_META;
   m->range = 0;

   nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0,
           (struct sockaddr *)&a, sizeof(struct sockaddr_nl));
   if (nsent == -1) {
      perror("sendto(IPQM_MODE)");
      return EXIT_FAILURE;
   }

   /* we're ready to filter packets */
   signal(SIGINT, sigint);
   while (!done) {
      alen = sizeof(struct sockaddr_nl);
      nrecv = recvfrom(fd, (void *)ibuf, 128, 0,
              (struct sockaddr *)&ra, &ralen);
      if (nrecv == -1) {
         perror("recvfrom(IPQM_PACKET)");
         done = 1;
         continue;
      }

      h = (struct nlmsghdr *)ibuf;
      p = NLMSG_DATA(h);

strftime(dbuf, 20, "%Y-%m-%d %H:%M:%S", localtime(&p->timestamp_sec));
printf(
"-----\n"
"remote_pid: %d\n"
"packet_id: %lu\n"
"mark: %lu\n"
"timestamp: %s.%06ld\n"
"hook: %u\n"
"indev: %s\n"
"outdev: %s\n"
"hw_protocol: %u\n"
"hw_type: %u\n"
"hw_addrlen: %u\n"
"hw_addr: %s\n"
"data_len: %u\n",
ra.nl_pid,
p->packet_id, p->mark,
dbuf, p->timestamp_usec,
p->hook, p->indev_name, p->outdev_name,
p->hw_protocol, p->hw_type, p->hw_addrlen, (char *)NULL,
p->data_len);


      /* Sent ACCEPT verdict message */
      h = (struct nlmsghdr *)obuf;
      h->nlmsg_type = IPQM_VERDICT;
      h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_verdict_msg));
      h->nlmsg_flags = 0; /*NLM_F_REQUEST;*/
      h->nlmsg_pid = getpid();
      h->nlmsg_seq = seq++;

      v = (struct ipq_verdict_msg *)NLMSG_DATA(h);
      v->value = NF_ACCEPT;
      v->id = p->packet_id;

      nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0,
              (struct sockaddr *)&a, sizeof(struct sockaddr_nl));
      if (nsent == -1) {
         perror("sendto(IPQM_VERDICT)");
         done = 1;
         continue;
      }
   }

   /* Send a mode message to unregister from packet messages */
   h = (struct nlmsghdr *)obuf;
   h->nlmsg_type = IPQM_MODE;
   h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_mode_msg));
   h->nlmsg_flags = NLM_F_REQUEST;
   h->nlmsg_pid = getpid();
   h->nlmsg_seq = seq++;

   m = NLMSG_DATA(h);
   m->value = IPQ_COPY_NONE;
   m->range = 0;

   nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0,
           (struct sockaddr *)&a, sizeof(struct sockaddr_nl));
   if (nsent == -1) {
      perror("sendto(IPQM_MODE)");
      return EXIT_FAILURE;
   }

   close(fd);

   return 0;
}



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux