summaryrefslogtreecommitdiff
path: root/accel-pppd
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2013-09-06 10:55:35 +0400
committerDmitry Kozlov <xeb@mail.ru>2013-09-06 10:55:35 +0400
commit7ea5ddfb8cf3a2507b901882bd92c5c946e372c8 (patch)
treea201079f18621a2037ac6c65f1107f814b141843 /accel-pppd
parent5f8334da2d874e0be028ad03376574de1598f0cd (diff)
downloadaccel-ppp-7ea5ddfb8cf3a2507b901882bd92c5c946e372c8.tar.gz
accel-ppp-7ea5ddfb8cf3a2507b901882bd92c5c946e372c8.zip
ipoe: various fixes in relay operation
Diffstat (limited to 'accel-pppd')
-rw-r--r--accel-pppd/ctrl/ipoe/dhcpv4.c37
-rw-r--r--accel-pppd/ctrl/ipoe/dhcpv4.h2
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c104
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h1
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;