代码拉取完成,页面将自动刷新
#include <arpa/inet.h>
#include <errno.h>
#include <iostream>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <sstream>
#include <stdexcept>
#include <string.h>
#include <string>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
using namespace std;
#define throw_unix_error(fn) throw runtime_error(string(fn) + ": " + strerror(errno))
struct {
string iface;
bool hexdump = false;
} options;
void parse_options(int argc, char *argv[])
{
for (;;) {
int c = getopt(argc, argv, ":i:x");
switch (c) {
case -1:
return;
case 'i':
options.iface = optarg;
break;
case 'x':
options.hexdump = true;
break;
default:
throw invalid_argument(string{(char)c});
}
}
}
struct __attribute__((__packed__)) myicmp {
struct ethhdr eth_hdr;
struct iphdr ip_hdr;
struct icmp icmp;
/* 假设没有ip选项*/
union {
struct udphdr udp_hdr;
};
};
struct ipaddr {
in_addr_t in_addr;
};
ostream &operator<<(ostream &out, const ipaddr &ip)
{
struct in_addr in;
in.s_addr = ip.in_addr;
out << inet_ntoa(in);
return out;
}
ostream &operator<<(ostream &out, const struct iphdr &ip_hdr)
{
out << "IP " << ipaddr{ip_hdr.saddr} << " > " << ipaddr{ip_hdr.daddr};
return out;
}
inline int icmp_len(const myicmp *icmp)
{
return ntohs(icmp->ip_hdr.tot_len) - (icmp->ip_hdr.ihl << 2);
}
struct midnight {
unsigned long ms;
};
ostream &operator<<(ostream &out, const midnight &mn)
{
unsigned long ms = mn.ms % 1000UL;
unsigned long sec = mn.ms / 1000UL;
char buf[32];
sprintf(buf, "%02lu:%02lu:%02lu.%03lu",
sec / 60 / 60,
sec / 60 % 60,
sec % 60,
ms);
out << buf;
return out;
}
template <int type, int code = 0>
struct outicmp {
const myicmp *icmp;
};
template <int type, int code>
ostream &operator<<(ostream &out, const outicmp<type, code> &icmp)
{
out << "TODO";
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_DEST_UNREACH, ICMP_NET_UNREACH> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP net " << ipaddr{icmp.icmp->icmp.icmp_ip.ip_dst.s_addr} << " unreachable"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_DEST_UNREACH, ICMP_HOST_UNREACH> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP host " << ipaddr{icmp.icmp->icmp.icmp_ip.ip_dst.s_addr} << " unreachable"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP " << ipaddr{icmp.icmp->icmp.icmp_ip.ip_dst.s_addr}
<< " unreachable - need to frag (mtu " << ntohs(icmp.icmp->icmp.icmp_nextmtu) << ")"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_REDIRECT, ICMP_REDIR_HOST> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP redirect " << ipaddr{icmp.icmp->icmp.icmp_ip.ip_dst.s_addr}
<< " to host " << ipaddr{icmp.icmp->icmp.icmp_gwaddr.s_addr}
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_ECHO> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP echo query"
<< ", id " << ntohs(icmp.icmp->icmp.icmp_id)
<< ", seq " << ntohs(icmp.icmp->icmp.icmp_seq)
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_ECHOREPLY> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP echo reply"
<< ", id " << ntohs(icmp.icmp->icmp.icmp_id)
<< ", seq " << ntohs(icmp.icmp->icmp.icmp_seq)
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_TIMESTAMP> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP time stamp query"
<< ", id " << ntohs(icmp.icmp->icmp.icmp_id)
<< ", seq " << ntohs(icmp.icmp->icmp.icmp_seq)
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_TIMESTAMPREPLY> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP time stamp reply"
<< ", id " << ntohs(icmp.icmp->icmp.icmp_id)
<< ", seq " << ntohs(icmp.icmp->icmp.icmp_seq)
<< ", org " << midnight{ntohl(icmp.icmp->icmp.icmp_otime)}
<< ", recv " << midnight{ntohl(icmp.icmp->icmp.icmp_rtime)}
<< ", xmit " << midnight{ntohl(icmp.icmp->icmp.icmp_ttime)}
<< ", length " << icmp_len(icmp.icmp)
<< endl;
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_DEST_UNREACH, ICMP_PORT_UNREACH> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP " << ipaddr{icmp.icmp->icmp.icmp_ip.ip_dst.s_addr}
<< " udp port " << ntohs(icmp.icmp->udp_hdr.uh_dport) << " unreachable"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_TIME_EXCEEDED, ICMP_EXC_TTL> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP time exceeded in-transit"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
ostream &operator<<(ostream &out, const outicmp<ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME> &icmp)
{
out << icmp.icmp->ip_hdr
<< ": ICMP ip reassembly time exceeded"
<< ", length " << icmp_len(icmp.icmp);
return out;
}
void dump_icmp_dest_unreach(const myicmp *icmp)
{
switch (icmp->icmp.icmp_code) {
case ICMP_PORT_UNREACH:
cout << outicmp<ICMP_DEST_UNREACH, ICMP_PORT_UNREACH>{icmp} << endl;
break;
case ICMP_NET_UNREACH:
cout << outicmp<ICMP_DEST_UNREACH, ICMP_NET_UNREACH>{icmp} << endl;
break;
case ICMP_HOST_UNREACH:
cout << outicmp<ICMP_DEST_UNREACH, ICMP_HOST_UNREACH>{icmp} << endl;
break;
case ICMP_FRAG_NEEDED:
cout << outicmp<ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED>{icmp} << endl;
break;
}
}
void dump_icmp_time_exceeded(const myicmp *icmp)
{
switch (icmp->icmp.icmp_code) {
case ICMP_EXC_TTL:
cout << outicmp<ICMP_TIME_EXCEEDED, ICMP_EXC_TTL>{icmp} << endl;
break;
case ICMP_EXC_FRAGTIME:
cout << outicmp<ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME>{icmp} << endl;
break;
}
}
void dump_icmp_redirect(const myicmp *icmp)
{
switch (icmp->icmp.icmp_code) {
case ICMP_REDIR_HOST:
cout << outicmp<ICMP_REDIRECT, ICMP_REDIR_HOST>{icmp} << endl;
break;
}
}
void hexdump(const unsigned char *ptr, size_t len)
{
stringstream ss;
char buf[16];
for (size_t i = 0; i < len; i += 2) {
if (i % 16) {
ss << ' ';
} else {
sprintf(buf, "\t0x%04x: ", (unsigned int)i);
ss << '\n'
<< buf;
}
sprintf(buf, "%02x%02x", ptr[i], ptr[i + 1]);
ss << buf;
}
string s = ss.str();
if (!s.empty())
s.erase(s.cbegin());
cout << s << endl;
}
void icmpdump(const unsigned char *ptr, size_t len)
{
myicmp *icmp = (myicmp *)ptr;
if (icmp->eth_hdr.h_proto != htons(ETH_P_IP))
return;
if (icmp->ip_hdr.protocol != IPPROTO_ICMP)
return;
switch (icmp->icmp.icmp_type) {
case ICMP_ECHO:
cout << outicmp<ICMP_ECHO>{icmp} << endl;
break;
case ICMP_ECHOREPLY:
cout << outicmp<ICMP_ECHOREPLY>{icmp} << endl;
break;
case ICMP_TIMESTAMP:
cout << outicmp<ICMP_TIMESTAMP>{icmp} << endl;
break;
case ICMP_TIMESTAMPREPLY:
cout << outicmp<ICMP_TIMESTAMPREPLY>{icmp} << endl;
break;
case ICMP_DEST_UNREACH:
dump_icmp_dest_unreach(icmp);
break;
case ICMP_TIME_EXCEEDED:
dump_icmp_time_exceeded(icmp);
break;
case ICMP_REDIRECT:
dump_icmp_redirect(icmp);
break;
}
if (options.hexdump)
hexdump(ptr, len);
}
void do_listen()
{
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0)
throw_unix_error("socket");
if (!options.iface.empty()) {
unsigned int iface_idx = if_nametoindex(options.iface.c_str());
if (iface_idx == 0)
throw_unix_error("if_nametoindex");
struct sockaddr_ll addr;
bzero(&addr, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = iface_idx;
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
throw_unix_error("bind");
}
for (;;) {
unsigned char buf[1024];
ssize_t nrecv = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
if (nrecv < 0)
throw_unix_error("recvfrom");
icmpdump(buf, nrecv);
}
}
int main(int argc, char *argv[])
{
try {
parse_options(argc, argv);
do_listen();
} catch (const runtime_error &e) {
cout << e.what() << endl;
} catch (const invalid_argument &e) {
cout << "usage: " << argv[0] << " [-i interface] [-x]" << endl;
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。