/**
* ddos/server.c
* Copyright (C) 2008 Markus Broeker
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
int set_proc_limit (int);
#define SVPORT "4000"
#define MAXLEN 1024
#define MAXMEM 200
int server_write (int client_socket, char *s)
{
if (s == NULL) {
fprintf (stderr, "Invalid data: s == NULL");
return -1;
}
return write (client_socket, s, strlen (s));
}
int server_init (char *port)
{
int server_socket, status;
struct addrinfo hints;
struct addrinfo *result, *rp;
int yes = 1, no = 0;
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo (NULL, "4000", &hints, &result) < 0) {
perror ("GETADDRINFO");
return -1;
}
server_socket = -1;
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((server_socket = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) {
perror ("SOCKET");
continue;
}
// enable rebinding of the socket
if (setsockopt (server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) == -1) {
perror ("setsockopt");
return -1;
}
// disable IPV6ONLY, eg enable an hybrid socket
if (rp->ai_family == AF_INET6)
if (setsockopt (server_socket, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof (int)) == -1)
perror ("setsockopt");
if ((bind (server_socket, rp->ai_addr, rp->ai_addrlen)) == -1) {
perror ("BIND");
close (server_socket);
server_socket = -1;
} else {
printf ("bound to an %s socket on port %s\n", (rp->ai_family == AF_INET6) ? "IPv6" : "IPv4", port);
}
}
status = listen (server_socket, 10);
if (status != 0) {
perror ("LISTEN");
return -1;
}
if (result != NULL)
freeaddrinfo (result);
return server_socket;
}
int main (int argc, char **argv)
{
int server_socket;
int client_socket;
char message[MAXLEN + 1];
int len;
pid_t pid;
pid_t parent_pid;
if ((server_socket = server_init (SVPORT)) < 0)
return EXIT_FAILURE;
int links = 0;
parent_pid = getpid ();
/*
* Child quits immediately, father mustn't wait
*/
signal (SIGCHLD, SIG_IGN);
if (set_proc_limit (200) != 0) {
printf ("Cannot set the process limit\n");
return EXIT_FAILURE;
}
for (;;) {
client_socket = accept (server_socket, NULL, NULL);
printf ("PARENT PID = %d\n", parent_pid);
pid = fork ();
switch (pid) {
case 0: /* Child */
close (server_socket);
if ((len = read (client_socket, message, MAXLEN)) == -1)
break;
message[len] = '\0';
len = server_write (client_socket, "Please wait...\r\n");
sleep (10);
printf ("DELETING LINK [%04d] %04d\n", getpid (), links--);
shutdown (client_socket, SHUT_RDWR);
close (client_socket);
return 1;
case -1:
perror ("Fork Error");
close (client_socket);
/*
* server is still alive and will continue when resources are available
*/
break;
default: /* PID > 0 */
close (client_socket);
printf ("Starting LINK [%04d] %04d\n", pid, links++);
}
}
return close (server_socket);
}