/* darkyhopper.c - simple channel hopper
 *
 * I made this in about 15 minutes from iwconfig.c.  Requires libiw.
 * Compile like: gcc darkyhopper.c -o darkyhopper -liw
 * Use like: ./darkyhopper eth1
 *
 * There are likely much better hoppers out there, at least WRT
 * configurability.  This hopper cycles through all US channels (1-11)
 * changing channels every 0.5 seconds.  I tested this with a Cisco 350
 * PCMCIA card in Red Hat Linux 9, RH kernel 2.4.20-20 (with a few
 * unrelated -- I hope -- patches).
 *
 * 2003-09-20, darkness <darkness@codefu.org>
 */

/*
 *	Wireless Tools
 *
 *		Jean II - HPLB 97->99 - HPL 99->01
 *
 * Main code for "iwconfig". This is the generic tool for most
 * manipulations...
 * You need to link this code against "iwlib.c" and "-lm".
 *
 * This file is released under the GPL license.
 *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
 */

#include "iwlib.h"		/* Header */

/************************* SETTING ROUTINES **************************/

/*------------------------------------------------------------------*/
/*
 * Macro to handle errors when setting WE
 * Print a nice error message and exit...
 * We define them as macro so that "return" do the right thing.
 * The "do {...} while(0)" is a standard trick
 */
#define ERR_SET_EXT(rname, request) \
	fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
		rname, request)

/*------------------------------------------------------------------*/
/*
 * Wrapper to push some Wireless Parameter in the driver
 * Use standard wrapper and add pretty error message if fail...
 */
#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
	do { \
	if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
		ERR_SET_EXT(rname, request); \
		fprintf(stderr, "    SET failed on device %-1.8s ; %s.\n", \
			ifname, strerror(errno)); \
		return(-5); \
	} } while(0)

/******************************* MAIN ********************************/

/*------------------------------------------------------------------*/
/*
 * The main !
 */
int
main(int	argc,
     char **	argv)
{
  int skfd;		/* generic raw socket desc.	*/

  /* Create a channel to the NET kernel. */
  if((skfd = iw_sockets_open()) < 0)
    {
      perror("socket");
      exit(-1);
    }

  if (argc != 2)
    {
      fprintf(stderr, "Need to specify name of device to hop on\n");
			exit (1);
    }
  else
    {
			struct iwreq wrq;

			wrq.u.freq.m = 1;
			wrq.u.freq.e = 0;

			for (;;) {
			  IW_SET_EXT_ERR(skfd, argv[1], SIOCSIWFREQ, &wrq, "Set frequency");
				if (++wrq.u.freq.m > 11)
				  wrq.u.freq.m = 1;
				usleep(500000);
			}
		}

  /* It doesn't seem very likely we'll ever get here.  --darky */
  /* Close the socket. */
  close(skfd);

	return 1;
}
