"Fossies" - the Fresh Open Source Software Archive

Member "ettercap-0.8.3.1/src/ec_network.c" (1 Aug 2020, 13657 Bytes) of package /linux/privat/ettercap-0.8.3.1.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 "ec_network.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.8.3_vs_0.8.3.1.

    1 #include <ec.h>
    2 #include <ec_capture.h>
    3 #include <ec_decode.h>
    4 #include <ec_queue.h>
    5 #include <ec_network.h>
    6 #include <ec_threads.h>
    7 
    8 #include <pcap.h>
    9 #include <libnet.h>
   10 #if !defined(OS_WINDOWS)
   11 #include <ifaddrs.h>
   12 #endif
   13 
   14 #if defined(OS_BSD_OPEN)
   15    /* OPENBSD needs 0 */
   16    #define PCAP_TIMEOUT 0
   17 #elif defined(OS_SOLARIS)
   18    /* SOLARIS needs > 1 */
   19    #define PCAP_TIMEOUT 10
   20 #else
   21    /* LINUX needs > 0 */
   22    /* FREEBSD needs 1 */
   23    /* MACOSX  needs 1 */
   24    #define PCAP_TIMEOUT 1
   25 #endif
   26 
   27 struct source_entry {
   28    struct iface_env iface;
   29    LIST_ENTRY(source_entry) next;
   30 };
   31 
   32 /* globals */
   33 static LIST_HEAD(,source_entry) sources_list;
   34 static pthread_mutex_t sl_mutex = PTHREAD_MUTEX_INITIALIZER;
   35 #define SOURCES_LIST_LOCK     do{ pthread_mutex_lock(&sl_mutex); }while(0)
   36 #define SOURCES_LIST_UNLOCK   do{ pthread_mutex_unlock(&sl_mutex); }while(0)
   37 
   38 /* protos */
   39 static void close_network();
   40 static void pcap_winit(pcap_t *pcap);
   41 static void source_print(struct iface_env *source);
   42 static int source_init(char *name, struct iface_env *source, bool primary, bool live);
   43 static void source_close(struct iface_env *iface);
   44 static int secondary_sources_init(char **sources);
   45 static void close_secondary_sources(void);
   46 static void l3_init(void);
   47 static void l3_close(void);
   48 
   49 /* the code */
   50 
   51 void network_init()
   52 {
   53    char *iface;
   54 
   55    DEBUG_MSG("init_network");
   56 
   57    EC_GBL_PCAP->snaplen = UINT16_MAX;
   58    
   59    if(EC_GBL_OPTIONS->read) {
   60       source_init(EC_GBL_OPTIONS->pcapfile_in, EC_GBL_IFACE, true, false);
   61       source_print(EC_GBL_IFACE);
   62    } else {
   63       iface = EC_GBL_OPTIONS->iface ? EC_GBL_OPTIONS->iface : (EC_GBL_OPTIONS->iface = capture_default_if());
   64       ON_ERROR(iface, NULL, "No suitable interface found...");
   65       source_init(iface, EC_GBL_IFACE, true, true);
   66       source_print(EC_GBL_IFACE);
   67       if(EC_GBL_SNIFF->type == SM_BRIDGED) {
   68          source_init(EC_GBL_OPTIONS->iface_bridge, EC_GBL_BRIDGE, true, true);
   69          source_print(EC_GBL_BRIDGE);
   70          if(EC_GBL_BRIDGE->dlt != EC_GBL_IFACE->dlt)
   71             FATAL_ERROR("Can't bridge interfaces of different types");
   72       }
   73    }
   74 
   75    if(get_decoder(LINK_LAYER, EC_GBL_IFACE->dlt) == NULL) {
   76       if(EC_GBL_OPTIONS->read)
   77          FATAL_ERROR("Dump file not supported (%s)", pcap_datalink_val_to_description(EC_GBL_PCAP->dlt));
   78       else
   79          FATAL_ERROR("Interface \"%s\" not supported (%s)", EC_GBL_OPTIONS->iface, pcap_datalink_val_to_description(EC_GBL_PCAP->dlt));
   80    }
   81    
   82    if(EC_GBL_OPTIONS->write)
   83       pcap_winit(EC_GBL_IFACE->pcap);
   84    
   85    /* determine alignment margin and allocate packet buffer per interface */
   86    EC_GBL_PCAP->align = get_alignment(EC_GBL_PCAP->dlt);
   87    SAFE_CALLOC(EC_GBL_IFACE->pbuf, UINT16_MAX + EC_GBL_PCAP->align + 256, sizeof(char));
   88    if (!EC_GBL_OPTIONS->read && EC_GBL_SNIFF->type == SM_BRIDGED)
   89       SAFE_CALLOC(EC_GBL_BRIDGE->pbuf, UINT16_MAX + EC_GBL_PCAP->align + 256, sizeof(char));
   90 
   91    if(EC_GBL_OPTIONS->secondary) {
   92       secondary_sources_init(EC_GBL_OPTIONS->secondary);
   93       atexit(close_secondary_sources);
   94    }
   95 
   96    /* Layer 3 handlers initialization */
   97    if(!EC_GBL_OPTIONS->unoffensive)
   98       l3_init();
   99       
  100    atexit(close_network);
  101 }
  102 
  103 static void close_network()
  104 {
  105    pcap_close(EC_GBL_IFACE->pcap);
  106    SAFE_FREE(EC_GBL_IFACE->pbuf);
  107    if(EC_GBL_SNIFF->type == SM_BRIDGED) {
  108       pcap_close(EC_GBL_BRIDGE->pcap);
  109       SAFE_FREE(EC_GBL_BRIDGE->pbuf);
  110    }
  111 
  112    if(EC_GBL_OPTIONS->write)
  113       pcap_dump_close(EC_GBL_PCAP->dump);
  114 
  115    libnet_destroy(EC_GBL_IFACE->lnet);
  116    libnet_destroy(EC_GBL_BRIDGE->lnet);
  117 
  118    DEBUG_MSG("ATEXIT: close_network");
  119 }
  120 
  121 static void pcap_winit(pcap_t *pcap)
  122 {
  123    pcap_dumper_t *pdump;
  124    pdump = pcap_dump_open(pcap, EC_GBL_OPTIONS->pcapfile_out);
  125    ON_ERROR(pdump, NULL, "pcap_dump_open: %s", pcap_geterr(pcap));
  126    EC_GBL_PCAP->dump = pdump;
  127 }
  128 
  129 static void source_print(struct iface_env *source)
  130 {
  131    char strbuf[256];
  132    struct net_list *ip6;
  133 
  134    if(source->is_live) {
  135       USER_MSG("Listening on:\n");
  136       USER_MSG("%6s -> %s\n", source->name, mac_addr_ntoa(source->mac, strbuf));
  137       if(source->has_ipv4) {
  138          USER_MSG("\t  %s/", ip_addr_ntoa(&source->ip, strbuf));
  139          USER_MSG("%s\n", ip_addr_ntoa(&source->netmask, strbuf));
  140       }
  141       if(source->has_ipv6) {
  142          LIST_FOREACH(ip6, &source->ip6_list, next) {
  143             USER_MSG("\t  %s/%d\n", ip_addr_ntoa(&ip6->ip, strbuf), ip6->prefix);
  144          }
  145          USER_MSG("\n");
  146       } else {
  147          USER_MSG("\n\n");
  148       }
  149    } else {
  150       USER_MSG("Reading from %s\n", source->name);
  151    }
  152 
  153 }
  154 
  155 static int source_init(char *name, struct iface_env *source, bool primary, bool live)
  156 {
  157    int ret;
  158    pcap_t *pcap = NULL;
  159    libnet_t *lnet = NULL;
  160    struct bpf_program bpf;
  161    char pcap_errbuf[PCAP_ERRBUF_SIZE];
  162    char lnet_errbuf[LIBNET_ERRBUF_SIZE];
  163    int snaplen;
  164 
  165    struct libnet_ether_addr *mac;
  166    struct sockaddr_in *sa4;
  167    struct sockaddr_in6 *sa6;
  168    struct net_list *ip6;
  169 
  170 #if !defined(OS_WINDOWS)
  171   struct ifaddrs *ifaddrs, *ifaddr;
  172 #endif
  173 
  174    DEBUG_MSG("source_init %s", name);
  175 
  176    BUG_IF(source == NULL);
  177 
  178    /* ===pcap initialization=== */
  179    if(live) {
  180       pcap = pcap_open_live(name, EC_GBL_PCAP->snaplen, EC_GBL_PCAP->promisc, PCAP_TIMEOUT, pcap_errbuf);
  181       if(pcap == NULL) {
  182          if(primary)
  183             ON_ERROR(pcap, NULL, "pcap_open_live: %s", pcap_errbuf);
  184          else
  185             return -E_INITFAIL;
  186       }
  187    } else {
  188       /* secondary sources must not be offline */
  189       if(!primary)
  190          return -E_NOTHANDLED;
  191 
  192       struct stat st;
  193       int stat_result;
  194       FILE* pcap_file_h;
  195 
  196       pcap = pcap_open_offline(name, pcap_errbuf);
  197       ON_ERROR(pcap, NULL, "pcap_open_offline: %s", pcap_errbuf);
  198 
  199       pcap_file_h = pcap_file(pcap);
  200       ON_ERROR(pcap_file_h, 0, "pcap_fileno returned an invalid file handle");
  201 
  202       stat_result = fstat(fileno(pcap_file_h), &st);
  203       ON_ERROR(stat_result, -1, "fstat failed.");
  204 
  205       EC_GBL_PCAP->dump_size = st.st_size;
  206    }
  207    source->dlt = pcap_datalink(pcap);
  208    if(primary)
  209       EC_GBL_PCAP->dlt = source->dlt;
  210    if(source->dlt == DLT_IEEE802_11) {
  211       DEBUG_MSG("Wireless monitor mode used, switching to unoffensive mode");
  212       source->unoffensive = 1;
  213       if(primary)
  214          EC_GBL_OPTIONS->unoffensive = 1;
  215    }
  216    if(!strcmp(name, "lo")) {
  217       DEBUG_MSG("Loopback interface used, switching to unoffensive mode");
  218       source->unoffensive = 1;
  219       if(primary)
  220          EC_GBL_OPTIONS->unoffensive = 1;
  221    }
  222 
  223    if(EC_GBL_PCAP->filter && strcmp(EC_GBL_PCAP->filter, "") && live) {
  224       u_int net, mask;
  225       if(pcap_lookupnet(name, &net, &mask, pcap_errbuf) == -1)
  226          ERROR_MSG("%s - %s", name, pcap_errbuf);
  227       if(pcap_compile(pcap, &bpf, EC_GBL_PCAP->filter, 1, mask) < 0)
  228          ERROR_MSG("Wrong pcap filter: %s - %s", name, pcap_geterr(pcap));
  229       if(pcap_setfilter(pcap, &bpf) == 1)
  230          ERROR_MSG("Cannot set pcap filter: %s - %s", name, pcap_geterr(pcap));
  231    }
  232 
  233    snaplen = pcap_snapshot(pcap);
  234    DEBUG_MSG("requested snaplen for %s: %d, assigned snaplen: %d", name, EC_GBL_PCAP->snaplen, snaplen);
  235    if(primary)
  236       EC_GBL_PCAP->snaplen = snaplen;
  237    source->pcap = pcap;
  238 
  239    SAFE_STRDUP(source->name, name);
  240 
  241    if(live) {
  242       source->is_live = 1;
  243    } else {
  244       source->is_ready = 1;
  245       return E_SUCCESS;
  246    }
  247 
  248    if(!EC_GBL_OPTIONS->unoffensive && !source->unoffensive) {
  249       lnet = libnet_init(LIBNET_LINK_ADV, name, lnet_errbuf);
  250       ON_ERROR(lnet, NULL, "libnet_init: %s", lnet_errbuf);
  251 
  252       mac = libnet_get_hwaddr(lnet);
  253       memcpy(&source->mac, mac, MEDIA_ADDR_LEN);
  254    }
  255 
  256    source->lnet = lnet;
  257 
  258    source->mtu = get_iface_mtu(name);
  259 #if defined(OS_WINDOWS)
  260   pcap_if_t *dev;
  261 
  262   for (dev = (pcap_if_t *)EC_GBL_PCAP->ifs; dev; dev = dev->next) {
  263       if(strcmp(dev->name, name))
  264         continue;
  265 
  266       if(dev->addresses->addr->sa_family == AF_INET) {
  267         sa4 = (struct sockaddr_in*) dev->addresses->addr;
  268 
  269         ip_addr_init(&source->ip, AF_INET, (u_char*)&sa4->sin_addr);
  270         if(EC_GBL_OPTIONS->netmask) {
  271             if(ip_addr_pton(EC_GBL_OPTIONS->netmask, &source->netmask) != E_SUCCESS)
  272               FATAL_ERROR("Invalid netmask %s", EC_GBL_OPTIONS->netmask);
  273         } else {
  274             sa4 = (struct sockaddr_in*) dev->addresses->netmask;
  275             ip_addr_init(&source->netmask, AF_INET, (u_char*)&sa4->sin_addr);
  276         }
  277         ip_addr_get_network(&source->ip, &source->netmask, &source->network);
  278         source->has_ipv4 = 1;
  279       }
  280       else if(dev->addresses->addr->sa_family == AF_INET6) {
  281         SAFE_CALLOC(ip6, 1, sizeof(*ip6));
  282         sa6 = (struct sockaddr_in6*) dev->addresses->addr;
  283         ip_addr_init(&ip6->ip, AF_INET6, (u_char*)&sa6->sin6_addr);
  284 
  285         sa6 = (struct sockaddr_in6*) dev->addresses->netmask;
  286         ip_addr_init(&ip6->netmask, AF_INET6, (u_char*)&sa6->sin6_addr);
  287         ip_addr_get_network(&ip6->ip, &ip6->netmask, &ip6->network);
  288         ip6->prefix = ip_addr_get_prefix(&ip6->netmask);
  289         LIST_INSERT_HEAD(&source->ip6_list, ip6, next);
  290         source->has_ipv6 = 1;
  291       }
  292   }
  293 
  294 #else
  295    ret = getifaddrs(&ifaddrs);
  296    ON_ERROR(ret, -1, "getifaddrs: %s", strerror(errno));
  297 
  298    for(ifaddr = ifaddrs; ifaddr; ifaddr = ifaddr->ifa_next) {
  299       if (ifaddr->ifa_addr == NULL)
  300          continue;
  301       if(strcmp(ifaddr->ifa_name, name))
  302          continue;
  303 
  304       if(ifaddr->ifa_addr->sa_family == AF_INET) {
  305          sa4 = (struct sockaddr_in*)ifaddr->ifa_addr;
  306          ip_addr_init(&source->ip, AF_INET, (u_char*)&sa4->sin_addr);
  307          if(EC_GBL_OPTIONS->netmask) {
  308             if(ip_addr_pton(EC_GBL_OPTIONS->netmask, &source->netmask) != E_SUCCESS)
  309                FATAL_ERROR("Invalid netmask %s", EC_GBL_OPTIONS->netmask);
  310          } else {
  311             sa4 = (struct sockaddr_in*)ifaddr->ifa_netmask;
  312             ip_addr_init(&source->netmask, AF_INET, (u_char*)&sa4->sin_addr);
  313          }
  314          ip_addr_get_network(&source->ip, &source->netmask, &source->network);
  315          source->has_ipv4 = 1;
  316       } else if(ifaddr->ifa_addr->sa_family == AF_INET6) {
  317          SAFE_CALLOC(ip6, 1, sizeof(*ip6));
  318          sa6 = (struct sockaddr_in6*)ifaddr->ifa_addr;
  319          ip_addr_init(&ip6->ip, AF_INET6, (u_char*)&sa6->sin6_addr);
  320          sa6 = (struct sockaddr_in6*)ifaddr->ifa_netmask;
  321          ip_addr_init(&ip6->netmask, AF_INET6, (u_char*)&sa6->sin6_addr);
  322          ip_addr_get_network(&ip6->ip, &ip6->netmask, &ip6->network);
  323          ip6->prefix = ip_addr_get_prefix(&ip6->netmask);
  324          LIST_INSERT_HEAD(&source->ip6_list, ip6, next);
  325          source->has_ipv6 = 1;
  326       }
  327    }
  328 
  329    freeifaddrs(ifaddrs);
  330 #endif  /* OS_WINDOWS */
  331 
  332    source->is_ready = 1;
  333 
  334    return E_SUCCESS;
  335 }
  336 
  337 static void source_close(struct iface_env *iface)
  338 {
  339 #ifdef WITH_IPV6
  340    struct net_list *n;
  341 #endif
  342 
  343    iface->is_ready = 0;
  344 
  345    if(iface->pcap != NULL)
  346       pcap_close(iface->pcap);
  347 
  348    if(iface->lnet != NULL)
  349       libnet_destroy(iface->lnet);
  350   
  351 #ifdef WITH_IPV6 
  352    LIST_FOREACH(n, &iface->ip6_list, next) {
  353       LIST_REMOVE(n, next);
  354       SAFE_FREE(n);
  355    }
  356 #endif
  357 
  358    SAFE_FREE(iface->name);
  359    memset(iface, 0, sizeof(*iface));
  360 }
  361 
  362 static int secondary_sources_init(char **sources)
  363 {
  364    struct source_entry *se;
  365    int n = 0;
  366 
  367    SOURCES_LIST_LOCK;
  368 
  369    for(n = 0; sources[n] != NULL; n++) {
  370       SAFE_CALLOC(se, 1, sizeof(*se));
  371 
  372       /* secondary interfaces are always live */
  373       source_init(sources[n], &se->iface, true, false);
  374       if(se->iface.is_ready)
  375          LIST_INSERT_HEAD(&sources_list, se, next);
  376       else 
  377          SAFE_FREE(se);
  378    }
  379 
  380    SOURCES_LIST_UNLOCK;
  381 
  382    return n;
  383 }
  384 
  385 void secondary_sources_foreach(void (*callback)(struct iface_env*))
  386 {
  387     struct source_entry *se;
  388 
  389     SOURCES_LIST_LOCK;
  390 
  391     LIST_FOREACH(se, &sources_list, next) {
  392         callback(&se->iface);
  393     }
  394 
  395     SOURCES_LIST_UNLOCK;
  396 }
  397 
  398 static void close_secondary_sources(void)
  399 {
  400    struct source_entry *se;
  401 
  402    SOURCES_LIST_LOCK;
  403 
  404    LIST_FOREACH(se, &sources_list, next) {
  405       LIST_REMOVE(se, next);
  406       source_close(&se->iface);
  407       SAFE_FREE(se);
  408    }
  409 
  410    SOURCES_LIST_UNLOCK;
  411 }
  412 
  413 static void l3_init(void)
  414 {
  415    libnet_t *l4;
  416 #ifdef WITH_IPV6
  417    libnet_t *l6;
  418 #endif
  419 #ifdef OS_WINDOWS
  420    char *name = EC_GBL_OPTIONS->iface;
  421 #else
  422    char *name = NULL;
  423 #endif
  424 
  425 
  426    char lnet_errbuf[LIBNET_ERRBUF_SIZE];
  427 
  428    DEBUG_MSG("l3_init");
  429 
  430    /* open the socket at layer 3 */
  431    l4 = libnet_init(LIBNET_RAW4_ADV, name, lnet_errbuf);               
  432    if (l4 == NULL) {
  433       DEBUG_MSG("send_init: libnet_init(LIBNET_RAW4_ADV) failed: %s", lnet_errbuf);
  434       USER_MSG("Libnet failed IPv4 initialization. Don't send IPv4 packets.\n");
  435    }
  436 
  437    EC_GBL_LNET->lnet_IP4 = l4;               
  438 
  439 #ifdef WITH_IPV6
  440    /* open the socket at layer 3 for IPv6 */
  441    l6 = libnet_init(LIBNET_RAW6_ADV, name, lnet_errbuf);
  442    if(l6 == NULL) {
  443       DEBUG_MSG("%s: libnet_init(LIBNET_RAW6_ADV) failed: %s", __func__, lnet_errbuf);
  444       USER_MSG("Libnet failed IPv6 initialization. Don't send IPv6 packets.\n");
  445    }
  446    
  447    EC_GBL_LNET->lnet_IP6 = l6;
  448 #endif
  449 
  450    atexit(l3_close);
  451 }
  452 
  453 static void l3_close(void)
  454 {
  455    if(EC_GBL_LNET->lnet_IP4)
  456       libnet_destroy(EC_GBL_LNET->lnet_IP4);
  457 #ifdef WITH_IPV6
  458    if(EC_GBL_LNET->lnet_IP6)
  459       libnet_destroy(EC_GBL_LNET->lnet_IP6);
  460 #endif
  461    
  462    DEBUG_MSG("ATEXIT: send_closed");
  463 }
  464 
  465 struct iface_env* iface_by_mac(u_int8 mac[MEDIA_ADDR_LEN])
  466 {
  467    struct source_entry *se;
  468 
  469    SOURCES_LIST_LOCK;
  470 
  471    LIST_FOREACH(se, &sources_list, next) {
  472       if(!memcmp(se->iface.mac, mac, MEDIA_ADDR_LEN)) {
  473          SOURCES_LIST_UNLOCK;
  474          return &se->iface;
  475       }
  476    }
  477 
  478    SOURCES_LIST_UNLOCK;
  479    return NULL;
  480 }
  481