diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2013-06-04 15:41:21 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2013-06-04 15:41:21 +0400 |
commit | 9ba02ed111f321b71bd526c95bbf559d4cee4de8 (patch) | |
tree | 1c628edc764adcc4751e11b9af2250f362672408 /accel-pppd | |
parent | 537aa4db022683d11cf13dab60a3410016f98ca8 (diff) | |
download | accel-ppp-9ba02ed111f321b71bd526c95bbf559d4cee4de8.tar.gz accel-ppp-9ba02ed111f321b71bd526c95bbf559d4cee4de8.zip |
ipoe: check opt82 change
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 175 |
1 files changed, 149 insertions, 26 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index a2991f4..b0d5201 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -126,12 +126,16 @@ static void ipoe_serv_close(struct triton_context_t *ctx); static void __ipoe_session_activate(struct ipoe_session *ses); static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack); -static struct ipoe_session *ipoe_session_lookup(struct ipoe_serv *serv, struct dhcpv4_packet *pack) +static struct ipoe_session *ipoe_session_lookup(struct ipoe_serv *serv, struct dhcpv4_packet *pack, struct ipoe_session **opt82_ses) { - struct ipoe_session *ses; + struct ipoe_session *ses, *res = NULL; uint8_t *agent_circuit_id = NULL; uint8_t *agent_remote_id = NULL; + int opt82_match; + + if (opt82_ses) + *opt82_ses = NULL; if (pack->relay_agent && dhcpv4_parse_opt82(pack->relay_agent, &agent_circuit_id, &agent_remote_id)) { agent_circuit_id = NULL; @@ -139,38 +143,44 @@ static struct ipoe_session *ipoe_session_lookup(struct ipoe_serv *serv, struct d } list_for_each_entry(ses, &serv->sessions, entry) { - if (agent_circuit_id && !ses->agent_circuit_id) - continue; + opt82_match = pack->relay_agent != NULL; - if (agent_remote_id && !ses->agent_remote_id) - continue; + if (opt82_match && agent_circuit_id && !ses->agent_circuit_id) + opt82_match = 0; - if (!agent_circuit_id && ses->agent_circuit_id) - continue; + if (opt82_match && agent_remote_id && !ses->agent_remote_id) + opt82_match = 0; - if (!agent_remote_id && ses->agent_remote_id) - continue; + if (opt82_match && !agent_circuit_id && ses->agent_circuit_id) + opt82_match = 0; + + if (opt82_match && !agent_remote_id && ses->agent_remote_id) + opt82_match = 0; - if (agent_circuit_id) { + if (opt82_match && agent_circuit_id) { if (*agent_circuit_id != *ses->agent_circuit_id) - continue; + opt82_match = 0; + if (memcmp(agent_circuit_id + 1, ses->agent_circuit_id + 1, *agent_circuit_id)) - continue; + opt82_match = 0; } - if (agent_remote_id) { + if (opt82_match && agent_remote_id) { if (*agent_remote_id != *ses->agent_remote_id) - continue; + opt82_match = 0; + if (memcmp(agent_remote_id + 1, ses->agent_remote_id + 1, *agent_remote_id)) - continue; - - return ses; + opt82_match = 0; } + + if (opt82_match && opt82_ses) + *opt82_ses = ses; if (memcmp(pack->hdr->chaddr, ses->hwaddr, 6)) continue; - return ses; + res = ses; + break; /*if (pack->client_id && !ses->client_id) continue; @@ -193,7 +203,43 @@ static struct ipoe_session *ipoe_session_lookup(struct ipoe_serv *serv, struct d return ses;*/ } - return NULL; + if (!res || !pack->relay_agent || !opt82_ses || *opt82_ses) + return res; + + list_for_each_entry(ses, &serv->sessions, entry) { + if (agent_circuit_id && !ses->agent_circuit_id) + continue; + + if (opt82_match && agent_remote_id && !ses->agent_remote_id) + continue; + + if (opt82_match && !agent_circuit_id && ses->agent_circuit_id) + continue; + + if (opt82_match && !agent_remote_id && ses->agent_remote_id) + continue; + + if (opt82_match && agent_circuit_id) { + if (*agent_circuit_id != *ses->agent_circuit_id) + continue; + + if (memcmp(agent_circuit_id + 1, ses->agent_circuit_id + 1, *agent_circuit_id)) + continue; + } + + if (opt82_match && agent_remote_id) { + if (*agent_remote_id != *ses->agent_remote_id) + continue; + + if (memcmp(agent_remote_id + 1, ses->agent_remote_id + 1, *agent_remote_id)) + continue; + } + + *opt82_ses = ses; + break; + } + + return res; } static void ipoe_session_timeout(struct triton_timer_t *t) @@ -894,6 +940,9 @@ static void __ipoe_session_terminate(struct ap_session *ses) static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack) { struct ipoe_session *ses = container_of(dhcpv4->ctx, typeof(*ses), ctx); + int opt82_match; + uint8_t *agent_circuit_id = NULL; + uint8_t *agent_remote_id = NULL; if (ap_shutdown) return; @@ -902,6 +951,49 @@ static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packe log_ppp_info2("recv "); dhcpv4_print_packet(pack, 0, log_info2); } + + if (pack->relay_agent && dhcpv4_parse_opt82(pack->relay_agent, &agent_circuit_id, &agent_remote_id)) { + agent_circuit_id = NULL; + agent_remote_id = NULL; + } + + opt82_match = pack->relay_agent != NULL; + + if (opt82_match && agent_circuit_id && !ses->agent_circuit_id) + opt82_match = 0; + + if (opt82_match && agent_remote_id && !ses->agent_remote_id) + opt82_match = 0; + + if (opt82_match && !agent_circuit_id && ses->agent_circuit_id) + opt82_match = 0; + + if (opt82_match && !agent_remote_id && ses->agent_remote_id) + opt82_match = 0; + + if (opt82_match && agent_circuit_id) { + if (*agent_circuit_id != *ses->agent_circuit_id) + opt82_match = 0; + + if (memcmp(agent_circuit_id + 1, ses->agent_circuit_id + 1, *agent_circuit_id)) + opt82_match = 0; + } + + if (opt82_match && agent_remote_id) { + if (*agent_remote_id != *ses->agent_remote_id) + opt82_match = 0; + + if (memcmp(agent_remote_id + 1, ses->agent_remote_id + 1, *agent_remote_id)) + opt82_match = 0; + } + + if (!opt82_match) { + log_ppp_info2("port change detected\n"); + if (pack->msg_type == DHCPREQUEST) + dhcpv4_send_nak(dhcpv4, pack); + triton_context_call(ses->ctrl.ctx, (triton_event_func)__ipoe_session_terminate, &ses->ses); + return; + } if (pack->msg_type == DHCPDISCOVER) { if (ses->yiaddr) { @@ -922,7 +1014,7 @@ static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packe else if (ses->serv->dhcpv4_relay) dhcpv4_relay_send(ses->serv->dhcpv4_relay, pack, 0, ses->serv->ifname, conf_agent_remote_id); - triton_context_call(ses->ctrl.ctx, (triton_event_func)__ipoe_session_terminate, ses); + triton_context_call(ses->ctrl.ctx, (triton_event_func)__ipoe_session_terminate, &ses->ses); } else { dhcpv4_packet_ref(pack); ipoe_session_keepalive(pack); @@ -936,7 +1028,7 @@ static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packe static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack) { struct ipoe_serv *serv = container_of(dhcpv4->ctx, typeof(*serv), ctx); - struct ipoe_session *ses; + struct ipoe_session *ses, *opt82_ses; //struct dhcpv4_packet *reply; if (ap_shutdown) @@ -944,10 +1036,16 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p pthread_mutex_lock(&serv->lock); if (pack->msg_type == DHCPDISCOVER) { - ses = ipoe_session_lookup(serv, pack); + ses = ipoe_session_lookup(serv, pack, &opt82_ses); if (!ses) { if (serv->opt_shared == 0) ipoe_drop_sessions(serv, NULL); + else if (opt82_ses) { + if (conf_verbose) + log_ppp_warn("mac change detected\n"); + + triton_context_call(&opt82_ses->ctx, (triton_event_func)__ipoe_session_terminate, &opt82_ses->ses); + } ses = ipoe_session_create_dhcpv4(serv, pack); if (ses) { @@ -960,6 +1058,18 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p } } } else { + if ((opt82_ses && ses != opt82_ses) || (!opt82_ses && pack->relay_agent)) { + if (conf_verbose) { + log_switch(dhcpv4->ctx, &ses->ses); + log_ppp_info2("recv "); + dhcpv4_print_packet(pack, 0, log_ppp_info2); + log_ppp_warn("port change detected\n"); + } + + triton_context_call(&ses->ctx, (triton_event_func)__ipoe_session_terminate, &ses->ses); + goto out; + } + log_switch(dhcpv4->ctx, &ses->ses); if (conf_verbose) { @@ -976,7 +1086,7 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p } } } else if (pack->msg_type == DHCPREQUEST) { - ses = ipoe_session_lookup(serv, pack); + ses = ipoe_session_lookup(serv, pack, &opt82_ses); if (!ses) { if (conf_verbose) { @@ -986,18 +1096,29 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p if (serv->opt_shared == 0) ipoe_drop_sessions(serv, NULL); + else if (opt82_ses) { + if (conf_verbose) { + log_switch(dhcpv4->ctx, &opt82_ses->ses); + log_ppp_warn("mac change detected\n"); + } + + triton_context_call(&opt82_ses->ctx, (triton_event_func)__ipoe_session_terminate, &opt82_ses->ses); + } dhcpv4_send_nak(dhcpv4, pack); } else { if (pack->hdr->ciaddr == ses->yiaddr && pack->hdr->xid != ses->xid) ses->xid = pack->hdr->xid; if ((pack->server_id && (pack->server_id != ses->siaddr || pack->request_ip != ses->yiaddr)) || - (pack->hdr->ciaddr && (pack->hdr->xid != ses->xid || pack->hdr->ciaddr != ses->yiaddr))) { + (pack->hdr->ciaddr && (pack->hdr->xid != ses->xid || pack->hdr->ciaddr != ses->yiaddr)) || + (opt82_ses && ses != opt82_ses) || (!opt82_ses && pack->relay_agent)) { if (conf_verbose) { log_switch(dhcpv4->ctx, &ses->ses); log_ppp_info2("recv "); dhcpv4_print_packet(pack, 0, log_info2); + if ((opt82_ses && ses != opt82_ses) || (!opt82_ses && pack->relay_agent)) + log_ppp_warn("port change detected\n"); } if (pack->server_id == ses->siaddr) @@ -1027,12 +1148,14 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p } } } else if (pack->msg_type == DHCPDECLINE || pack->msg_type == DHCPRELEASE) { - ses = ipoe_session_lookup(serv, pack); + ses = ipoe_session_lookup(serv, pack, &opt82_ses); if (ses) { dhcpv4_packet_ref(pack); triton_context_call(&ses->ctx, (triton_event_func)ipoe_session_decline, pack); } } + +out: pthread_mutex_unlock(&serv->lock); } |