IPFW + Divert and multicast IPv6

Julien DHERSIN dhersin at gmail.com
Wed Apr 11 12:42:14 UTC 2007


Hi,

I would like to know if anyone has already tried to divert multicast
IPv6 packets and to reinject them in the IPv6 stack ?
The idea is to filter the multicast IPv6 packets (UDP:54321) according
to the option data in the header.

My IPFW script is quite short :
#!/bin/sh
/sbin/ipfw -q flush
/sbin/ipfw add divert 1234 udp from any to any 54321

I found the following code in a mini howto but it is not working :

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_var.h>
#include <arpa/inet.h>

#ifdef IPSEC
#include <netinet6/ipsec.h>
#endif /*IPSEC*/

#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <math.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <unistd.h>


#define BUFSIZE 65535

int
main(int argc, char **argv)
{
  int                 fd,
                      rawfd,
                      fdfw,
                      ret,
                      n;
  int                 on = 1;
  struct sockaddr_in6 bindPort, sin;
  int                 sinlen;
  int                 port_nb;
  struct              ip6_hdr *hdr;
  unsigned char       packet[BUFSIZE];
  struct in6_addr     addr;
  int                 i,
                      direction;
  struct ip_mreq      mreq;

  if (argc != 2)
  {
    fprintf(stderr, "Usage: %s <port number>\n", argv[0]);
    exit(1);
  }
  bindPort.sin6_family = AF_INET6;
  bindPort.sin6_port = htons(atol(argv[1]));
  bindPort.sin6_addr = in6addr_any;


  fprintf(stderr, "%s:Creating a socket\n", argv[0]);
  /* open a divert socket */
  fd = socket(AF_INET6, SOCK_RAW, IPPROTO_DIVERT);

  if (fd == -1)
  {
    fprintf(stderr, "%s:We could not open a divert socket\n", argv[0]);
    exit(1);
  }

  fprintf(stderr, "%s:Binding a socket\n", argv[0]);
  ret = bind(fd, (struct sockaddr6*)&bindPort, sizeof(struct sockaddr_in6));

  if (ret != 0)
  {
    close(fd);
    fprintf(stderr, "%s: Error bind(): %s", argv[0], strerror(ret));
    exit(2);
  }
  printf("%s: Waiting for data...\n", argv[0]);
  /* read data in */
  sinlen = sizeof(struct sockaddr_in);
  while (1)
  {
    n = recvfrom(fd, packet, BUFSIZE, 0, (struct sockaddr6*)&sin, &sinlen);
    hdr = (struct ip6_hdr *) packet;

    printf("%s: The packet looks like this:\n", argv[0]);
    for (i = 0; i < 80; i++)
    {
      printf("%02x ", (int)*(packet + i));
      if (!((i + 1) % 16))
        printf("\n");
    };
    printf("\n");

    printf("%s Reinjecting DIVERT %i bytes\n", argv[0], n);
    n=sendto(fd, packet, n ,0, &sin, sinlen);
    printf("%s: %i bytes reinjected.\n", argv[0], n);

    if (n<=0)
      printf("%s: Oops: errno = %i\n", argv[0], errno);
  }
}

Thanks for your help.

Regards,
Julien


More information about the freebsd-ipfw mailing list