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:
@@ -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,
|
||||
|
||||
60
tcpip.cc
60
tcpip.cc
@@ -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
17
tcpip.h
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user