1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Merging my IGMP -sO patch. This adds build_igmp_raw() to easily build IGMP packets and uses it for -sO. Systems respond more when these packets are sent with an actual IGMP header. The RFC says they MUST verify the checksum, so that's most likely why I always got open|filtered instead of open. Since the different IGMP types all seem to have the checksum in the same place in the packet, it should at least tell us if it's supported or not even if the rest of the header is bogus (because the rest of the header has changed a little bit between the versions).

This commit is contained in:
kris
2007-01-17 17:40:16 +00:00
parent 2ce87a0250
commit 9ff574d50e
3 changed files with 85 additions and 0 deletions

View File

@@ -2186,6 +2186,14 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
o.extra_payload, o.extra_payload_length,
&packetlen);
break;
case IPPROTO_IGMP:
packet = build_igmp_raw(&o.decoys[decoy], hss->target->v4hostip(),
o.ttl, ipid, IP_TOS_DEFAULT, false,
o.ipoptions, o.ipoptionslen,
0x11, 0,
o.extra_payload, o.extra_payload_length,
&packetlen);
break;
case IPPROTO_UDP:
packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(),
o.ttl, ipid, IP_TOS_DEFAULT, false,

View File

@@ -1447,6 +1447,66 @@ return build_ip_raw(source, victim,
packetlen);
}
/* Builds an IGMP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not
actually sent by this function. Caller must delete the buffer when
finished with the packet. The packet length is returned in packetlen,
which must be a valid int pointer.
*/
u8 *build_igmp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u8 tos, bool df,
u8 *ipopt, int ipoptlen,
u8 ptype, u8 pcode,
char *data, u16 datalen, u32 *packetlen) {
struct {
u8 igmp_type;
u8 igmp_code;
u16 igmp_cksum;
u32 var; /* changes between types, unused. usually group address. */
u8 data[1500];
} igmp;
u32 *datastart = (u32 *) igmp.data;
int dlen = sizeof(igmp.data);
int igmplen = 0;
char *pkt = (char *) &igmp;
igmp.igmp_type = ptype;
igmp.igmp_code = pcode;
if (ptype == 0x11) { /* Membership Query */
igmplen = 8;
} else if (ptype == 0x12) { /* v1 Membership Report */
igmplen = 8;
} else if (ptype == 0x16) { /* v2 Membership Report */
igmplen = 8;
} else if (ptype == 0x17) { /* v2 Leave Group */
igmplen = 8;
} else if (ptype == 0x22) { /* v3 Membership Report */
igmplen = 8;
} else {
fatal("Unknown igmp type (%d) in build_igmp_raw", ptype);
}
if (datalen > 0) {
igmplen += MIN(dlen, datalen);
memset(datastart, 0, MIN(dlen, datalen));
}
igmp.igmp_cksum = 0;
igmp.igmp_cksum = in_cksum((unsigned short *)pkt, igmplen);
if (o.badsum)
--igmp.igmp_cksum;
return build_ip_raw(source, victim,
IPPROTO_IGMP,
ttl, get_random_u16(), tos, df,
ipopt, ipoptlen,
pkt, igmplen,
packetlen);
}
/* A simple function I wrote to help in debugging, shows the important fields
of a TCP packet*/

17
tcpip.h
View File

@@ -464,6 +464,10 @@ struct icmp
};
#endif /* HAVE_STRUCT_ICMP */
/* Some systems might not have this */
#ifndef IPPROTO_IGMP
#define IPPROTO_IGMP 2
#endif
/* Prototypes */
/* Converts an IP address given in a sockaddr_storage to an IPv4 or
@@ -575,6 +579,19 @@ u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
u16 seq, unsigned short id, u8 ptype, u8 pcode,
char *data, u16 datalen, u32 *packetlen);
/* Builds an IGMP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not
actually sent by this function. Caller must delete the buffer when
finished with the packet. The packet length is returned in packetlen,
which must be a valid int pointer.
*/
u8 *build_igmp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u8 tos, bool df,
u8* ipopt, int ipoptlen,
u8 ptype, u8 pcode,
char *data, u16 datalen, u32 *packetlen);
/* Builds an IP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not