intf_t * intf_open(void) { intf_t *intf; int one = 1; if ((intf = calloc(1, sizeof(*intf))) != NULL) { intf->fd = intf->fd6 = -1; if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (intf_close(intf)); setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof(one)); #ifdef SIOCGIFNETMASK_IN6 if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { # ifdef EPROTONOSUPPORT if (errno != EPROTONOSUPPORT) # endif return (intf_close(intf)); } #endif } return (intf); }
/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ int eth_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) { intf_t *intf; struct intf_entry ie; pcap_if_t *pcapdevs; pcap_if_t *pdev; char pname[128]; if ((intf = intf_open()) == NULL) return -1; pname[0] = '\0'; memset(&ie, 0, sizeof(ie)); strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name)); if (intf_get(intf, &ie) != 0) { intf_close(intf); return -1; } intf_close(intf); /* Next we must find the pcap device name corresponding to the device. The device description used to be compared with those from PacketGetAdapterNames(), but that was unrelaible because dnet and pcap sometimes give different descriptions. For example, dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's Packet Scheduler)". Then IP addresses used to be compared, but that proved to be unreliable as well. Now we compare hardware addresses much like eth_open() does */ if (pcap_findalldevs(&pcapdevs, NULL) == -1) return -1; if (pname[0] == '\0' && ie.intf_link_addr.addr_type == ADDR_TYPE_ETH) { for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { eth_t eth; eth_addr_t ea; eth.lpa = PacketOpenAdapter(pdev->name); if (eth.lpa == NULL) continue; if (eth.lpa->hFile != INVALID_HANDLE_VALUE && eth_get(ð, &ea) == 0 && memcmp(&ea, &ie.intf_link_addr.addr_eth, ETH_ADDR_LEN) == 0) { /* Found it -- Yay! */ strlcpy(pname, pdev->name, sizeof(pname)); } PacketCloseAdapter(eth.lpa); } } pcap_freealldevs(pcapdevs); if (pname[0]) { strlcpy(pcapdev, pname, pcapdevlen); return 0; } return -1; }
/* Converts a libdnet interface name to its pcap equivalent. The pcap name is stored in pcapdev up to a length of pcapdevlen, including the terminating '\0'. Returns -1 on error. */ int intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) { IP_ADAPTER_ADDRESSES *a; pcap_if_t *pcapdevs; pcap_if_t *pdev, *selected; intf_t *intf; if ((intf = intf_open()) == NULL) return (-1); if (_refresh_tables(intf) < 0) { intf_close(intf); return (-1); } a = _find_adapter_address(intf, intf_name); if (a == NULL) { intf_close(intf); return (-1); } if (pcap_findalldevs(&pcapdevs, NULL) == -1) { intf_close(intf); return (-1); } /* Loop through all the pcap devices until we find a match. */ selected = NULL; for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) { char *name; if (pdev->name == NULL) continue; name = strchr(pdev->name, '{'); if (name == NULL) continue; if (strcmp(name, a->AdapterName) == 0) break; } if (pdev != NULL) strlcpy(pcapdev, pdev->name, pcapdevlen); intf_close(intf); pcap_freealldevs(pcapdevs); if (pdev == NULL) return -1; else return 0; }
eth_t * eth_open(const char *device) { eth_t *eth; intf_t *intf; struct intf_entry ifent; eth_addr_t ea; char *p, *buf; ULONG len; /* Get interface entry. */ memset(&ifent, 0, sizeof(ifent)); if ((intf = intf_open()) != NULL) { strlcpy(ifent.intf_name, device, sizeof(ifent.intf_name)); intf_get(intf, &ifent); intf_close(intf); } if (ifent.intf_link_addr.addr_type != ADDR_TYPE_ETH) return (NULL); /* Get Packet driver adapter name/desc lists. */ buf = NULL; PacketGetAdapterNames(buf, &len); if (len > 0 && (buf = malloc(len)) != NULL) { if (!PacketGetAdapterNames(buf, &len)) { free(buf); buf = NULL; } } if (buf == NULL) return (NULL); /* XXX - find adapter with matching interface MAC address. */ if ((eth = calloc(1, sizeof(*eth))) == NULL) { free(buf); return (NULL); } for (p = buf; *p != '\0'; p += strlen(p) + 1) { if ((eth->lpa = PacketOpenAdapter(p)) != NULL) { if (eth->lpa->hFile != INVALID_HANDLE_VALUE && eth_get(eth, &ea) == 0 && memcmp(&ea, &ifent.intf_link_addr.addr_eth, ETH_ADDR_LEN) == 0) { PacketSetBuff(eth->lpa, 512000); eth->pkt = PacketAllocatePacket(); break; } PacketCloseAdapter(eth->lpa); } } free(buf); if (eth->pkt == NULL) eth = eth_close(eth); return (eth); }
int main(int argc, char **argv) { ip_t *sock; intf_t *intf; struct addr dst; struct ip_hdr *ip; struct udp_hdr *udp; struct intf_entry entry; int len = IP_HDR_LEN + UDP_HDR_LEN; char buf[len]; if (argc < 2 || addr_aton(argv[1], &dst)) { printf("error: please specify a target ip address\n"); return 1; } memset(buf, 0, sizeof(buf)); ip = (struct ip_hdr *) buf; ip->ip_v = 4; ip->ip_hl = 5; ip->ip_tos = 0; ip->ip_off = 0; ip->ip_sum = 0; ip->ip_ttl = IP_TTL_MAX; ip->ip_p = IP_PROTO_UDP; ip->ip_id = htons(0xdead); ip->ip_len = htons(len); udp = (struct udp_hdr *) (buf + IP_HDR_LEN); udp->uh_sum = 0; udp->uh_sport = htons(0); udp->uh_dport = htons(5353); udp->uh_ulen = htons(UDP_HDR_LEN); intf = intf_open(); intf_get_dst(intf, &entry, &dst); intf_close(intf); ip->ip_src = entry.intf_addr.addr_ip; ip->ip_dst = dst.addr_ip; ip_checksum(buf, len); sock = ip_open(); if (!sock) { printf("error: root privileges needed for raw socket\n"); return 1; } ip_send(sock, buf, len); ip_close(sock); return 0; }
intf_t * intf_open(void) { intf_t *intf; if ((intf = calloc(1, sizeof(*intf))) != NULL) { intf->fd = intf->fd6 = -1; if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (intf_close(intf)); #ifdef SIOCGIFNETMASK_IN6 if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { # ifdef EPROTONOSUPPORT if (errno != EPROTONOSUPPORT) # endif return (intf_close(intf)); } #endif } return (intf); }
tun_t * tun_close(tun_t *tun) { if (tun->fd > 0) close(tun->fd); if (tun->intf != NULL) { /* Restore interface configuration on close. */ intf_set(tun->intf, &tun->save); intf_close(tun->intf); } free(tun); return (NULL); }
arp_t * arp_close(arp_t *a) { if (a != NULL) { if (a->fd >= 0) close(a->fd); #ifdef HAVE_ARPREQ_ARP_DEV if (a->intf != NULL) intf_close(a->intf); #endif free(a); } return (NULL); }
/** * Shut down an object interface * * @v intf Object interface * @v rc Reason for close * * Blocks further operations from being received via the interface, * executes a close operation on the destination interface, and * unplugs the interface. */ void intf_shutdown ( struct interface *intf, int rc ) { DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n", INTF_DBG ( intf ), strerror ( rc ) ); /* Block further operations */ intf_nullify ( intf ); /* Notify destination of close */ intf_close ( intf, rc ); /* Unplug interface */ intf_unplug ( intf ); }
static int fragroute_close(void) { if (ctx.tun != NULL) tun_close(ctx.tun); if (ctx.route != NULL) route_close(ctx.route); if (ctx.intf != NULL) intf_close(ctx.intf); if (ctx.eth != NULL) eth_close(ctx.eth); if (ctx.arp != NULL) arp_close(ctx.arp); if (ctx.dfile != NULL) pcap_dump_close(ctx.dfile); #ifdef WIN32 WSACleanup(); #endif return (-1); }
END_TEST START_TEST(test_intf_get) { struct intf_entry ifent; intf_t *i; i = intf_open(); memset(&ifent, 0, sizeof(ifent)); fail_unless(intf_get(i, &ifent) < 0, "didn't fail on empty request"); ifent.intf_len = sizeof(ifent); fail_unless(intf_get(i, &ifent) < 0, "didn't fail on empty name"); intf_close(i); }
static PyObject * interfaces(PyObject *self, PyObject *args) { intf_t *intf; PyObject *dict; struct intf_entry *entry = NULL; dict = PyDict_New(); if (!dict) return NULL; intf = intf_open(); intf_loop( intf, interfaces_callback, (void*) dict ); intf_close(intf); if (!dict) myerror("Could not read any net interfaces"); return dict; }
int intf_main(int argc, char *argv[]) { struct intf_entry *entry; struct addr *ap, addr; char *cmd, buf[1024]; if (argc < 2) usage(); cmd = argv[1]; entry = (struct intf_entry *)buf; memset(entry, 0, sizeof(*entry)); entry->intf_len = sizeof(buf); if ((intf = intf_open()) == NULL) err(1, "intf_open"); if (strcmp(cmd, "show") == 0) { if (intf_loop(intf, print_intf, NULL) < 0) err(1, "intf_loop"); } else if (strcmp(cmd, "get") == 0) { if (argc < 3) usage(); strlcpy(entry->intf_name, argv[2], sizeof(entry->intf_name)); if (intf_get(intf, entry) < 0) err(1, "intf_get"); print_intf(entry, NULL); } else if (strcmp(cmd, "src") == 0) { if (argc < 3 || addr_aton(argv[2], &addr) < 0) usage(); if (intf_get_src(intf, entry, &addr) < 0) err(1, "intf_get_src"); print_intf(entry, NULL); } else if (strcmp(cmd, "dst") == 0) { if (argc < 3 || addr_aton(argv[2], &addr) < 0) usage(); if (intf_get_dst(intf, entry, &addr) < 0) err(1, "intf_get_dst"); print_intf(entry, NULL); } else if (strcmp(cmd, "set") == 0) { if (argc < 4) usage(); strlcpy(entry->intf_name, argv[2], sizeof(entry->intf_name)); for (argv += 3, argc -= 3; argc > 1; argv += 2, argc -= 2) { if (strcmp(argv[0], "alias") == 0) { ap = &entry->intf_alias_addrs [entry->intf_alias_num++]; } else if (strcmp(argv[0], "dst") == 0) { ap = &entry->intf_dst_addr; } else if (strcmp(argv[0], "inet") == 0) { ap = &entry->intf_addr; } else if (strcmp(argv[0], "link") == 0) { ap = &entry->intf_link_addr; } else break; if (addr_pton(argv[1], ap) < 0) err(1, "invalid address: %s", argv[1]); } for ( ; argc > 0; argv++, argc--) { if (strcmp(argv[0], "up") == 0) entry->intf_flags |= INTF_FLAG_UP; else if (strcmp(argv[0], "down") == 0) entry->intf_flags &= ~INTF_FLAG_UP; else if (strcmp(argv[0], "arp") == 0) entry->intf_flags &= ~INTF_FLAG_NOARP; else if (strcmp(argv[0], "noarp") == 0) entry->intf_flags |= INTF_FLAG_NOARP; else usage(); } if (intf_set(intf, entry) < 0) err(1, "intf_set"); } else usage(); intf_close(intf); exit(0); }
int main(int argc, char *argv[]) { struct intf_entry ifent; intf_t *intf; int i, tests; char *cmd; if (argc < 3) usage(); for (tests = 0, i = 1; i < argc - 1; i++) { cmd = argv[i]; if (strcmp(cmd, "all") == 0) tests = ~0; else if (strcmp(cmd, "ping") == 0) tests |= TEST_PING; else if (strcmp(cmd, "ip-opt") == 0) tests |= TEST_IP_OPT; else if (strcmp(cmd, "ip-tracert") == 0) tests |= TEST_IP_TRACERT; else if (strcmp(cmd, "frag") == 0) tests |= TEST_FRAG; else if (strcmp(cmd, "frag-new") == 0) tests |= TEST_FRAG_NEW; else if (strcmp(cmd, "frag-old") == 0) tests |= TEST_FRAG_OLD; else if (strcmp(cmd, "frag-timeout") == 0) tests |= TEST_FRAG_TIMEOUT; else usage(); } if (addr_aton(argv[i], &ctx.dst) < 0) err(1, "invalid host %s", argv[i]); if ((intf = intf_open()) == NULL) err(1, "couldn't open interface handle"); ifent.intf_len = sizeof(ifent); if (intf_get_dst(intf, &ifent, &ctx.dst) < 0) err(1, "couldn't find interface for %s", addr_ntoa(&ctx.dst)); memcpy(&ctx.src, &ifent.intf_addr, sizeof(ctx.src)); ctx.src.addr_bits = IP_ADDR_BITS; intf_close(intf); if ((ctx.ip = ip_open()) == NULL) err(1, "couldn't open raw IP interface"); if ((ctx.pcap = pcap_open(ifent.intf_name)) == NULL) err(1, "couldn't open %s for sniffing", ifent.intf_name); if ((ctx.dloff = pcap_dloff(ctx.pcap)) < 0) err(1, "couldn't determine link layer offset"); ctx.rnd = rand_open(); pkt_init(16); TAILQ_INIT(&ctx.pktq); ping = pkt_new(); ip_pack_hdr(ping->pkt_ip, 0, IP_HDR_LEN + 8 + 24, 666, 0, IP_TTL_DEFAULT, IP_PROTO_ICMP, ctx.src.addr_ip, ctx.dst.addr_ip); icmp_pack_hdr_echo(ping->pkt_icmp, ICMP_ECHO, ICMP_CODE_NONE, 666, 1, "AAAAAAAABBBBBBBBCCCCCCCC", 24); ping->pkt_end = ping->pkt_eth_data + IP_HDR_LEN + 8 + 24; pkt_decorate(ping); if ((tests & TEST_PING) != 0) test_ping(); if ((tests & TEST_IP_OPT) != 0) test_ip_opt(); if ((tests & TEST_IP_TRACERT) != 0) test_ip_tracert(); if ((tests & TEST_FRAG) != 0) test_frag(NULL, 0); if ((tests & TEST_FRAG_NEW) != 0) test_frag("new", 0); if ((tests & TEST_FRAG_OLD) != 0) test_frag("old", 0); if ((tests & TEST_FRAG_TIMEOUT) != 0) test_frag(NULL, 1); rand_close(ctx.rnd); pcap_close(ctx.pcap); ip_close(ctx.ip); exit(0); }
/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ int intf_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) { int i; intf_t *intf; struct intf_entry ie; pcap_if_t *pcapdevs; pcap_if_t *pdev; char pname[128]; struct sockaddr_in devip; pcap_addr_t *pa; if ((intf = intf_open()) == NULL) return -1; pname[0] = '\0'; memset(&ie, 0, sizeof(ie)); strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name)); if (intf_get(intf, &ie) != 0) { intf_close(intf); return -1; } intf_close(intf); /* Find the first IPv4 address for ie */ if (ie.intf_addr.addr_type == ADDR_TYPE_IP) { addr_ntos(&ie.intf_addr, (struct sockaddr *) &devip); } else { for(i=0; i < (int) ie.intf_alias_num; i++) { if (ie.intf_alias_addrs[i].addr_type == ADDR_TYPE_IP) { addr_ntos(&ie.intf_alias_addrs[i], (struct sockaddr *) &devip); break; } } if (i == ie.intf_alias_num) return -1; // Failed to find IPv4 address, which is currently a requirement } /* Next we must find the pcap device name corresponding to the device. The device description used to be compared with those from PacketGetAdapterNames(), but that was unrelaible because dnet and pcap sometimes give different descriptions. For example, dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's Packet Scheduler)". Plus, Packet* functions aren't really supported for external use by the WinPcap folks. So I have rewritten this to compare interface addresses (which has its own problems -- what if you want to listen an an interface with no IP address set?) --Fyodor */ if (pcap_findalldevs(&pcapdevs, NULL) == -1) return -1; for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { for (pa=pdev->addresses; pa && !pname[0]; pa = pa->next) { if (pa->addr->sa_family != AF_INET) continue; if (((struct sockaddr_in *)pa->addr)->sin_addr.s_addr == devip.sin_addr.s_addr) { strlcpy(pname, pdev->name, sizeof(pname)); /* Found it -- Yay! */ break; } } } pcap_freealldevs(pcapdevs); if (pname[0]) { strlcpy(pcapdev, pname, pcapdevlen); return 0; } return -1; }