diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2016-03-19 20:17:02 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2016-03-19 20:17:02 +0300 |
commit | 64e5c04c0d9aa4b46235c5f0da45d22abf9cce1c (patch) | |
tree | c0e09acd376ca98f5024528c360f66408bb2da32 | |
parent | 39c7832eac5f3fe6f58bd188df23e677be8ee9bd (diff) | |
download | accel-ppp-64e5c04c0d9aa4b46235c5f0da45d22abf9cce1c.tar.gz accel-ppp-64e5c04c0d9aa4b46235c5f0da45d22abf9cce1c.zip |
ipoe: send arp reply for sessions started by arp request
-rw-r--r-- | accel-pppd/ctrl/ipoe/arp.c | 14 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 32 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.h | 26 | ||||
-rw-r--r-- | drivers/ipoe/ipoe.c | 7 |
4 files changed, 60 insertions, 19 deletions
diff --git a/accel-pppd/ctrl/ipoe/arp.c b/accel-pppd/ctrl/ipoe/arp.c index 2bf5a951..58533582 100644 --- a/accel-pppd/ctrl/ipoe/arp.c +++ b/accel-pppd/ctrl/ipoe/arp.c @@ -112,6 +112,20 @@ out: mempool_free(ah); } +void arp_send(int ifindex, struct _arphdr *arph) +{ + struct sockaddr_ll dst; + + memset(&dst, 0, sizeof(dst)); + dst.sll_family = AF_PACKET; + dst.sll_ifindex = ifindex; + dst.sll_protocol = htons(ETH_P_ARP); + + arph->ar_op = htons(ARPOP_REPLY); + + sendto(arp_hnd.fd, arph, sizeof(*arph), MSG_DONTWAIT, (struct sockaddr *)&dst, sizeof(dst)); +} + static int arp_read(struct triton_md_handler_t *h) { int r, i; diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 12bb2ba7..8068983d 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -800,23 +800,25 @@ static void __ipoe_session_start(struct ipoe_session *ses) ses->timer.expire_tv.tv_sec = conf_offer_timeout; triton_timer_add(&ses->ctx, &ses->timer, 0); } else { - if (!ses->siaddr) + if (!ses->router) find_gw_addr(ses); - if (!ses->siaddr) - ses->siaddr = ses->serv->opt_src; + if (!ses->router) + ses->router = ses->serv->opt_src; - if (!ses->siaddr) + if (!ses->router) ses->siaddr = iproute_get(ses->yiaddr, NULL); - if (!ses->siaddr) { - log_ppp_error("can't determine local address\n"); + if (!ses->router) { + log_ppp_error("can't determine router address\n"); ap_session_terminate(&ses->ses, TERM_NAS_ERROR, 1); return; } if (ses->ses.ipv4 && !ses->ses.ipv4->addr) - ses->ses.ipv4->addr = ses->siaddr; + ses->ses.ipv4->addr = ses->router; + + ses->siaddr = ses->router; __ipoe_session_activate(ses); } @@ -903,6 +905,14 @@ static void __ipoe_session_activate(struct ipoe_session *ses) dhcpv4_packet_free(ses->dhcpv4_request); ses->dhcpv4_request = NULL; + } else if (ses->arph) { + if (ses->arph->ar_tpa == ses->router) { + memcpy(ses->arph->ar_tha, ses->serv->hwaddr, ETH_ALEN); + arp_send(ses->serv->ifindex, ses->arph); + } + + _free(ses->arph); + ses->arph = NULL; } ses->timer.expire = ipoe_session_timeout; @@ -1015,6 +1025,9 @@ static void ipoe_session_free(struct ipoe_session *ses) if (ses->dhcpv4_relay_reply) dhcpv4_packet_free(ses->dhcpv4_relay_reply); + if (ses->arph) + _free(ses->arph); + if (ses->ctrl.called_station_id && ses->ctrl.called_station_id != ses->ses.ifname) _free(ses->ctrl.called_station_id); @@ -1806,6 +1819,11 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc if (serv->timer.tpd) triton_timer_del(&serv->timer); + if (arph) { + ses->arph = _malloc(sizeof(*arph)); + memcpy(ses->arph, arph, sizeof(*arph)); + } + triton_context_call(&ses->ctx, (triton_event_func)ipoe_session_start, ses); triton_context_wakeup(&ses->ctx); diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h index 52b3c8da..c8b03b9c 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.h +++ b/accel-pppd/ctrl/ipoe/ipoe.h @@ -18,6 +18,18 @@ #define ETH_ALEN 6 #endif +struct _arphdr { + __be16 ar_hrd; + __be16 ar_pro; + __u8 ar_hln; + __u8 ar_pln; + __be16 ar_op; + __u8 ar_sha[ETH_ALEN]; + __be32 ar_spa; + __u8 ar_tha[ETH_ALEN]; + __be32 ar_tpa; +} __packed; + struct ipoe_serv { struct list_head entry; struct triton_context_t ctx; @@ -82,6 +94,7 @@ struct ipoe_session { uint8_t *data; struct dhcpv4_packet *dhcpv4_request; struct dhcpv4_packet *dhcpv4_relay_reply; + struct _arphdr *arph; int relay_retransmit; int ifindex; char *username; @@ -106,18 +119,6 @@ struct ipoe_session_info { uint32_t peer_addr; }; -struct _arphdr { - __be16 ar_hrd; - __be16 ar_pro; - __u8 ar_hln; - __u8 ar_pln; - __be16 ar_op; - __u8 ar_sha[ETH_ALEN]; - __be32 ar_spa; - __u8 ar_tha[ETH_ALEN]; - __be32 ar_tpa; -} __packed; - #ifdef USE_LUA char *ipoe_lua_get_username(struct ipoe_session *, const char *func); int ipoe_lua_make_vlan_name(const char *func, const char *parent, int svid, int cvid, char *name); @@ -146,6 +147,7 @@ void ipoe_nl_del_net(uint32_t addr); void *arpd_start(struct ipoe_serv *ipoe); void arpd_stop(void *arp); +void arp_send(int ifindex, struct _arphdr *arph); #endif diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c index 5bafde6a..059b1397 100644 --- a/drivers/ipoe/ipoe.c +++ b/drivers/ipoe/ipoe.c @@ -736,9 +736,16 @@ static rx_handler_result_t ipoe_recv(struct sk_buff **pskb) return RX_HANDLER_PASS; arph = (struct _arphdr *)skb_network_header(skb); + if (arph->ar_op != htons(ARPOP_REQUEST)) return RX_HANDLER_PASS; + if (arph->ar_hrd != htons(ARPHRD_ETHER)) + return RX_HANDLER_PASS; + + if (arph->ar_pro != htons(ETH_P_IP)) + return RX_HANDLER_PASS; + saddr = arph->ar_sip; } else return RX_HANDLER_PASS; |