#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/* Ziel (und Quelle) ist localhost */
#define DEST "127.0.0.1"

int main(void)
  {
  int s;                     /* Sockethandle */
  struct sockaddr_in daddr;  /* IP-Adresse */
  char packet[50];           /* Datenpaket-Puffer */

  /* Der IP-Header zeigt auf den Pufferanfang 
     (ueberlagert den Puffer)                  */
  struct iphdr *ip = (struct iphdr *)packet;  

  /* RAW-Socket kreieren */
  s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (s == -1)
    {
    perror("socket() ging schief");
    if (errno == EACCES) printf(" (EACCES)\n");
    if (errno == EAFNOSUPPORT) printf(" (EAFNOSUPPORT)\n");
    return 1;
    }

  /* IP-Adresse etc. eintragen, Port wird bei SOCK_RAW nicht gebraucht */
  daddr.sin_family = AF_INET;
  daddr.sin_port = 0;
  /* IP-Adresse (String) in 32-Bit-Binaerwert umwandeln */
  inet_pton(AF_INET, DEST, (struct in_addr *)&daddr.sin_addr.s_addr);
  /* Struktur mit Nullen fuellen */
  memset(daddr.sin_zero, 0, sizeof(daddr.sin_zero));
  /* Puffer loeschen */
  memset(packet, 0, sizeof(packet));

  /* Nachricht als Nutzdaten in den Puffer schreiben, 
     aber hinter(!) den IP-Header                       */
  strcpy(packet + sizeof(struct iphdr),"Here comes the Evil!");
  
  /* IP-Header zusammenbauen */
  ip->ihl = 5;                            /* Headerlaenge, 5 x 32 Bit */
  ip->version = 4;                        /* IP-Version 4 */
  ip->tos = 0;                            /* Type of Service */
  ip->tot_len = htons(40);                /* 16-Byte-Wert */
  ip->frag_off = 0;                       /* keine Fragmentierung */
  ip->ttl = 64;                           /* default */
  ip->protocol = IPPROTO_RAW;             /* Protocol auf Layer 4 */
  ip->check = 0;                          /* wird autom. berechnet */
  ip->saddr = daddr.sin_addr.s_addr;      /* Quell-Adresse */
  ip->daddr = daddr.sin_addr.s_addr;      /* Ziel-Adresse */

  /* Nachricht senden */
  while(1) 
    {
    sleep(1);
    if (sendto(s,                         /* Socket */
               (char *)packet,            /* Datenpuffer */
               sizeof(packet),            /* Laenge Datenpuffer */
               0,                         /* routing flags, in der Regel 0 */
               (struct sockaddr *)&daddr, /* Ziel-IP-Adresse */
               (socklen_t)sizeof(daddr)   /* Laenge Ziel-IP-Adresse */
               ) < 0)
      perror("packet send error:");
    }
  exit(0);
  }
