diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-05-26 09:51:06 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-05-26 09:51:06 +0400 |
commit | 33ca7f48ec3369301c1f0ce4aa1abe306151af76 (patch) | |
tree | ed8a4a9a27cc070e732ec5c11b7b34f630ee6e3e /accel-pppd/ctrl | |
parent | b002a1bdc060bf26497ea65174bfb66468560abb (diff) | |
download | accel-ppp-33ca7f48ec3369301c1f0ce4aa1abe306151af76.tar.gz accel-ppp-33ca7f48ec3369301c1f0ce4aa1abe306151af76.zip |
ipoe: send NAK after number of unreplied REQUESTs
After introduction offer-delay accel-ppp stopped to answer NAK for REQUESTs if requested session is not existing
to give chance other servers to reply. But this causes that some broken clients enter to infinite REQUEST loop.
This patch corrects this issue, so if offer-delay is not configured (means that this is only server in the net) or
after receiving few REQUESTs accel-ppp send NAK for non-existing sessions.
Diffstat (limited to 'accel-pppd/ctrl')
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 62 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.h | 1 |
2 files changed, 59 insertions, 4 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 6855fbaf..e13ec45a 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -90,6 +90,13 @@ struct delay { int delay; }; +struct request_item { + struct list_head entry; + uint32_t xid; + time_t expire; + int cnt; +}; + static int conf_dhcpv4 = 1; static int conf_up = 0; static int conf_mode = 0; @@ -114,6 +121,7 @@ static int conf_l4_redirect_table; static int conf_l4_redirect_on_reject; static const char *conf_l4_redirect_ipset; static int conf_vlan_timeout = 30; +static int conf_max_request = 3; static const char *conf_relay; @@ -140,6 +148,7 @@ static unsigned int stat_delayed_offer; static mempool_t ses_pool; static mempool_t disc_item_pool; +static mempool_t req_item_pool; static int connlimit_loaded; @@ -1114,7 +1123,7 @@ static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packe if (conf_verbose) { log_ppp_info2("recv "); - dhcpv4_print_packet(pack, 0, log_info2); + dhcpv4_print_packet(pack, 0, log_ppp_info2); } if (pack->relay_agent && dhcpv4_parse_opt82(pack->relay_agent, &agent_circuit_id, &agent_remote_id)) { @@ -1268,6 +1277,42 @@ static void ipoe_serv_check_disc(struct ipoe_serv *serv, struct dhcpv4_packet *p } } +static int ipoe_serv_request_check(struct ipoe_serv *serv, uint32_t xid) +{ + struct request_item *r; + struct list_head *pos, *n; + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + list_for_each_safe(pos, n, &serv->req_list) { + r = list_entry(pos, typeof(*r), entry); + if (r->xid == xid) { + if (++r->cnt == conf_max_request) { + list_del(&r->entry); + mempool_free(r); + return 1; + } + + r->expire = ts.tv_sec + 30; + return 0; + } + + if (ts.tv_sec > r->expire) { + list_del(&r->entry); + mempool_free(r); + } + } + + r = mempool_alloc(req_item_pool); + r->xid = xid; + r->expire = ts.tv_sec + 30; + r->cnt = 0; + list_add_tail(&r->entry, &serv->req_list); + + return 0; +} + static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack, int force) { struct ipoe_serv *serv = container_of(dhcpv4->ctx, typeof(*serv), ctx); @@ -1346,7 +1391,7 @@ static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet if (!ses) { if (conf_verbose) { - log_debug("recv "); + log_debug("%s: recv ", serv->ifname); dhcpv4_print_packet(pack, 0, log_debug); } @@ -1362,7 +1407,8 @@ static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet } triton_context_call(&opt82_ses->ctx, (triton_event_func)__ipoe_session_terminate, &opt82_ses->ses); - } + } else if (list_empty(&conf_offer_delay) || ipoe_serv_request_check(serv, pack->hdr->xid)) + dhcpv4_send_nak(dhcpv4, pack); } else { ses->xid = pack->hdr->xid; @@ -1373,7 +1419,7 @@ static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet if (conf_verbose) { log_switch(dhcpv4->ctx, &ses->ses); log_ppp_info2("recv "); - dhcpv4_print_packet(pack, 0, log_info2); + dhcpv4_print_packet(pack, 0, log_ppp_info2); if ((opt82_ses && ses != opt82_ses) || (!opt82_ses && pack->relay_agent)) log_ppp_warn("port change detected\n"); } @@ -1735,6 +1781,12 @@ static void ipoe_serv_release(struct ipoe_serv *serv) mempool_free(d); __sync_sub_and_fetch(&stat_delayed_offer, 1); } + + while (!list_empty(&serv->req_list)) { + struct request_item *r = list_first_entry(&serv->req_list, typeof(*r), entry); + list_del(&r->entry); + mempool_free(r); + } if (serv->disc_timer.tpd) triton_timer_del(&serv->disc_timer); @@ -2220,6 +2272,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int INIT_LIST_HEAD(&serv->sessions); INIT_LIST_HEAD(&serv->addr_list); INIT_LIST_HEAD(&serv->disc_list); + INIT_LIST_HEAD(&serv->req_list); memcpy(serv->hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); serv->disc_timer.expire = ipoe_serv_disc_timer; @@ -2967,6 +3020,7 @@ static void ipoe_init(void) { ses_pool = mempool_create(sizeof(struct ipoe_session)); disc_item_pool = mempool_create(sizeof(struct disc_item)); + req_item_pool = mempool_create(sizeof(struct request_item)); uc_pool = mempool_create(sizeof(struct unit_cache)); triton_context_register(&l4_redirect_ctx, NULL); diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h index 5ef46b7a..88e37e46 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.h +++ b/accel-pppd/ctrl/ipoe/ipoe.h @@ -27,6 +27,7 @@ struct ipoe_serv { struct dhcpv4_relay *dhcpv4_relay; struct arp_serv *arp; struct list_head disc_list; + struct list_head req_list; struct triton_timer_t disc_timer; struct triton_timer_t timer; pthread_mutex_t lock; |