669 lines
22 KiB
C
669 lines
22 KiB
C
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (C) 1999 - 2000 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// Module:
|
|
// parser.c
|
|
//
|
|
// Abstract:
|
|
// This sample illustrates how to use the new Winsock 2 ioctls:
|
|
// SIO_RCVALL, SIO_RCVALL_MCAST, and SIO_RCVALL_IGMPMCAST.
|
|
//
|
|
// This module includes routines for parsing the IP headers read.
|
|
// Not all protocol headers are parsed, just the most common ones
|
|
// (IPv4, TCP, UDP, and IGMP). You can easily extend this to parse
|
|
// any protocol headers not covered. Additionally, code for parsing
|
|
// IPv6 headers is not provided as the SIO_RCVALL* ioctls are not
|
|
// currently supported by the IPv6 stack.
|
|
//
|
|
// Usage:
|
|
// See rcvall.c
|
|
//
|
|
// Build:
|
|
// See rcvall.c
|
|
//
|
|
//
|
|
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "parser.h"
|
|
#include "resolve.h"
|
|
#include "iphdr.h"
|
|
|
|
//
|
|
// A list of protocol types in the IP protocol header
|
|
//
|
|
char *szProto[] = {"Reserved", // 0
|
|
"ICMP", // 1
|
|
"IGMP", // 2
|
|
"GGP", // 3
|
|
"IP", // 4
|
|
"ST", // 5
|
|
"TCP", // 6
|
|
"UCL", // 7
|
|
"EGP", // 8
|
|
"IGP", // 9
|
|
"BBN-RCC-MON", // 10
|
|
"NVP-II", // 11
|
|
"PUP", // 12
|
|
"ARGUS", // 13
|
|
"EMCON", // 14
|
|
"XNET", // 15
|
|
"CHAOS", // 16
|
|
"UDP", // 17
|
|
"MUX", // 18
|
|
"DCN-MEAS", // 19
|
|
"HMP", // 20
|
|
"PRM", // 21
|
|
"XNS-IDP", // 22
|
|
"TRUNK-1", // 23
|
|
"TRUNK-2", // 24
|
|
"LEAF-1", // 25
|
|
"LEAF-2", // 26
|
|
"RDP", // 27
|
|
"IRTP", // 28
|
|
"ISO-TP4", // 29
|
|
"NETBLT", // 30
|
|
"MFE-NSP", // 31
|
|
"MERIT-INP", // 32
|
|
"SEP", // 33
|
|
"3PC", // 34
|
|
"IDPR", // 35
|
|
"XTP", // 36
|
|
"DDP", // 37
|
|
"IDPR-CMTP", // 38
|
|
"TP++", // 39
|
|
"IL", // 40
|
|
"SIP", // 41
|
|
"SDRP", // 42
|
|
"SIP-SR", // 43
|
|
"SIP-FRAG", // 44
|
|
"IDRP", // 45
|
|
"RSVP", // 46
|
|
"GRE", // 47
|
|
"MHRP", // 48
|
|
"BNA", // 49
|
|
"SIPP-ESP", // 50
|
|
"SIPP-AH", // 51
|
|
"I-NLSP", // 52
|
|
"SWIPE", // 53
|
|
"NHRP", // 54
|
|
"unassigned", // 55
|
|
"unassigned", // 56
|
|
"unassigned", // 57
|
|
"unassigned", // 58
|
|
"unassigned", // 59
|
|
"unassigned", // 60
|
|
"any host internal protocol", // 61
|
|
"CFTP", // 62
|
|
"any local network", // 63
|
|
"SAT-EXPAK", // 64
|
|
"KRYPTOLAN", // 65
|
|
"RVD", // 66
|
|
"IPPC", // 67
|
|
"any distributed file system", // 68
|
|
"SAT-MON", // 69
|
|
"VISA", // 70
|
|
"IPCV", // 71
|
|
"CPNX", // 72
|
|
"CPHB", // 73
|
|
"WSN", // 74
|
|
"PVP", // 75
|
|
"BR-SAT-MON", // 76
|
|
"SUN-ND", // 77
|
|
"WB-MON", // 78
|
|
"WB-EXPAK", // 79
|
|
"ISO-IP", // 80
|
|
"VMTP", // 81
|
|
"SECURE-VMTP",// 82
|
|
"VINES", // 83
|
|
"TTP", // 84
|
|
"NSFNET-IGP", // 85
|
|
"DGP", // 86
|
|
"TCF", // 87
|
|
"IGRP", // 88
|
|
"OSPFIGP", // 89
|
|
"Sprite-RPC", // 90
|
|
"LARP", // 91
|
|
"MTP", // 92
|
|
"AX.25", // 93
|
|
"IPIP", // 94
|
|
"MICP", // 95
|
|
"SCC-SP", // 96
|
|
"ETHERIP", // 97
|
|
"ENCAP", // 98
|
|
"any private encryption scheme", // 98
|
|
"GMTP" // 99
|
|
};
|
|
|
|
//
|
|
// The types of IGMP messages
|
|
//
|
|
char *szIgmpType[] = {"Invalid - 0",
|
|
"Host Membership Query",
|
|
"Host Membership Report",
|
|
"Invalid - 3",
|
|
"Invalid - 4",
|
|
"Invalid - 5",
|
|
"Version 2 Membership Report",
|
|
"Leave Group"
|
|
};
|
|
|
|
//
|
|
// IGMPv3 Modes
|
|
//
|
|
char *szIgmpMode[] = {"Invalid-Mode-0",
|
|
"MODE_IS_INCLUDE",
|
|
"MODE_IS_EXCLUDE",
|
|
"CHANGE_TO_INCLUDE_MODE",
|
|
"CHANGE_TO_EXCLUDE_MODE",
|
|
"ALLOW_NEW_SOURCES",
|
|
"BLOCK_OLD_SOURCES"
|
|
"Invalid-Mode-7",
|
|
"Invalid-Mode-8"
|
|
};
|
|
|
|
//
|
|
// Function: PrintIpv4Header
|
|
//
|
|
// Description:
|
|
// Prints the IPv4 header to the console in a readable form.
|
|
//
|
|
void
|
|
PrintIpv4Header(
|
|
IPV4_HDR *v4hdr,
|
|
int len
|
|
)
|
|
{
|
|
SOCKADDR_IN sa4 = {0};
|
|
char srcaddr[INET_ADDRSTRLEN] = {'\0'},
|
|
destaddr[INET_ADDRSTRLEN] = {'\0'};
|
|
|
|
UNREFERENCED_PARAMETER( len );
|
|
|
|
printf("IPv4: Version %2d : Length %2d : Type of Service 0x%02x\n",
|
|
HI_BYTE(v4hdr->ip_verlen), LO_BYTE(v4hdr->ip_verlen) * 4, v4hdr->ip_tos);
|
|
printf("IPv4: Total Length %5d : ID 0x%04x : Time to Live %d\n",
|
|
ntohs(v4hdr->ip_totallength), ntohs(v4hdr->ip_offset), v4hdr->ip_ttl);
|
|
// Make sure protocol value is in the array of szProto
|
|
if ((v4hdr->ip_protocol >= 0) && (v4hdr->ip_protocol < (sizeof(szProto) / sizeof(char *))))
|
|
printf("IPv4: Protocol %9s : Checksum 0x%04x\n",
|
|
szProto[v4hdr->ip_protocol], v4hdr->ip_checksum);
|
|
else
|
|
printf("IPv4: Protocol %9d : Checksum 0x%04x\n",
|
|
v4hdr->ip_protocol, v4hdr->ip_checksum);
|
|
|
|
sa4.sin_family = AF_INET;
|
|
sa4.sin_port = 0;
|
|
sa4.sin_addr.s_addr = v4hdr->ip_srcaddr;
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), srcaddr, INET_ADDRSTRLEN);
|
|
|
|
sa4.sin_addr.s_addr = v4hdr->ip_destaddr;
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), destaddr, INET_ADDRSTRLEN);
|
|
|
|
printf("IPv4: Source Address %s\nIPv4: Destination Address %s\n",
|
|
srcaddr, destaddr);
|
|
|
|
}
|
|
|
|
//
|
|
// Function: PrintUdpHeader
|
|
//
|
|
// Description:
|
|
// Prints the UDP header in readable form to the console.
|
|
//
|
|
void
|
|
PrintUdpHeader(
|
|
UDP_HDR *udphdr,
|
|
int len
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER( len );
|
|
|
|
printf("UDP: Source Port %6d : Destination Port %6d\n",
|
|
ntohs(udphdr->src_portno), ntohs(udphdr->dest_portno));
|
|
printf("UDP: Length %8d : Checksum 0x4%x\n",
|
|
ntohs(udphdr->udp_length), udphdr->udp_checksum);
|
|
}
|
|
|
|
//
|
|
// Function: PrintTcpHeader
|
|
//
|
|
// Description:
|
|
// Prints the TCP header in readable form to the console.
|
|
//
|
|
void
|
|
PrintTcpHeader(
|
|
TCP_HDR *tcphdr,
|
|
int len
|
|
)
|
|
{
|
|
USHORT flags = 0;
|
|
|
|
UNREFERENCED_PARAMETER( len );
|
|
|
|
printf("TCP: Source Port %6d : Destination Port %6d\n",
|
|
ntohs(tcphdr->src_portno), ntohs(tcphdr->dest_portno));
|
|
printf("TCP: Sequence Num %10lu : ACK %10lu\n",
|
|
ntohl(tcphdr->seq_num), ntohl(tcphdr->ack_num));
|
|
printf("TCP: Length %6d : Flags ",
|
|
((ntohs(tcphdr->lenflags) >> 12) * 4));
|
|
|
|
flags = (ntohs(tcphdr->lenflags) & 0x3F);
|
|
if (flags & 0x20)
|
|
printf("URG ");
|
|
if (flags & 0x10)
|
|
printf("ACK ");
|
|
if (flags & 0x08)
|
|
printf("PSH ");
|
|
if (flags & 0x04)
|
|
printf("RST ");
|
|
if (flags & 0x02)
|
|
printf("SYN ");
|
|
if (flags & 0x01)
|
|
printf("FIN ");
|
|
printf("\n");
|
|
printf("TCP: Window Size %10d : Checksum 0x%04x : Urgent Pointer 0x%04x\n",
|
|
ntohs(tcphdr->window_size), ntohs(tcphdr->tcp_checksum),
|
|
ntohs(tcphdr->tcp_urgentptr));
|
|
}
|
|
|
|
//
|
|
// Function: PrintIgmpHeader
|
|
//
|
|
// Description:
|
|
// This routine prints an IGMP header to the console. For IGMPv1 and IGMPv2
|
|
// this is fairly trivial as the headers are mostly the same and are the
|
|
// same size. For IGMPv3 this is considerably more difficult as the packets
|
|
// can be variable length which requires many additional checks to make sure
|
|
// the packet lengths are consistent.
|
|
//
|
|
void
|
|
PrintIgmpHeader(
|
|
IGMP_HDR *igmphdr,
|
|
int len
|
|
)
|
|
{
|
|
SOCKADDR_IN sa4 = {0};
|
|
char addrbuf[INET_ADDRSTRLEN] = {'\0'};
|
|
int i = 0;
|
|
|
|
if (
|
|
#ifdef INEFFICIENT
|
|
// In case you need to modify the code, the following conditional will
|
|
// distinguish between individual messages and versions...
|
|
|
|
// IGMP membership query v1
|
|
( (igmphdr->version_type == 0x11) && (igmphdr->max_resp_time == 0) && (len == sizeof(IGMP_HDR)) ) ||
|
|
|
|
// IGMP membership report v1
|
|
( (igmphdr->version_type == 0x12) && (igmphdr->max_resp_time == 0) && (len == sizeof(IGMP_HDR)) ) ||
|
|
|
|
// IGMP membership query v2
|
|
( (igmphdr->version_type == 0x11) && (igmphdr->max_resp_time != 0) && (len == sizeof(IGMP_HDR)) ) ||
|
|
|
|
// IGMP membership report v2
|
|
( (igmphdr->version_type == 0x16) && (igmphdr->max_resp_time != 0) && (len == sizeof(IGMP_HDR)) ) ||
|
|
|
|
// IGMP leave group (v2)
|
|
( igmphdr->version_type == 0x17 )
|
|
#else
|
|
( len == sizeof(IGMP_HDR) )
|
|
#endif
|
|
)
|
|
{
|
|
if ( (LO_BYTE(igmphdr->version_type) >= 0) &&
|
|
(LO_BYTE(igmphdr->version_type) < (sizeof(szIgmpType) / sizeof(char *)))
|
|
)
|
|
printf("IGMP: Version %2d : Type %16s : Maximum Response Time %d\n",
|
|
HI_BYTE(igmphdr->version_type), szIgmpType[LO_BYTE(igmphdr->version_type)],
|
|
igmphdr->max_resp_time);
|
|
else
|
|
printf("IGMP: Version %2d : Type %16d : Maximum Response Time %d\n",
|
|
HI_BYTE(igmphdr->version_type), LO_BYTE(igmphdr->version_type),
|
|
igmphdr->max_resp_time);
|
|
|
|
// Print the group address
|
|
sa4.sin_family = AF_INET;
|
|
sa4.sin_addr.s_addr = igmphdr->group_addr;
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), addrbuf, INET_ADDRSTRLEN);
|
|
printf("IGMP: Checksum 0x%04x : Group %s\n",
|
|
igmphdr->checksum, addrbuf);
|
|
}
|
|
else if ( (igmphdr->version_type == 0x11) && (len > sizeof(IGMP_HDR)) )
|
|
{
|
|
IGMP_HDR_QUERY_V3 *query=NULL;
|
|
|
|
//
|
|
// IGMP membership query v3
|
|
//
|
|
|
|
query = (IGMP_HDR_QUERY_V3 *)igmphdr;
|
|
|
|
// Verify data is big enough to contain the entire packet
|
|
if ( (len < sizeof(IGMP_HDR_QUERY_V3)) ||
|
|
(len < (int) (sizeof(IGMP_HDR_QUERY_V3) + (sizeof(ULONG) * (query->num_sources-1))) )
|
|
)
|
|
{
|
|
printf("IGMP: Invalid packet\n");
|
|
return;
|
|
}
|
|
|
|
printf("IGMP: Version 3 : Type Membership Query : Maximum Response Time %d\n",
|
|
query->max_resp_time);
|
|
|
|
// Print the group address
|
|
sa4.sin_family = AF_INET;
|
|
sa4.sin_addr.s_addr = query->group_addr;
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), addrbuf, INET_ADDRSTRLEN);
|
|
printf("IGMP: Checksum 0x%04x : Group %s\n",
|
|
query->checksum, addrbuf);
|
|
|
|
printf("IGMP: Resv 0x%1x : S 0x%1x : QRV 0x%1x : QQIC 0x%02x\n",
|
|
(query->resv_suppr_robust >> 4),
|
|
((query->resv_suppr_robust >> 3) & 0x1),
|
|
(query->resv_suppr_robust && 0x7),
|
|
query->qqi
|
|
);
|
|
printf("IGMP: Source Count: %lu\n",
|
|
ntohl(query->num_sources));
|
|
|
|
// Print out the array of source addresses
|
|
for(i=0; i < (int)ntohl(query->num_sources) ;i++)
|
|
{
|
|
sa4.sin_addr.s_addr = query->sources[i];
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), addrbuf, INET_ADDRSTRLEN);
|
|
printf("IGMP: Source [%02d] %s\n", i, addrbuf);
|
|
}
|
|
|
|
}
|
|
else if ( (igmphdr->version_type == 0x22) && (len > sizeof(IGMP_HDR)) )
|
|
{
|
|
IGMP_HDR_REPORT_V3 *report=NULL;
|
|
IGMP_GROUP_RECORD_V3 *group=NULL;
|
|
ULONG totalrecordslen = 0,
|
|
recordlen = 0,
|
|
offset = 0;
|
|
char *ptr=NULL;
|
|
int j = 0;
|
|
|
|
//
|
|
// IGMP membership report v3
|
|
//
|
|
|
|
report = (IGMP_HDR_REPORT_V3 *)igmphdr;
|
|
|
|
// Safe to touch these fields as we already know the packet is at least
|
|
// 8 bytes in length.
|
|
printf("IGMP: Membership Report : Reserved 0x%02x : Checksum 0x%04x\n",
|
|
report->reserved1, report->checksum);
|
|
printf("IGMP: Resereved 0x%04x : Number of Records %d\n",
|
|
report->reserved2, ntohs(report->num_records));
|
|
|
|
// Get a pointer to start of records;
|
|
ptr = (char *)report + sizeof(IGMP_HDR_REPORT_V3);
|
|
offset = 0;
|
|
i = 0;
|
|
|
|
totalrecordslen = len - sizeof(IGMP_HDR_REPORT_V3);
|
|
|
|
// Go through each of the IGMP group records
|
|
while (offset < totalrecordslen)
|
|
{
|
|
// Get a pointer to the group record
|
|
group = (IGMP_GROUP_RECORD_V3 *) &ptr[offset];
|
|
|
|
// Make sure we have enough for group record header (note: we subtract
|
|
// off the size of the one source which may or may not be present).
|
|
// The goal is to make sure we can safely read the num_sources field.
|
|
if ((offset + sizeof(IGMP_GROUP_RECORD_V3) - sizeof(ULONG)) > totalrecordslen)
|
|
{
|
|
printf("IGMP: Invalid packet\n");
|
|
break;
|
|
}
|
|
|
|
// Compute size of this record
|
|
recordlen = sizeof(IGMP_GROUP_RECORD_V3) +
|
|
(sizeof(ULONG) * (ntohs(group->num_sources) - 1)) +
|
|
group->aux_data_len;
|
|
offset += recordlen;
|
|
|
|
// Make sure we have enough for the whole record
|
|
if (offset > totalrecordslen)
|
|
{
|
|
printf("IGMP: Invalid packet\n");
|
|
break;
|
|
}
|
|
|
|
// Make sure 'type' is in the array of strings if not just print the
|
|
// integer value
|
|
if ((group->type >= 0) && (group->type < (sizeof(szIgmpMode) / sizeof(char *))) )
|
|
printf("IGMP RECORD [%02d]: Type %16s : Aux Data Len %d\n",
|
|
i, szIgmpMode[group->type], group->aux_data_len);
|
|
else
|
|
printf("IGMP RECORD [%02d]: Type %16d : Aux Data Len %d\n",
|
|
i, group->type, group->aux_data_len);
|
|
|
|
// Print the group address
|
|
sa4.sin_family = AF_INET;
|
|
sa4.sin_addr.s_addr = group->group_addr;
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), addrbuf, INET_ADDRSTRLEN);
|
|
printf("IGMP RECORD [%02d]: Number of Sources %9d : Group Address %s\n",
|
|
i, ntohs(group->num_sources), addrbuf);
|
|
|
|
// Print the list of sources
|
|
for(j=0; j < ntohs(group->num_sources) ;j++)
|
|
{
|
|
sa4.sin_addr.s_addr = group->source_addr[j];
|
|
FormatAddress((SOCKADDR *)&sa4, sizeof(sa4), addrbuf, INET_ADDRSTRLEN);
|
|
printf("IGMP_RECORD [%02d]: Source [%02d] %s\n",
|
|
i, j, addrbuf);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("IGMP: Invalid packet\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: CheckForMatchIPv4
|
|
//
|
|
// Description:
|
|
// This routine determines whether the received packet matches the filter
|
|
// specified. The source and destination IPv4 addresses as well as the
|
|
// source and destination ports can be filtered on. Note that for protocols
|
|
// that don't contain port numbers (e.g. IGMP) then the port comparison
|
|
// portion of the code will automatically fail.
|
|
//
|
|
int
|
|
CheckForMatchIPv4(
|
|
unsigned int filtermask,
|
|
SOCKADDR *srcfilter,
|
|
SOCKADDR *destfilter,
|
|
IPV4_HDR *hdr,
|
|
char *nexthdr
|
|
)
|
|
{
|
|
PORT_HDR *ports=NULL;
|
|
int match = 0;
|
|
|
|
match = 1;
|
|
ports = (PORT_HDR *)nexthdr;
|
|
|
|
// Try to match source address if specified
|
|
if ((match) && (filtermask & FILTER_MASK_SOURCE_ADDRESS))
|
|
{
|
|
match = !memcmp(
|
|
&((SOCKADDR_IN *)srcfilter)->sin_addr.s_addr,
|
|
&hdr->ip_srcaddr,
|
|
sizeof(unsigned long)
|
|
);
|
|
}
|
|
// Try to match the destination address if specified
|
|
if ((match) && (filtermask & FILTER_MASK_DESTINATION_ADDRESS))
|
|
{
|
|
match = !memcmp(
|
|
&((SOCKADDR_IN *)destfilter)->sin_addr.s_addr,
|
|
&hdr->ip_destaddr,
|
|
sizeof(unsigned long)
|
|
);
|
|
}
|
|
// Try to match source port if specified and ports is not NULL (i.e. its TCP or UDP)
|
|
if ((match) && (ports) && (filtermask & FILTER_MASK_SOURCE_PORT))
|
|
{
|
|
match = ( ((SOCKADDR_IN *)srcfilter)->sin_port == ports->src_portno );
|
|
}
|
|
else if ((ports == NULL) && (filtermask & FILTER_MASK_SOURCE_PORT))
|
|
{
|
|
match = 0;
|
|
}
|
|
|
|
// Try to match destination port if specified and ports is not NULL (i.e. its TCP or UDP)
|
|
if ((match) && (ports) && (filtermask & FILTER_MASK_DESTINATION_PORT))
|
|
{
|
|
match = ( ((SOCKADDR_IN *)destfilter)->sin_port == ports->dest_portno );
|
|
}
|
|
else if ((ports == NULL) && (filtermask & FILTER_MASK_DESTINATION_PORT))
|
|
{
|
|
match = 0;
|
|
}
|
|
|
|
return match;
|
|
}
|
|
|
|
//
|
|
// Function: DecodeIPHeader
|
|
//
|
|
// Description:
|
|
// This function takes a pointer to an IP header and prints
|
|
// it out in a readable form.
|
|
//
|
|
int
|
|
DecodeIPHeader(
|
|
char *buf,
|
|
int buflen,
|
|
unsigned long filtermask,
|
|
SOCKADDR *srcfilter,
|
|
SOCKADDR *destfilter
|
|
)
|
|
{
|
|
IPV4_HDR *ipv4hdr=NULL;
|
|
UDP_HDR *udphdr=NULL;
|
|
TCP_HDR *tcphdr=NULL;
|
|
IGMP_HDR *igmphdr=NULL;
|
|
BOOL bFilterMatch = FALSE;
|
|
int ip_version = 0,
|
|
ipv4_header_len = 0;
|
|
|
|
printf("buflen = %d\n", buflen);
|
|
|
|
// Make sure we can at least extract the IP version
|
|
if (buflen < sizeof(char))
|
|
{
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
// Check the IP version
|
|
ip_version = HI_BYTE(*buf);
|
|
|
|
if (ip_version == 4)
|
|
{
|
|
// Verify the buffer is large enough
|
|
if (buflen < sizeof(IPV4_HDR))
|
|
{
|
|
fprintf(stderr, "Received buffer too small!\n");
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
// Get length of IPv4 header to determine where next protocol header begins
|
|
ipv4_header_len = LO_BYTE(*buf) * 4;
|
|
|
|
ipv4hdr = (IPV4_HDR *)buf;
|
|
|
|
bFilterMatch = TRUE;
|
|
|
|
// Test for match (if filter specified) and get pointer to next protocol header
|
|
switch (ipv4hdr->ip_protocol)
|
|
{
|
|
case IPPROTO_UDP:
|
|
|
|
udphdr = (UDP_HDR *) &buf[ipv4_header_len];
|
|
if (filtermask)
|
|
bFilterMatch = CheckForMatchIPv4(filtermask, srcfilter, destfilter, ipv4hdr, (char *)udphdr);
|
|
break;
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
tcphdr = (TCP_HDR *) &buf[ipv4_header_len];
|
|
if (filtermask)
|
|
bFilterMatch = CheckForMatchIPv4(filtermask, srcfilter, destfilter, ipv4hdr, (char *)tcphdr);
|
|
break;
|
|
|
|
case IPPROTO_IGMP:
|
|
|
|
igmphdr = (IGMP_HDR *) &buf[ipv4_header_len];
|
|
if (filtermask)
|
|
bFilterMatch = CheckForMatchIPv4(filtermask, srcfilter, destfilter, ipv4hdr, NULL);
|
|
break;
|
|
|
|
default:
|
|
|
|
// Don't know about this protocol so if we're filtering, don't print it
|
|
if (filtermask)
|
|
bFilterMatch = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
// If this packet matches, then print it
|
|
if (bFilterMatch)
|
|
{
|
|
PrintIpv4Header(ipv4hdr, buflen);
|
|
|
|
switch (ipv4hdr->ip_protocol)
|
|
{
|
|
case IPPROTO_UDP:
|
|
|
|
PrintUdpHeader(udphdr, buflen - ipv4_header_len);
|
|
break;
|
|
|
|
case IPPROTO_TCP:
|
|
|
|
PrintTcpHeader(tcphdr, buflen - ipv4_header_len);
|
|
break;
|
|
|
|
case IPPROTO_IGMP:
|
|
|
|
PrintIgmpHeader(igmphdr, buflen - ipv4_header_len);
|
|
break;
|
|
|
|
default:
|
|
|
|
printf(" No decoder for protocol: %d\n", ipv4hdr->ip_protocol);
|
|
break;
|
|
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
}
|
|
else if (ip_version == 6)
|
|
{
|
|
fprintf(stderr, "Currently don't support decoding IPv6 headers\n");
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|