int debug_verbose = 0;
#define ADDRTOA_BUF (32*2 + 3 + 1 + 3 + 1 + 1)
void dmp_block(char *s, caddr_t bb, int len)
{
int i;
unsigned char *b = bb;
printk("dmp: "
"at %s, len=%d:\n", s, len);
for(i = 0; i < len; i++ /*, c++*/) {
if(!(i % 16)) {
printk(
"debug: @%03x:",
i);
}
printk(" %02x", b[i]);
if(!((i + 1) % 16)) {
printk("\n");
}
}
if(i % 16) {
printk("\n");
}
}
static void
print_ip6(struct ipv6hdr *ip)
{
char buf[ADDRTOA_BUF];
printk("debug: IPV6:");
printk(" prio:%d", ip->priority);
printk(" ver:%d", ip->version);
printk(" flow:%02x%02x%02x", ip->flow_lbl[0], ip->flow_lbl[1], ip->flow_lbl[2]);
printk(" pllen:%d", ntohs(ip->payload_len));
printk(" hopl:%d", ip->hop_limit);
printk(" nexthdr:%d", ip->nexthdr);
if(ip->nexthdr == IPPROTO_UDP)
printk(" (UDP)");
if(ip->nexthdr == IPPROTO_TCP)
printk(" (TCP)");
if(ip->nexthdr == IPPROTO_ICMP)
printk(" (ICMP)");
if(ip->nexthdr == IPPROTO_ICMPV6)
printk(" (ICMP)");
if(ip->nexthdr == IPPROTO_ESP)
printk(" (ESP)");
if(ip->nexthdr == IPPROTO_AH)
printk(" (AH)");
if(ip->nexthdr == IPPROTO_COMP)
printk(" (COMP)");
inet_addrtot(AF_INET6, &ip->saddr, 0, buf, sizeof(buf));
printk(" saddr:%s", buf);
#if 0
if(ip->protocol == IPPROTO_UDP)
printk(":%d",
ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
if(ip->protocol == IPPROTO_TCP)
printk(":%d",
ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
#endif
inet_addrtot(AF_INET6, &ip->daddr, 0, buf, sizeof(buf));
printk(" daddr:%s", buf);
#if 0
if(ip->protocol == IPPROTO_UDP)
printk(":%d",
ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
if(ip->protocol == IPPROTO_TCP)
printk(":%d",
ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
if(ip->protocol == IPPROTO_ICMP)
printk(" type:code=%d:%d",
((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,
((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);
#endif
printk("\n");
if(debug_verbose) {
__u8 *c;
int len = ntohs(ip->payload_len);
c = (__u8 *)&ip[1];
dmp_block("ip_print", c, len);
}
}
static void
print_ip4(struct iphdr *ip)
{
char buf[ADDRTOA_BUF];
struct tcphdr *tcphdr = NULL;
if (!ip)
return;
/* we are taking some liberties here assuming that the IP and TCP
* headers are contiguous in memory */
switch (ip->protocol) {
case IPPROTO_TCP:
case IPPROTO_UDP:
/* NOTE: we only use this for getting port numbers, and they
* are at the same offsets for both tcp and udp headers
*/
tcphdr = (struct tcphdr*)((caddr_t)ip + (ip->ihl << 2));
break;
}
printk("IP:");
printk(" ihl:%d", ip->ihl << 2);
printk(" ver:%d", ip->version);
printk(" tos:%d", ip->tos);
printk(" tlen:%d", ntohs(ip->tot_len));
printk(" id:%d", ntohs(ip->id));
printk(" %s%s%sfrag_off:%d",
ip->frag_off & __constant_htons(IP_CE) ? "CE " : "",
ip->frag_off & __constant_htons(IP_DF) ? "DF " : "",
ip->frag_off & __constant_htons(IP_MF) ? "MF " : "",
(ntohs(ip->frag_off) & IP_OFFSET) << 3);
printk(" ttl:%d", ip->ttl);
printk(" proto:%d", ip->protocol);
if(ip->protocol == IPPROTO_UDP)
printk(" (UDP)");
if(ip->protocol == IPPROTO_TCP)
printk(" (TCP)");
if(ip->protocol == IPPROTO_ICMP)
printk(" (ICMP)");
if(ip->protocol == IPPROTO_ESP)
printk(" (ESP)");
if(ip->protocol == IPPROTO_AH)
printk(" (AH)");
if(ip->protocol == IPPROTO_COMP)
printk(" (COMP)");
printk(" chk:%d", ntohs(ip->check));
addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf));
printk(" saddr:%s", buf);
if(tcphdr)
printk(":%d",
ntohs(tcphdr->source));
addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf));
printk(" daddr:%s", buf);
if(tcphdr)
printk(":%d",
ntohs(tcphdr->dest));
if(ip->protocol == IPPROTO_ICMP)
printk(" type:code=%d:%d",
((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,
((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);
if(ip->protocol == IPPROTO_TCP) {
printk(" seq=%u ack=%u", tcphdr->seq, tcphdr->ack_seq);
if (tcphdr->fin) printk(" FIN");
if (tcphdr->syn) printk(" SYN");
if (tcphdr->rst) printk(" RST");
if (tcphdr->psh) printk(" PSH");
if (tcphdr->ack) printk(" ACK");
if (tcphdr->urg) printk(" URG");
if (tcphdr->ece) printk(" ECE");
if (tcphdr->cwr) printk(" CWR");
}
printk("\n");
if(debug_verbose) {
__u8 *c;
int len = ntohs(ip->tot_len) - ip->ihl*4;
c = ((__u8*)ip) + ip->ihl*4;
dmp_block("ip_print", c, len);
}
}
void print_ip(void *ip)
{
if (((struct iphdr *) ip)->version == 6)
print_ip6((struct ipv6hdr *) ip);
else
print_ip4((struct iphdr *) ip);
}
该函数既可以打印ipv4 报文,又可以打印ipv6报文,如果打开debug_verbose选项还可以打印数据包的详细信息,默认关闭只打印三层头部和四层头部信息,很方便开发者调试。比如已icmp协议为例打印格式如下
IP:
ihl:20
ver:4
tos:0
tlen:60
id:1627
frag_off:0
ttl:127
proto:1
(ICMP)
chk:55287
saddr:3.3.3.2
daddr:10.53.77.53
type:code=0:0