int main ( int argc, char *argv[], char *envp[] ) { struct mon_t *mon; struct config_t *config; config = Config_create ( argc, argv ); mon = Monitor_create ( config ); Monitor_run ( mon ); return 0; }
int main(void) { Lexer_source_T ls; Lexer_T l; Config_parser_T cp; Config_T c; struct Greyd_state gs; struct Con con; Blacklist_T bl1, bl2, bl3; struct sockaddr_storage src; int ret; char *conf = "hostname = \"greyd.org\"\n" "banner = \"greyd IP-based SPAM blocker\"\n" "section grey {\n" " enable = 1,\n" " traplist_name = \"test traplist\",\n" " traplist_message = \"you have been trapped\",\n" " grey_expiry = 3600,\n" " stutter = 15\n" "}\n" "section firewall {\n" " driver = \"../drivers/fw_dummy.so\"\n" "}\n" "section database {\n" " driver = \"../drivers/bdb.so\",\n" " path = \"/tmp/greyd_test_grey.db\"\n" "}"; /* Empty existing database file. */ ret = unlink("/tmp/greyd_test_grey.db"); if(ret < 0 && errno != ENOENT) { printf("Error unlinking test Berkeley DB: %s\n", strerror(errno)); } TEST_START(49); c = Config_create(); ls = Lexer_source_create_from_str(conf, strlen(conf)); l = Config_lexer_create(ls); cp = Config_parser_create(l); Config_parser_start(cp, c); /* * Set up the greyd state and blacklists. */ memset(&gs, 0, sizeof(gs)); gs.config = c; gs.max_cons = 4; gs.max_black = 4; gs.blacklists = Hash_create(5, NULL); bl1 = Blacklist_create("blacklist_1", "You (%A) are on blacklist 1", BL_STORAGE_TRIE); bl2 = Blacklist_create("blacklist_2", "You (%A) are on blacklist 2", BL_STORAGE_TRIE); bl3 = Blacklist_create("blacklist_3_with_an_enormously_big_long_long_epic_epicly_long_large_name", "Your address %A\\nis on blacklist 3", BL_STORAGE_TRIE); Hash_insert(gs.blacklists, bl1->name, bl1); Hash_insert(gs.blacklists, bl2->name, bl2); Hash_insert(gs.blacklists, bl3->name, bl3); Blacklist_add(bl1, "10.10.10.1/32"); Blacklist_add(bl1, "10.10.10.2/32"); Blacklist_add(bl2, "10.10.10.1/32"); Blacklist_add(bl2, "10.10.10.2/32"); Blacklist_add(bl2, "2001::fad3:1/128"); Blacklist_add(bl3, "10.10.10.2/32"); Blacklist_add(bl3, "10.10.10.3/32"); Blacklist_add(bl3, "2001::fad3:1/128"); /* * Start testing the connection management. */ memset(&src, 0, sizeof(src)); ((struct sockaddr_in *) &src)->sin_family = AF_INET; inet_pton(AF_INET, "10.10.10.1", &((struct sockaddr_in *) &src)->sin_addr); memset(&con, 0, sizeof(con)); Con_init(&con, 0, &src, &gs); TEST_OK(con.state == 0, "init state ok"); TEST_OK(con.last_state == 0, "last state ok"); TEST_OK(List_size(con.blacklists) == 2, "blacklist matches ok"); TEST_OK(!strcmp(con.src_addr, "10.10.10.1"), "src addr ok"); TEST_OK(con.out_buf != NULL, "out buf ok"); TEST_OK(con.out_p == con.out_buf, "out buf pointer ok"); TEST_OK(con.out_size == CON_OUT_BUF_SIZE, "out buf size ok"); TEST_OK(!strcmp(con.lists, "blacklist_1 blacklist_2"), "list summary ok"); /* The size of the banner. */ TEST_OK(con.out_remaining == 75, "out buf remaining ok"); TEST_OK(gs.clients == 1, "clients ok"); TEST_OK(gs.black_clients == 1, "blacklisted clients ok"); /* * Test the closing of a connection. */ Con_close(&con, &gs); TEST_OK(List_size(con.blacklists) == 0, "blacklist empty ok"); TEST_OK(con.out_buf == NULL, "out buf ok"); TEST_OK(con.out_p == NULL, "out buf pointer ok"); TEST_OK(con.out_size == 0, "out buf size ok"); TEST_OK(con.lists == NULL, "lists ok"); TEST_OK(gs.clients == 0, "clients ok"); TEST_OK(gs.black_clients == 0, "blacklisted clients ok"); /* Test recycling a connection. */ memset(&src, 0, sizeof(src)); ((struct sockaddr_in6 *) &src)->sin6_family = AF_INET6; inet_pton(AF_INET6, "2001::fad3:1", &((struct sockaddr_in6 *) &src)->sin6_addr); Con_init(&con, 0, &src, &gs); TEST_OK(con.state == 0, "init state ok"); TEST_OK(con.last_state == 0, "last state ok"); TEST_OK(List_size(con.blacklists) == 2, "blacklist matches ok"); TEST_OK(!strcmp(con.src_addr, "2001::fad3:1"), "src addr ok"); TEST_OK(con.out_buf != NULL, "out buf ok"); TEST_OK(con.out_p == con.out_buf, "out buf pointer ok"); TEST_OK(con.out_size == CON_OUT_BUF_SIZE, "out buf size ok"); /* * As the 3rd blacklist's name is really long, the summarize lists * function should truncate with a "...". */ TEST_OK(!strcmp(con.lists, "blacklist_2 ..."), "list summary ok"); /* The size of the banner. */ TEST_OK(con.out_remaining == 75, "out buf remaining ok"); TEST_OK(gs.clients == 1, "clients ok"); TEST_OK(gs.black_clients == 1, "blacklisted clients ok"); /* * Test the rejection message building. */ Con_build_reply(&con, "451"); TEST_OK(!strcmp(con.out_p, "451-You (2001::fad3:1) are on blacklist 2\n" "451-Your address 2001::fad3:1\n" "451 is on blacklist 3\n"), "Blacklisted error response ok"); TEST_OK(con.out_remaining == 94, "out buf remaining ok"); /* * Test the writing of the buffer without stuttering. */ time_t now = time(NULL); int con_pipe[2], to_write, nread; char in[CON_OUT_BUF_SIZE]; pipe(con_pipe); con.fd = con_pipe[1]; con.w = now; to_write = con.out_remaining; Con_handle_write(&con, &now, &gs); nread = read(con_pipe[0], in, to_write); in[nread] = '\0'; TEST_OK(!strcmp(in, "451-You (2001::fad3:1) are on blacklist 2\n" "451-Your address 2001::fad3:1\n" "451 is on blacklist 3\n"), "Con write without stuttering ok"); /* * Test the writing with stuttering. Note the reply is longer due * to the stutering adding in \r before each \n if there isn't one * already. */ Con_build_reply(&con, "451"); gs.max_cons = 100; gs.max_black = 100; con.w = now; while(con.out_remaining > 0) { Con_handle_write(&con, &now, &gs); now += con.stutter + 1; } memset(in, 0, sizeof(in)); nread = read(con_pipe[0], in, to_write + 3); in[nread] = '\0'; TEST_OK(!strcmp(in, "451-You (2001::fad3:1) are on blacklist 2\r\n" "451-Your address 2001::fad3:1\r\n" "451 is on blacklist 3\r\n"), "Con write with stuttering ok"); /* Test recycling a connection, which is not on a blacklist. */ Con_close(&con, &gs); memset(&src, 0, sizeof(src)); ((struct sockaddr_in6 *) &src)->sin6_family = AF_INET6; inet_pton(AF_INET6, "fa40::fad3:1", &((struct sockaddr_in6 *) &src)->sin6_addr); Con_init(&con, 0, &src, &gs); TEST_OK(List_size(con.blacklists) == 0, "not on blacklist ok"); /* * Note custom error codes only apply for blacklist connections, so expect * a 451 for this greylisted connections. */ Con_build_reply(&con, "551"); TEST_OK(!strcmp(con.out_p, "451 Temporary failure, please try again later.\r\n"), "greylisted error response ok"); Con_close(&con, &gs); List_destroy(&con.blacklists); /* * Test the connection reading function. */ memset(&src, 0, sizeof(src)); ((struct sockaddr_in *) &src)->sin_family = AF_INET; inet_pton(AF_INET, "10.10.10.1", &((struct sockaddr_in *) &src)->sin_addr); pipe(con_pipe); memset(&con, 0, sizeof(con)); Con_init(&con, con_pipe[0], &src, &gs); char *out = "EHLO greyd.org\r\n"; write(con_pipe[1], out, strlen(out)); Con_handle_read(&con, &now, &gs); /* This should change the state. */ TEST_OK(con.state == CON_STATE_HELO_IN, "Initial state set ok"); Con_handle_read(&con, &now, &gs); TEST_OK(!strcmp(con.in_buf, "EHLO greyd.org"), "con read ok"); TEST_OK(!strcmp(con.helo, "greyd.org"), "helo parsed ok"); TEST_OK(con.state = CON_STATE_HELO_OUT, "state helo out ok"); char *mail_from = "MAIL FROM: <*****@*****.**>\r\n"; write(con_pipe[1], mail_from, strlen(mail_from)); Con_next_state(&con, &now, &gs); TEST_OK(con.state = CON_STATE_MAIL_IN, "state mail in ok"); Con_handle_read(&con, &now, &gs); TEST_OK(!strcmp(con.mail, "*****@*****.**"), "MAIL FROM parsed ok"); TEST_OK(con.state = CON_STATE_MAIL_OUT, "state mail out ok"); char *rcpt = "RCPT TO: [email protected]\r\n"; write(con_pipe[1], rcpt, strlen(rcpt)); Con_next_state(&con, &now, &gs); TEST_OK(con.state = CON_STATE_RCPT_IN, "state rcpt in ok"); Con_handle_read(&con, &now, &gs); TEST_OK(!strcmp(con.rcpt, "*****@*****.**"), "RCPT parsed ok"); TEST_OK(con.state = CON_STATE_RCPT_OUT, "state rcpt out ok"); char *data = "DATA\r\n"; write(con_pipe[1], data, strlen(data)); Con_next_state(&con, &now, &gs); TEST_OK(con.state = CON_STATE_RCPT_IN, "state rcpt in ok"); /* this will goto spam. */ Con_handle_read(&con, &now, &gs); TEST_OK(con.state = CON_STATE_DATA_OUT, "state data out ok"); char *msg = "This is a spam message\r\ndeliver me!\r\n.\r\n"; write(con_pipe[1], msg, strlen(msg)); Con_next_state(&con, &now, &gs); TEST_OK(con.state = CON_STATE_MESSAGE, "state message ok"); Con_handle_read(&con, &now, &gs); TEST_OK(con.state = CON_STATE_CLOSE, "state close ok"); /* This should close the connection. */ Con_next_state(&con, &now, &gs); /* Cleanup. */ List_destroy(&con.blacklists); Hash_destroy(&gs.blacklists); Blacklist_destroy(&bl1); Blacklist_destroy(&bl2); Blacklist_destroy(&bl3); Config_destroy(&c); Config_parser_destroy(&cp); TEST_COMPLETE; }
int main(void) { Config_T c, m; Config_section_T s1, s2, s; Config_value_T v; List_T list; int *count; TEST_START(34); c = Config_create(); TEST_OK((c != NULL), "Config created successfully"); s1 = Config_section_create(SEC1); Config_section_set_str(s1, VAR1, VAL1); Config_section_set_int(s1, VAR2, VAL2); Config_add_section(c, s1); s = Config_get_section(c, SEC1); TEST_OK((s != NULL), "Non-null section fetched as expected"); TEST_OK((strcmp(s->name, SEC1) == 0), "Fetched section matches expected name"); s = Config_get_section(c, "this section doesn't exist"); TEST_OK((s == NULL), "Non-existant section fetched as expected"); Config_destroy(&c); /* * Test the recursive config loading & parsing from a blank config. */ c = Config_create(); Config_load_file(c, "data/config_test1.conf"); s1 = Config_get_section(c, "storage"); TEST_OK((s1 != NULL), "Storage section parsed correctly"); v = Config_section_get(s1, "storage_driver"); TEST_OK((v && (strcmp(v->v.s, "MySQL") == 0)), "Section variable overridden correctly"); v = Config_section_get(s1, "db_host"); TEST_OK((v && (strcmp(v->v.s, "localhost") == 0)), "Section variable overridden correctly"); v = Config_section_get(s1, "db_port"); TEST_OK((v && (v->v.i == 3306)), "Section variable overridden correctly"); v = Config_section_get(s1, "db_name"); TEST_OK((v && (strcmp(v->v.s, "greyd") == 0)), "Section variable overridden correctly"); s2 = Config_get_section(c, CONFIG_DEFAULT_SECTION); TEST_OK((s2 != NULL), "Storage section parsed correctly"); v = Config_section_get(s2, "ip_address"); TEST_OK((v && (strcmp(v->v.s, "1.2.3.4") == 0)), "Default section variable left alone correctly"); v = Config_section_get(s2, "another_global"); TEST_OK((v && (strcmp(v->v.s, "this is overwritten") == 0)), "Default section variable overridden correctly"); v = Config_section_get(s2, "limit"); TEST_OK((v && (v->v.i == 25)), "Default section variable overridden correctly"); s1 = Config_get_section(c, "cache"); TEST_OK((s1 != NULL), "Storage section in included config parsed correctly"); v = Config_section_get(s1, "cache_driver"); TEST_OK((v && (strcmp(v->v.s, "memcached") == 0)), "Section variable overridden correctly"); v = Config_section_get(s1, "port"); TEST_OK((v && (v->v.i == 11211)), "Section variable overridden correctly"); v = Config_section_get(s1, "host"); TEST_OK((v && (strcmp(v->v.s, "localhost") == 0)), "Section variable overridden correctly"); /* Check the hashed included file counts. */ count = (int *) Hash_get(c->processed_includes, "data/config_test1.conf"); TEST_OK((count && (*count == 1)), "First config include file count as expected"); count = (int *) Hash_get(c->processed_includes, "data/config_test2.conf"); TEST_OK((count && (*count == 1)), "Second config include file count as expected"); count = (int *) Hash_get(c->processed_includes, "data/config_test3.conf"); TEST_OK((count && (*count == 1)), "Third config include file count as expected"); TEST_OK((Queue_size(c->includes) == 0), "Include file to process queue is empty as expected"); Config_set_str(c, "mystr1", NULL, "mystr value"); Config_set_str(c, "mystr1", "mysection1", "mystr1 value"); Config_set_int(c, "myint1", NULL, 4321); Config_set_int(c, "myint1", "mysection2", 1234); TEST_OK(!strcmp(Config_get_str(c, "mystr1", NULL, NULL), "mystr value"), "str set/get ok"); TEST_OK(!strcmp(Config_get_str(c, "mystr1", "mysection1", NULL), "mystr1 value"), "str set/get ok"); TEST_OK(Config_get_int(c, "myint1", NULL, 0) == 4321, "int set/get ok"); TEST_OK(Config_get_int(c, "myint1", "mysection2", 0) == 1234, "int set/get ok"); m = Config_create(); Config_set_str(m, "mystr1", NULL, "overwritten"); Config_set_str(m, "mystr1", "mysection6", "preserved"); Config_set_int(m, "myint1", "mysection2", 4); Config_set_int(m, "myint86", NULL, 4); Config_merge(m, c); TEST_OK(!strcmp(Config_get_str(m, "mystr1", NULL, NULL), "mystr value"), "str overwritten ok"); TEST_OK(!strcmp(Config_get_str(m, "mystr1", "mysection1", NULL), "mystr1 value"), "new str/section ok"); Config_delete(m, "mystr1", "mysection1"); TEST_OK(Config_get_str(m, "mystr1", "mysection1", NULL) == NULL, "str deleted ok"); TEST_OK(Config_get_int(m, "myint86", NULL, 0) == 4, "new int ok"); TEST_OK(Config_get_int(m, "myint1", "mysection2", 0) == 1234, "int overwrite"); Config_delete(m, "myint1", "mysection2"); TEST_OK(Config_get_int(m, "myint1", "mysection2", -1000) == -1000, "int deleted ok"); Config_append_list_str(m, "newlist", "newsection", "my str var"); Config_append_list_str(m, "newlist", "newsection", "another var"); list = Config_get_list(m, "newlist", "newsection"); TEST_OK((list != NULL), "list created successfully"); TEST_OK((List_size(list) == 2), "list entries ok"); Config_delete(m, "newlist", "newsection"); list = Config_get_list(m, "newlist", "newsection"); TEST_OK((list == NULL), "list deleted successfully"); /* Test deleting a non-existant value. */ Config_delete(m, "i dont exist", "no section"); Config_destroy(&c); Config_destroy(&m); TEST_COMPLETE; }