From e4b57e21ec2bc7f99c182eea23ecec297e111799 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 16 Jun 2014 20:24:15 +0300 Subject: [PATCH] Support IPv6 --- source/address.cpp | 22 ++++++++++++++++ source/address.h | 2 ++ source/netvis.cpp | 62 ++++++++++++++++++++++++++++++++++++++++------ source/netvis.h | 4 ++- 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/source/address.cpp b/source/address.cpp index 3a49971..4b56625 100644 --- a/source/address.cpp +++ b/source/address.cpp @@ -21,6 +21,14 @@ Address::Address(uint32_t a): data[i] = a>>(24-i*8); } +Address::Address(const in6_addr &a): + type(ETH_P_IPV6), + length(16), + mask_bits(128) +{ + copy(a.s6_addr, a.s6_addr+16, data); +} + Address::Address(unsigned short t, const unsigned char *d, unsigned char l): type(t), length(l) @@ -53,6 +61,11 @@ string Address::str() const char buf[INET_ADDRSTRLEN]; return inet_ntop(AF_INET, data, buf, INET_ADDRSTRLEN); } + else if(type==ETH_P_IPV6) + { + char buf[INET6_ADDRSTRLEN]; + return inet_ntop(AF_INET6, data, buf, INET6_ADDRSTRLEN); + } else return ""; } @@ -94,6 +107,15 @@ void Address::to_sockaddr(sockaddr_storage &sa) const sa_in.sin_port = 0; sa_in.sin_addr.s_addr = *(uint32_t *)data; } + else if(type==ETH_P_IPV6) + { + sockaddr_in6 &sa_in6 = reinterpret_cast(sa); + sa_in6.sin6_family = AF_INET6; + sa_in6.sin6_port = 0; + sa_in6.sin6_flowinfo = 0; + copy(data, data+16, sa_in6.sin6_addr.s6_addr); + sa_in6.sin6_scope_id = 0; + } else throw runtime_error("Unknown type"); } diff --git a/source/address.h b/source/address.h index 42e671f..eda9368 100644 --- a/source/address.h +++ b/source/address.h @@ -2,6 +2,7 @@ #define ADDRESS_H_ #include +#include #include struct Address @@ -13,6 +14,7 @@ struct Address Address(); Address(uint32_t); + Address(const in6_addr &); Address(unsigned short, const unsigned char *, unsigned char); void set_mask(const Address &); diff --git a/source/netvis.cpp b/source/netvis.cpp index a8f6209..0e2378f 100644 --- a/source/netvis.cpp +++ b/source/netvis.cpp @@ -46,7 +46,11 @@ NetVis::NetVis(int argc, char **argv): throw usage_error("No interface given"); iface = argv[1]; - char err[1024]; + char err[PCAP_ERRBUF_SIZE]; + pcap_if_t *devs; + if(pcap_findalldevs(&devs, err)==-1) + throw runtime_error(err); + pcap = pcap_open_live(iface.c_str(), 128, true, 0, err); if(!pcap) throw runtime_error(err); @@ -54,10 +58,29 @@ NetVis::NetVis(int argc, char **argv): if(pcap_setnonblock(pcap, true, err)==-1) throw runtime_error(err); - unsigned local_addr, local_mask; - pcap_lookupnet(iface.c_str(), &local_addr, &local_mask, err); - localnet = Address(ntohl(local_addr)); - localnet.set_mask(Address(ntohl(local_mask))); + for(pcap_if_t *d=devs; d; d=d->next) + if(iface==d->name) + { + for(pcap_addr_t *a=d->addresses; a; a=a->next) + { + if(a->addr->sa_family==AF_INET) + { + Address addr(ntohl(reinterpret_cast(a->addr)->sin_addr.s_addr)); + if(a->netmask) + addr.set_mask(Address(ntohl(reinterpret_cast(a->netmask)->sin_addr.s_addr))); + localnets.push_back(addr); + } + else if(a->addr->sa_family==AF_INET6) + { + Address addr(reinterpret_cast(a->addr)->sin6_addr); + if(a->netmask) + addr.set_mask(Address(reinterpret_cast(a->netmask)->sin6_addr)); + localnets.push_back(addr); + } + } + } + + pcap_freealldevs(devs); resolver = new Resolver; @@ -256,8 +279,9 @@ Host &NetVis::get_host(const Address &a) return *i->second; Host *host = new Host(*this, a); - if(localnet.masked_match(a)) - host->set_local(true); + for(list
::const_iterator j=localnets.begin(); j!=localnets.end(); ++j) + if(j->masked_match(a)) + host->set_local(true); resolver->push(host); host->set_position(Vector2(rand()*400.0/RAND_MAX-200.0, rand()*400.0/RAND_MAX-200.0)); for(unsigned j=0; j<100; ++j) @@ -296,6 +320,11 @@ void NetVis::handle_ethernet(CaptureContext &ctx, const ethhdr *eth, unsigned le const iphdr *ip = reinterpret_cast(eth+1); handle_ipv4(ctx, ip, len-sizeof(ethhdr)); } + else if(proto==ETH_P_IPV6) + { + const ip6_hdr *ip6 = reinterpret_cast(eth+1); + handle_ipv6(ctx, ip6, len-sizeof(ethhdr)); + } else IO::print("Unknown protocol in eth: %d\n", proto); } @@ -320,6 +349,25 @@ void NetVis::handle_ipv4(CaptureContext &ctx, const iphdr *ip, unsigned len) IO::print("Unknown protocol in ip: %d\n", ip->protocol); } +void NetVis::handle_ipv6(CaptureContext &ctx, const ip6_hdr *ip6, unsigned len) +{ + ctx.src_host = &get_host(ip6->ip6_src); + if(!IN6_IS_ADDR_MULTICAST(ip6->ip6_dst.s6_addr)) + ctx.dst_host = &get_host(ip6->ip6_dst); + + if(ip6->ip6_nxt==IPPROTO_TCP) + { + const tcphdr *tcp = reinterpret_cast(ip6+1); + handle_tcp(ctx, tcp, len-sizeof(ip6_hdr)); + } + else if(ip6->ip6_nxt==IPPROTO_UDP) + { + const udphdr *udp = reinterpret_cast(ip6+1); + handle_udp(ctx, udp, len-sizeof(ip6_hdr)); + } + else + IO::print("Unknown next header in ip6: %d\n", ip6->ip6_nxt); +} void NetVis::handle_tcp(CaptureContext &ctx, const tcphdr *tcp, unsigned) { diff --git a/source/netvis.h b/source/netvis.h index a59b650..cd45133 100644 --- a/source/netvis.h +++ b/source/netvis.h @@ -13,6 +13,7 @@ Distributed unter the GPL #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ private: std::string iface; pcap_t *pcap; Resolver *resolver; - Address localnet; + std::list
localnets; Msp::Graphics::SimpleGLWindow *wnd; Msp::GL::Font *font; @@ -85,6 +86,7 @@ private: static void capture_handler(unsigned char *, const pcap_pkthdr *, const unsigned char *); void handle_ethernet(CaptureContext &, const ethhdr *, unsigned); void handle_ipv4(CaptureContext &, const iphdr *, unsigned); + void handle_ipv6(CaptureContext &, const ip6_hdr *, unsigned); void handle_tcp(CaptureContext &, const tcphdr *, unsigned); void handle_udp(CaptureContext &, const udphdr *, unsigned); void handle_packet(CaptureContext &); -- 2.43.0