
/* promisc.c */

/* Andrew Davison (ad@ratree.psu.ac.th) May 1998 */

/* Check whether any interfaces have their promiscuous flag set.
   The -off options tries to switch them off, but any changes
   require super-user status on Linux

   Usage:
      promisc [-off]
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <net/if.h>

#define CONFSIZE 1024        /* size of configuration array */

int main(int argc, char *argv[]) 
{
  int sd, turnoff;
  struct ifconf config;           /* interface configuration info */
  struct ifreq ireq, *ifr;        /* interface request details */
  char *reqp, *end_req;

  turnoff = 0;
  if (argc == 2) {
    if (strcmp(argv[1], "-off") == 0) {
      turnoff = 1;
      printf("turnoff flag set\n");
    }
    else  {
      fprintf(stderr, "Usage: promisc [-off]\n");
      printf("turnoff flag not set\n");
    }
  }

  if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    fprintf(stderr, "Error while establishing a socket\n");
    exit(1);
  }

  /* initialise configuration info */
  config.ifc_len = CONFSIZE;
  config.ifc_buf = (char *) malloc(sizeof(char)*CONFSIZE);
  if (ioctl(sd, SIOCGIFCONF, &config) < 0) {  /* get interface configuration */
    perror("SIOCGIFCONF");
    exit(1);
  }

  end_req = config.ifc_buf + config.ifc_len;  
                           /* pointer to end of interface config array */
  reqp = config.ifc_buf;   /* pointer to start of array */

  /* move through the interface config array, testing each interface */
  while (reqp < end_req) {
    ifr = (struct ifreq *)reqp;         /* start examining an interface */
    ireq = *ifr;
    if (ioctl(sd, SIOCGIFFLAGS, &ireq) < 0) {
      fprintf(stderr, "Cannot read the interface flags for %s\n", 
                                                     ifr->ifr_name);
      continue;            /* skip this interface */
    }
    printf("%s: ", ifr->ifr_name);       /* print interface name */
    if ((ireq.ifr_flags & IFF_PROMISC) != 0) {
      if (turnoff) {
        printf("Promiscuous mode is ON... switching off\n");
        ireq.ifr_flags &= ~(IFF_PROMISC);                  /* switch off */
        if (ioctl(sd, SIOCSIFFLAGS, &ireq) < 0 )           /* set flags */
          fprintf(stderr, "Cannot switch off promiscuous mode flag");
      }
      else
        printf("Promiscuous mode is ON\n");
    }
    else
      printf("Promiscuous mode is OFF\n");

    reqp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr);
             /* move pointer to next array element (next interface) */
  }

  close(sd);
  return 0;
}


