diff options
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4.c | 37 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4.h | 2 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 104 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.h | 1 |
4 files changed, 97 insertions, 47 deletions
diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.c b/accel-pppd/ctrl/ipoe/dhcpv4.c index fa763445..fc2a9d34 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4.c +++ b/accel-pppd/ctrl/ipoe/dhcpv4.c @@ -535,10 +535,12 @@ static int dhcpv4_relay_read(struct triton_md_handler_t *h) continue; } + pthread_mutex_lock(&relay_lock); list_for_each_entry(c, &r->ctx_list, entry) { dhcpv4_packet_ref(pack); triton_context_call(c->ctx, c->recv, pack); } + pthread_mutex_unlock(&relay_lock); dhcpv4_packet_free(pack); } @@ -790,16 +792,14 @@ out_err: return 0; } -struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr, struct triton_context_t *ctx, triton_event_func recv) +struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, in_addr_t giaddr, struct triton_context_t *ctx, triton_event_func recv) { char str[17], *ptr; struct dhcpv4_relay *r; in_addr_t addr;// = inet_addr(_addr); int port = DHCP_SERV_PORT; - in_addr_t giaddr;// = inet_addr(_giaddr); struct sockaddr_in raddr; struct sockaddr_in laddr; - socklen_t len = sizeof(laddr); int sock = -1; int f = 1; struct dhcpv4_relay_ctx *c; @@ -818,22 +818,6 @@ struct dhcpv4_relay *dhcpv4_relay_create(const char *_addr, const char *_giaddr, raddr.sin_addr.s_addr = addr; raddr.sin_port = htons(port); - if (_giaddr) - giaddr = inet_addr(_giaddr); - else { - sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - - if (connect(sock, &raddr, sizeof(raddr))) { - log_error("dhcpv4: relay: %s: connect: %s\n", _addr, strerror(errno)); - goto out_err; - } - - getsockname(sock, &laddr, &len); - giaddr = laddr.sin_addr.s_addr; - - close(sock); - } - memset(&laddr, 0, sizeof(laddr)); laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = giaddr; @@ -896,13 +880,20 @@ found: out_err_unlock: pthread_mutex_unlock(&relay_lock); -out_err: if (sock != -1) close(sock); _free(r); return NULL; } +static void __dhcpv4_relay_free(struct dhcpv4_relay *r) +{ + triton_md_unregister_handler(&r->hnd); + close(r->hnd.fd); + triton_context_unregister(&r->ctx); + _free(r); +} + void dhcpv4_relay_free(struct dhcpv4_relay *r, struct triton_context_t *ctx) { struct dhcpv4_relay_ctx *c; @@ -918,11 +909,7 @@ void dhcpv4_relay_free(struct dhcpv4_relay *r, struct triton_context_t *ctx) if (list_empty(&r->ctx_list)) { list_del(&r->entry); - - triton_md_unregister_handler(&r->hnd); - close(r->hnd.fd); - triton_context_unregister(&r->ctx); - _free(r); + triton_context_call(&r->ctx, (triton_event_func)__dhcpv4_relay_free, r); } pthread_mutex_unlock(&relay_lock); } diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.h b/accel-pppd/ctrl/ipoe/dhcpv4.h index ea39657e..39e24ca6 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4.h +++ b/accel-pppd/ctrl/ipoe/dhcpv4.h @@ -97,7 +97,7 @@ struct ap_session; struct dhcpv4_serv *dhcpv4_create(struct triton_context_t *ctx, const char *ifname, const char *opt); void dhcpv4_free(struct dhcpv4_serv *); -struct dhcpv4_relay *dhcpv4_relay_create(const char *addr, const char *giaddr, struct triton_context_t *ctx, triton_event_func recv); +struct dhcpv4_relay *dhcpv4_relay_create(const char *addr, in_addr_t giaddr, struct triton_context_t *ctx, triton_event_func recv); void dhcpv4_relay_free(struct dhcpv4_relay *, struct triton_context_t *); int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, uint32_t server_id, const char *agent_circuit_id, const char *agent_remote_id); diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 5e88f5d9..425ede17 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -119,7 +119,9 @@ static const char *conf_relay; static const char *conf_lua_username_func; #endif -static int conf_offer_timeout = 3; +static int conf_offer_timeout = 10; +static int conf_relay_timeout = 3; +static int conf_relay_retransmit = 3; static LIST_HEAD(conf_gw_addr); static int conf_netmask = 24; static int conf_lease_time = 600; @@ -286,6 +288,26 @@ static void ipoe_session_timeout(struct triton_timer_t *t) ap_session_terminate(&ses->ses, TERM_LOST_CARRIER, 0); } +static void ipoe_relay_timeout(struct triton_timer_t *t) +{ + struct ipoe_session *ses = container_of(t, typeof(*ses), timer); + + if (!ses->serv->dhcpv4_relay || !ses->dhcpv4_request) { + triton_timer_del(t); + return; + } + + if (++ses->relay_retransmit > conf_relay_retransmit) { + triton_timer_del(t); + + log_ppp_info2("ipoe: relay timed out\n"); + + ap_session_terminate(&ses->ses, TERM_LOST_CARRIER, 0); + } else + dhcpv4_relay_send(ses->serv->dhcpv4_relay, ses->dhcpv4_request, ses->relay_server_id, ses->serv->ifname, conf_agent_remote_id); +} + + static void ipoe_session_set_username(struct ipoe_session *ses) { #ifdef USE_LUA @@ -522,8 +544,8 @@ static void ipoe_session_start(struct ipoe_session *ses) if (ses->dhcpv4_request && ses->serv->dhcpv4_relay) { dhcpv4_relay_send(ses->serv->dhcpv4_relay, ses->dhcpv4_request, ses->relay_server_id, ses->serv->ifname, conf_agent_remote_id); - ses->timer.expire = ipoe_session_timeout; - ses->timer.expire_tv.tv_sec = conf_offer_timeout; + ses->timer.expire = ipoe_relay_timeout; + ses->timer.period = conf_relay_timeout * 1000; triton_timer_add(&ses->ctx, &ses->timer, 0); } else __ipoe_session_start(ses); @@ -603,13 +625,14 @@ static void __ipoe_session_start(struct ipoe_session *ses) if (!ses->mask) ses->mask = 32; - + dhcpv4_send_reply(DHCPOFFER, ses->serv->dhcpv4, ses->dhcpv4_request, ses->yiaddr, ses->siaddr, ses->router, ses->mask, ses->lease_time, ses->dhcpv4_relay_reply); dhcpv4_packet_free(ses->dhcpv4_request); ses->dhcpv4_request = NULL; ses->timer.expire = ipoe_session_timeout; + ses->timer.period = 0; ses->timer.expire_tv.tv_sec = conf_offer_timeout; triton_timer_add(&ses->ctx, &ses->timer, 0); } else @@ -760,6 +783,7 @@ static void __ipoe_session_activate(struct ipoe_session *ses) } ses->timer.expire = ipoe_session_timeout; + ses->timer.period = 0; ses->timer.expire_tv.tv_sec = conf_lease_timeout ? conf_lease_timeout : ses->lease_time; if (ses->timer.tpd) triton_timer_mod(&ses->timer, 0); @@ -862,6 +886,9 @@ static void ipoe_session_free(struct ipoe_session *ses) if (ses->dhcpv4_request) dhcpv4_packet_free(ses->dhcpv4_request); + if (ses->dhcpv4_relay_reply) + dhcpv4_packet_free(ses->dhcpv4_relay_reply); + if (ses->ctrl.called_station_id) _free(ses->ctrl.called_station_id); @@ -1269,13 +1296,8 @@ static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet dhcpv4_print_packet(pack, 0, log_ppp_info2); } - if (ses->yiaddr) { - if (ses->serv->dhcpv4_relay) { - dhcpv4_packet_ref(pack); - triton_context_call(&ses->ctx, (triton_event_func)ipoe_session_keepalive, pack); - } else - dhcpv4_send_reply(DHCPOFFER, dhcpv4, pack, ses->yiaddr, ses->siaddr, ses->router, ses->mask, ses->lease_time, ses->dhcpv4_relay_reply); - } + if (ses->yiaddr) + dhcpv4_send_reply(DHCPOFFER, dhcpv4, pack, ses->yiaddr, ses->siaddr, ses->router, ses->mask, ses->lease_time, ses->dhcpv4_relay_reply); } } else if (pack->msg_type == DHCPREQUEST) { ipoe_serv_check_disc(serv, pack); @@ -1920,9 +1942,8 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int int opt_ifcfg = conf_ifcfg; int opt_nat = conf_nat; const char *opt_relay = conf_relay; - const char *opt_giaddr = NULL; - in_addr_t relay_addr = 0; - in_addr_t giaddr = 0; + in_addr_t relay_addr = conf_relay ? inet_addr(conf_relay) : 0; + in_addr_t opt_giaddr = 0; in_addr_t opt_src = conf_src; int opt_arp = conf_arp; struct ifreq ifr; @@ -1972,8 +1993,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int opt_relay = ptr1; relay_addr = inet_addr(ptr1); } else if (strcmp(str, "giaddr") == 0) { - opt_giaddr = ptr1; - giaddr = inet_addr(ptr1); + opt_giaddr = inet_addr(ptr1); } else if (strcmp(str, "nat") == 0) { opt_nat = atoi(ptr1); } else if (strcmp(str, "src") == 0) { @@ -1994,6 +2014,29 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int opt_dhcpv4 = conf_dhcpv4; } + if (opt_relay && !opt_giaddr && opt_dhcpv4) { + struct sockaddr_in addr; + int sock; + socklen_t len = sizeof(addr); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = relay_addr; + addr.sin_port = htons(DHCP_SERV_PORT); + + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (connect(sock, &addr, sizeof(addr))) { + log_error("dhcpv4: relay: %s: connect: %s\n", opt_relay, strerror(errno)); + goto out_err; + } + + getsockname(sock, &addr, &len); + opt_giaddr = addr.sin_addr.s_addr; + + close(sock); + } + if (opt_up) ipoe_nl_add_interface(ifindex); @@ -2019,17 +2062,17 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int serv->dhcpv4 = NULL; } - if (serv->dhcpv4_relay && - (serv->dhcpv4_relay->addr != relay_addr || serv->dhcpv4_relay->giaddr != giaddr)) { + if (serv->dhcpv4_relay && + (serv->dhcpv4_relay->addr != relay_addr || serv->dhcpv4_relay->giaddr != opt_giaddr)) { if (serv->opt_ifcfg) ipoe_serv_del_addr(serv, serv->dhcpv4_relay->giaddr); dhcpv4_relay_free(serv->dhcpv4_relay, &serv->ctx); serv->dhcpv4_relay = NULL; } - if (serv->opt_dhcpv4 && opt_relay) { + if (!serv->dhcpv4_relay && serv->opt_dhcpv4 && opt_relay) { if (opt_ifcfg) - ipoe_serv_add_addr(serv, giaddr); + ipoe_serv_add_addr(serv, opt_giaddr); serv->dhcpv4_relay = dhcpv4_relay_create(opt_relay, opt_giaddr, &serv->ctx, (triton_event_func)ipoe_recv_dhcpv4_relay); } @@ -2108,7 +2151,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int if (opt_relay) { if (opt_ifcfg) - ipoe_serv_add_addr(serv, giaddr); + ipoe_serv_add_addr(serv, opt_giaddr); serv->dhcpv4_relay = dhcpv4_relay_create(opt_relay, opt_giaddr, &serv->ctx, (triton_event_func)ipoe_recv_dhcpv4_relay); } } @@ -2135,6 +2178,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int parse_err: log_error("ipoe: failed to parse '%s'\n", opt); +out_err: _free(str0); } @@ -2741,6 +2785,18 @@ static void load_config(void) conf_mode = MODE_L2; conf_relay = conf_get_opt("ipoe", "relay"); + + opt = conf_get_opt("ipoe", "relay-timeout"); + if (opt && atoi(opt) > 0) + conf_relay_timeout = atoi(opt); + else + conf_relay_timeout = 3; + + opt = conf_get_opt("ipoe", "relay-retransmit"); + if (opt && atoi(opt) > 0) + conf_relay_retransmit = atoi(opt); + else + conf_relay_retransmit = 3; opt = conf_get_opt("ipoe", "agent-remote-id"); if (opt) @@ -2781,6 +2837,12 @@ static void load_config(void) else conf_vlan_timeout = 60; + opt = conf_get_opt("ipoe", "offer-timeout"); + if (opt && atoi(opt) > 0) + conf_offer_timeout = atoi(opt); + else + conf_offer_timeout = 10; + #ifdef RADIUS if (triton_module_loaded("radius")) load_radius_attrs(); diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h index 6b1b9b53..220a6c48 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.h +++ b/accel-pppd/ctrl/ipoe/ipoe.h @@ -68,6 +68,7 @@ struct ipoe_session { uint8_t *data; struct dhcpv4_packet *dhcpv4_request; struct dhcpv4_packet *dhcpv4_relay_reply; + int relay_retransmit; int ifindex; struct ipv4db_item_t ipv4; int ifcfg:1; |