diff --git a/scan_engine.cc b/scan_engine.cc index 0e7aedd75..c0f574f9f 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -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, diff --git a/tcpip.cc b/tcpip.cc index 2febbdc30..7e2da12a6 100644 --- a/tcpip.cc +++ b/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*/ diff --git a/tcpip.h b/tcpip.h index df14b36e7..5cd53d6a2 100644 --- a/tcpip.h +++ b/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