"Fossies" - the Fresh Open Source Software Archive

Member "chkrootkit-0.55/ifpromisc.c" (9 May 2021, 9023 Bytes) of package /linux/misc/chkrootkit-0.55.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ifpromisc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.54_vs_0.55.

    1 /*
    2    ifpromisc - This is a simple subset of Fred N. van Kempen,
    3                <waltje@uwalt.nl.mugnet.org>'s ifconfig and iplink code.
    4                Show state of all ethernet interfaces
    5                xxx is PROMISC
    6                or
    7                xxx is not promisc
    8 
    9    Version: @(#)ifpromisc.c 0.8 2003/11/30
   10         @(#)ifpromisc.c 0.7 2003/06/07
   11    Last Changes: Better detection of promisc mode on newer Linux kernels
   12                  Lantz Moore <lmoore@tump.com>
   13                  Fix for newer linux kernels, minor fixes
   14              Nelson Murilo, <nelson@pangeia.com.br>
   15                  Ports for Solaris
   16                  Andre Gustavo <gustavo@anita.visualnet.com.br>
   17                  Port for OpenBSD
   18              Nelson Murilo, <nelson@pangeia.com.br>
   19                  Fix wrong output (patched by Sean MacLennan) 
   20 
   21    Author:  Nelson Murilo, <nelson@pangeia.com.br>
   22         Copyright 1997-2021 (C) Pangeia Informatica
   23 
   24         This program is free software; you can redistribute it
   25         and/or  modify it under  the terms of  the GNU General
   26         Public  License as  published  by  the  Free  Software
   27         Foundation;  either  version 2 of the License, or  (at
   28         your option) any later version.
   29  */
   30 #include <sys/types.h>
   31 #include <sys/socket.h>
   32 #include <sys/ioctl.h>
   33 #ifdef __linux__
   34 #include <linux/if.h>
   35 #include <linux/if_arp.h>
   36 #include <linux/if_ether.h>
   37 #include <dirent.h>
   38 #include <sys/stat.h>
   39 #else
   40 #include <net/if.h>
   41 #ifndef __OpenBSD__
   42 #include <net/if_arp.h>
   43 #endif
   44 #endif
   45 #ifdef SOLARIS2
   46 #include <sys/sockio.h>
   47 #endif
   48 #include <stdio.h>
   49 #include <errno.h>
   50 #include <fcntl.h>
   51 #include <ctype.h>
   52 #include <stdlib.h>
   53 #include <string.h>
   54 #include <unistd.h>
   55 
   56 struct interface
   57 {
   58   char          name[IFNAMSIZ];     /* interface name   */
   59   short         type;           /* if type      */
   60   short         flags;          /* various flags    */
   61 #ifdef __linux__
   62   int           index;          /* interface index  */
   63 #endif
   64 };
   65 
   66 char *Release = "chkrootkit package",
   67      *Version = "@(#) ifpromisc 0.9 (2007/06/15)";
   68 //     *Version = "@(#) ifpromisc 0.8 (2003/11/30)";
   69 
   70 int skfd = -1;              /* AF_INET or AF_PACKET raw socket desc.    */
   71 int q = 0;                              /* Quiet mode on or off             */
   72 
   73 struct packet_info
   74 {
   75     int index;
   76     int type;
   77     int proto;
   78     int inode;
   79     char *cmd;
   80     struct packet_info *next;
   81 };
   82 
   83 #ifdef __linux__
   84 /*
   85  * the contents of /proc/net/packet
   86  */
   87 static struct packet_info *proc_net_packet = 0;
   88 
   89 /*
   90  * read the entries from /proc/net/packet
   91  */
   92 static void read_proc_net_packet()
   93 {
   94     FILE                *proc;
   95     char                buf[80];
   96 
   97     proc = fopen("/proc/net/packet", "r");
   98     if (!proc)
   99     {
  100         if (errno != ENOENT)
  101         {
  102             perror("opening /proc/net/packet");
  103         }
  104         return;
  105     }
  106 
  107     /* skip the header */
  108     fgets(buf, 80, proc);
  109     while (fgets(buf, 80, proc))
  110     {
  111         int             type = 0;
  112         unsigned int    proto = 0;
  113         int             index = 0;
  114         unsigned int    inode = 0;
  115 
  116         if (sscanf(buf, "%*p %*d %d %x   %d %*d %*u %*u %u",
  117                   &type, &proto, &index, &inode) == 4)
  118         {
  119             struct packet_info *pi;
  120 
  121             pi = (struct packet_info *)malloc(sizeof(struct packet_info));
  122             pi->type = type;
  123             pi->proto = proto;
  124             pi->index = index;
  125             pi->inode = inode;
  126             pi->cmd = 0;
  127 
  128             pi->next = proc_net_packet;
  129             proc_net_packet = pi;
  130         }
  131         else
  132         {
  133             fprintf(stderr, "cannot grok /proc/net/packet: %s", buf);
  134         }
  135     }
  136 
  137     fclose(proc);
  138 }
  139 
  140 /* look up an entry from /proc/net/packet by inode */
  141 static struct packet_info *find_packet_info(int inode)
  142 {
  143     struct packet_info *p;
  144     for (p = proc_net_packet; p; p = p->next)
  145     {
  146         if (p->inode == inode)
  147         {
  148             return p;
  149         }
  150     }
  151     return NULL;
  152 }
  153 
  154 /* walk a processes fd dir looking for sockets with inodes that match the
  155  * inodes from /proc/net/packet, when a match is found, the processes exe
  156  * is stored */
  157 static void walk_process(char *process)
  158 {
  159     DIR                 *dir;
  160     struct dirent       *ent;
  161     char                path[1024];
  162 
  163     if (snprintf(path, sizeof(path), "/proc/%s/fd", process) == -1)
  164     {
  165         fprintf(stderr, "giant process name! %s\n", process);
  166         return;
  167     }
  168 
  169     if ((dir = opendir(path)) == NULL)
  170     {
  171     if (errno != ENOENT)
  172            perror(path);
  173         return;
  174     }
  175 
  176     while ((ent = readdir(dir)))
  177     {
  178         struct stat             statbuf;
  179         struct packet_info     *info;
  180 
  181         if (snprintf(path, sizeof(path), "/proc/%s/fd/%s",
  182                      process, ent->d_name) == -1)
  183         {
  184             fprintf(stderr, "giant fd name /proc/%s/fd/%s\n",
  185                     process, ent->d_name);
  186             continue;
  187         }
  188 
  189         if (stat(path, &statbuf) == -1)
  190         {
  191             perror(path);
  192             continue;
  193         }
  194 
  195         if (S_ISSOCK(statbuf.st_mode)
  196             && (info = find_packet_info(statbuf.st_ino)))
  197         {
  198             char link[1024];
  199 
  200             memset(link, 0, sizeof(link));
  201             /* no need to check rv since it has to be long enough,
  202              * otherwise, one of the ones above will have failed */
  203             snprintf(path, sizeof(path), "/proc/%s/exe", process);
  204             readlink(path, link, sizeof(link) - 1);
  205             info->cmd = strdup(link);
  206         }
  207     }
  208 
  209     closedir(dir);
  210 }
  211 
  212 /* walk the proc file system looking for processes, call walk_proc on each
  213  * process */
  214 static void walk_processes()
  215 {
  216     DIR                 *dir;
  217     struct dirent       *ent;
  218 
  219     if ((dir = opendir("/proc")) == NULL)
  220     {
  221         perror("/proc");
  222         return;
  223     }
  224 
  225     while ((ent = readdir(dir)))
  226     {
  227         /* we only care about dirs that look like processes */
  228         if (strspn(ent->d_name, "0123456789") == strlen(ent->d_name))
  229         {
  230             walk_process(ent->d_name);
  231         }
  232     }
  233 
  234     closedir(dir);
  235 
  236 }
  237 
  238 /* return 1 if index is a member of pcap_session_list, 0 otherwise. */
  239 static int has_packet_socket(int index)
  240 {
  241     struct packet_info *p;
  242     for (p = proc_net_packet; p; p = p->next)
  243     {
  244         if (p->index == index)
  245         {
  246             return 1;
  247         }
  248     }
  249     return 0;
  250 }
  251 #endif /* __linux__ */
  252 
  253 static void ife_print(struct interface *ptr)
  254 {
  255 #ifdef __linux__
  256     int promisc = ptr->flags & IFF_PROMISC;
  257     int has_packet = has_packet_socket(ptr->index);
  258 
  259     if (promisc || has_packet)
  260     {
  261         printf("%s:", ptr->name);
  262         if (promisc)
  263             printf(" PROMISC");
  264         if (has_packet)
  265         {
  266             struct packet_info *p;
  267         int first_time = 1; 
  268             printf(" PF_PACKET(");
  269             for (p = proc_net_packet; p; p = p->next)
  270             {
  271                if (p->index == ptr->index)
  272                {
  273                   if (first_time) 
  274                   { 
  275                      first_time = 0; 
  276                      printf("%s", p->cmd); 
  277                   }
  278                   else 
  279                      printf(", %s", p->cmd);
  280                 }
  281             }
  282             printf(")");
  283         }
  284         printf("\n");
  285     }
  286     else
  287     {
  288         if (!q)
  289             printf("%s: not promisc and no PF_PACKET sockets\n",
  290                    ptr->name);
  291     }
  292 #else
  293    if (ptr->flags & IFF_PROMISC)
  294       printf("%s is %s", ptr->name, "PROMISC");
  295    else
  296    {
  297       if (!q)
  298          printf("%s is %s", ptr->name, "not promisc");
  299    }
  300    putchar('\n');
  301 #endif
  302 }
  303 
  304 /* Fetch the inteface configuration from the kernel. */
  305 static int if_fetch(char *ifname, struct interface *ife)
  306 {
  307   struct ifreq ifr;
  308 
  309   memset((char *) ife, 0, sizeof(struct interface));
  310   strncpy(ife->name, ifname, sizeof(ife->name));
  311 
  312   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
  313   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
  314       return(-1);
  315   ife->flags = ifr.ifr_flags;
  316 
  317 #ifdef __linux__
  318   /* store the device index */
  319   if (ioctl(skfd, SIOCGIFINDEX, &ifr) < 0)
  320       return(-1);
  321   ife->index = ifr.ifr_ifindex;
  322 #endif
  323 
  324   return(0);
  325 }
  326 
  327 static void if_print()
  328 {
  329    char buff[1024];
  330    struct interface ife;
  331    struct ifconf ifc;
  332    struct ifreq *ifr;
  333    int i;
  334 
  335    ifc.ifc_len = sizeof(buff);
  336    ifc.ifc_buf = buff;
  337    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
  338    {
  339       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
  340       return;
  341    }
  342 
  343    ifr = ifc.ifc_req;
  344    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
  345    {
  346       if (if_fetch(ifr->ifr_name, &ife) < 0)
  347       {
  348 #ifdef __linux__
  349          fprintf(stderr, "%s: unknown interface.\n", ifr->ifr_name);
  350 #endif
  351      continue;
  352       }
  353       if (!memcmp(ifr->ifr_name, "lo", 2))
  354          continue;
  355       ife_print(&ife);
  356    }
  357 }
  358 
  359 int main(int argc, char **argv)
  360 {
  361   if (argc == 2 && !memcmp(argv[1], "-q", 2))
  362      q++;
  363 
  364   /* Create a channel to the NET kernel. */
  365    if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
  366     perror("socket");
  367     exit(-1);
  368   }
  369 #ifdef __linux__
  370   read_proc_net_packet();
  371   walk_processes();
  372 #endif
  373 
  374   if_print();
  375   (void) close(skfd);
  376   exit(0);
  377 }