|
|
发表于 2005-6-4 19:24:36
|
显示全部楼层
ipdump.c
- /* I like BSD style better. */
- #define _BSD_SOURCE
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <net/ethernet.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #ifdef IPV6
- # include <netinet/ip6.h>
- #endif
- #include <netinet/tcp.h>
- #include <netinet/udp.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <string.h>
- #include "ipdump.h"
-
- #ifdef IPV6
- # define IP_PACKET_MAX \
- (sizeof (struct ether_header) + sizeof (struct ip6_hdr) + 65535)
- #else
- # define IP_PACKET_MAX \
- (sizeof (struct ether_header) + 65535)
- #endif
-
- static char __recvbuf[IP_PACKET_MAX];
- const void *__packet_data_ptr;
- size_t __packet_data_len;
-
- static int __proc_tcp_packet(const struct tcphdr *tcp, size_t len,
- struct ippacket *packet)
- {
- if (len >= sizeof (struct tcphdr) && len >= tcp->th_off << 2)
- {
- packet->tcp_seq = ntohl(tcp->th_seq);
- packet->tcp_flags = tcp->th_flags;
- packet->sport = ntohs(tcp->th_sport);
- packet->dport = ntohs(tcp->th_dport);
-
- __packet_data_ptr = (const char *)tcp + (tcp->th_off << 2);
- __packet_data_len = len - (tcp->th_off << 2);
- return 0;
- }
- else
- {
- errno = EBADMSG;
- return -1;
- }
- }
-
- static int __proc_udp_packet(const struct udphdr *udp, size_t len,
- struct ippacket *packet)
- {
- if (len >= sizeof (struct udphdr))
- {
- packet->tcp_flags = 0;
- packet->tcp_seq = 0;
- packet->sport = ntohs(udp->uh_sport);
- packet->dport = ntohs(udp->uh_dport);
-
- __packet_data_ptr = udp + 1;
- __packet_data_len = len - sizeof (struct udphdr);
- return 0;
- }
- else
- {
- errno = EBADMSG;
- return -1;
- }
- }
-
- static int __proc_other_packet(const void *other, size_t len,
- struct ippacket *packet)
- {
- packet->tcp_flags = 0;
- packet->tcp_seq = 0;
- packet->dport = packet->sport = 0;
-
- __packet_data_ptr = other;
- __packet_data_len = len;
- return 0;
- }
-
- inline static int __proc_ip4_packet(const struct ip *ip4, size_t len,
- struct ippacket *packet)
- {
- if (len >= sizeof (struct ip) && len >= ip4->ip_hl << 2)
- {
- packet->size = ntohs(ip4->ip_len);
- packet->family = AF_INET;
- packet->saddr.in_addr = ip4->ip_src;
- packet->daddr.in_addr = ip4->ip_dst;
- packet->protocol = ip4->ip_p;
-
- len -= ip4->ip_hl << 2;
- (const char *)ip4 += ip4->ip_hl << 2;
- if (packet->protocol == IPPROTO_TCP)
- return __proc_tcp_packet((const struct tcphdr *)ip4, len, packet);
- else if (packet->protocol == IPPROTO_UDP)
- return __proc_udp_packet((const struct udphdr *)ip4, len, packet);
- else
- return __proc_other_packet(ip4, len, packet);
- }
- else
- {
- errno = EBADMSG;
- return -1;
- }
- }
-
- #ifdef IPV6
- inline static int __proc_ip6_packet(const struct ip6_hdr *ip6, size_t len,
- struct ippacket *packet)
- {
- if (len >= sizeof (struct ip6_hdr))
- {
- packet->size = ntohs(ip6->ip6_plen);
- packet->family = AF_INET6;
- packet->saddr.in6_addr = ip6->ip6_src;
- packet->daddr.in6_addr = ip6->ip6_dst;
- packet->protocol = ip6->ip6_nxt;
-
- len -= sizeof (struct ip6_hdr);
- ip6++;
- if (packet->protocol == IPPROTO_TCP)
- return __proc_tcp_packet((const struct tcphdr *)ip6, len, packet);
- else if (packet->protocol == IPPROTO_UDP)
- return __proc_udp_packet((const struct udphdr *)ip6, len, packet);
- else
- return __proc_other_packet(ip6, len, packet);
- }
- else
- {
- errno = EBADMSG;
- return -1;
- }
- }
- #endif
-
- inline static int __proc_ip_packet(const void *ip, size_t len,
- struct ippacket *packet)
- {
- unsigned char version;
-
- if (len > 0)
- {
- version = *(unsigned char *)ip >> 4;
- if (version == 4)
- return __proc_ip4_packet((const struct ip *)ip, len, packet);
- #ifdef IPV6
- else if (version == 6)
- return __proc_ip6_packet((const struct ip6_hdr *)ip, len, packet);
- #endif
- else
- errno = EAFNOSUPPORT;
- }
- else
- errno = EBADMSG;
-
- return -1;
- }
-
- inline static int __mark_packet_dir(const struct ether_header *ethhdr,
- int sockfd, const char *ifname,
- struct ippacket *packet)
- {
- struct ifreq ifreq;
-
- strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
- if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) >= 0)
- {
- if (memcmp(ifreq.ifr_hwaddr.sa_data, ethhdr->ether_shost,
- ETH_ALEN) == 0)
- packet->direction = IPPACKET_OUT;
- else
- packet->direction = IPPACKET_IN;
-
- return 0;
- }
- else
- return -1;
- }
-
- inline static int __proc_ether_packet(const struct ether_header *ether,
- size_t len, int sockfd,
- const char *ifname,
- struct ippacket *packet)
- {
- if (len >= sizeof (struct ether_header))
- {
- if (ntohs(ether->ether_type) == ETHERTYPE_IP)
- {
- if (__proc_ip_packet(ether + 1, len - sizeof (struct ether_header),
- packet) >= 0)
- {
- if (__mark_packet_dir(ether, sockfd, ifname, packet) >= 0)
- return 0;
- }
- }
- else
- errno = ENOMSG;
- }
- else
- errno = EBADMSG;
-
- return -1;
- }
-
- /**
- * Read an IP pakcet from "sockfd". Make sure that "sockfd" is a
- * Linux packet socket.
- */
- int recv_ip_packet(int sockfd, struct ippacket *packet)
- {
- struct sockaddr sockaddr;
- socklen_t addrlen = sizeof (struct sockaddr);
- ssize_t n = recvfrom(sockfd, __recvbuf, IP_PACKET_MAX, 0,
- &sockaddr, &addrlen);
-
- if (n >= 0)
- {
- n = __proc_ether_packet((struct ether_header *)__recvbuf, n,
- sockfd, sockaddr.sa_data, packet);
- }
-
- return n;
- }
复制代码
ipdump.h
- #ifndef _IPDUMP_H_
- #define _IPDUMP_H_
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-
- #define IPPACKET_IN 1
- #define IPPACKET_OUT 2
-
- struct ippacket
- {
- int direction;
- unsigned short size;
- unsigned short family;
- union
- {
- struct in_addr in_addr;
- #ifdef IPV6
- struct in6_addr in6_addr;
- #endif
- } saddr, daddr;
- unsigned short sport;
- unsigned short dport;
- unsigned int tcp_seq;
- unsigned char tcp_flags;
- unsigned char protocol;
- };
-
- #ifdef __cplusplus
- extern "C"
- {
- #endif
-
- int recv_ip_packet(int sockfd, struct ippacket *packet);
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif
复制代码 |
|