rrl_table_t *rrl_create(size_t size) { if (size == 0) { return NULL; } const size_t tbl_len = sizeof(rrl_table_t) + size * sizeof(rrl_item_t); rrl_table_t *t = malloc(tbl_len); if (!t) return NULL; memset(t, 0, sizeof(rrl_table_t)); t->size = size; rrl_reseed(t); dbg_rrl("%s: created table size '%zu'\n", __func__, t->size); return t; }
int main(int argc, char *argv[]) { plan(10); /* Prepare query. */ knot_pkt_t *query = knot_pkt_new(NULL, 512, NULL); if (query == NULL) { return KNOT_ERROR; /* Fatal */ } knot_dname_t *qname = knot_dname_from_str("beef."); int ret = knot_pkt_put_question(query, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A); knot_dname_free(&qname, NULL); if (ret != KNOT_EOK) { knot_pkt_free(&query); return KNOT_ERROR; /* Fatal */ } /* Prepare response */ uint8_t rbuf[65535]; size_t rlen = sizeof(rbuf); memcpy(rbuf, query->wire, query->size); knot_wire_flags_set_qr(rbuf); rrl_req_t rq; rq.w = rbuf; rq.len = rlen; rq.query = query; rq.flags = 0; /* 1. create rrl table */ rrl_table_t *rrl = rrl_create(RRL_SIZE); ok(rrl != NULL, "rrl: create"); /* 2. set rate limit */ uint32_t rate = 10; rrl_setrate(rrl, rate); is_int(rate, rrl_rate(rrl), "rrl: setrate"); /* 3. setlocks */ ret = rrl_setlocks(rrl, RRL_LOCKS); is_int(KNOT_EOK, ret, "rrl: setlocks"); /* 4. N unlimited requests. */ conf_zone_t *zone_conf = malloc(sizeof(conf_zone_t)); conf_init_zone(zone_conf); zone_conf->name = strdup("rrl."); zone_t *zone = zone_new(zone_conf); struct sockaddr_storage addr; struct sockaddr_storage addr6; sockaddr_set(&addr, AF_INET, "1.2.3.4", 0); sockaddr_set(&addr6, AF_INET6, "1122:3344:5566:7788::aabb", 0); ret = 0; for (unsigned i = 0; i < rate; ++i) { if (rrl_query(rrl, &addr, &rq, zone) != KNOT_EOK || rrl_query(rrl, &addr6, &rq, zone) != KNOT_EOK) { ret = KNOT_ELIMIT; break; } } is_int(0, ret, "rrl: unlimited IPv4/v6 requests"); #ifdef ENABLE_TIMED_TESTS /* 5. limited request */ ret = rrl_query(rrl, &addr, &rq, zone); is_int(0, ret, "rrl: throttled IPv4 request"); /* 6. limited IPv6 request */ ret = rrl_query(rrl, &addr6, &rq, zone); is_int(0, ret, "rrl: throttled IPv6 request"); #else skip_block(2, "Timed tests not enabled"); #endif /* 7. invalid values. */ ret = 0; rrl_create(0); // NULL ret += rrl_setrate(0, 0); // 0 ret += rrl_rate(0); // 0 ret += rrl_setlocks(0,0); // -1 ret += rrl_query(0, 0, 0, 0); // -1 ret += rrl_query(rrl, 0, 0, 0); // -1 ret += rrl_query(rrl, (void*)0x1, 0, 0); // -1 ret += rrl_destroy(0); // -1 is_int(-488, ret, "rrl: not crashed while executing functions on NULL context"); #ifdef ENABLE_TIMED_TESTS /* 8. hopscotch test */ struct runnable_data rd = { 1, rrl, &addr, &rq, zone }; rrl_hopscotch(&rd); ok(rd.passed, "rrl: hashtable is ~ consistent"); /* 9. reseed */ is_int(0, rrl_reseed(rrl), "rrl: reseed"); /* 10. hopscotch after reseed. */ rrl_hopscotch(&rd); ok(rd.passed, "rrl: hashtable is ~ consistent"); #else skip_block(3, "Timed tests not enabled"); #endif zone_free(&zone); knot_pkt_free(&query); rrl_destroy(rrl); return 0; }