summaryrefslogtreecommitdiff
path: root/accel-pppd/ctrl/ipoe/arp.c
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2016-11-29 22:19:52 +0300
committerDmitry Kozlov <xeb@mail.ru>2016-11-29 22:19:52 +0300
commit8557ca019041374d43712506eecc21479f83b9e6 (patch)
tree92bb6ffd66129da92250e54d7f143aeed1f78cdb /accel-pppd/ctrl/ipoe/arp.c
parent01a985316d5240e7a2ba9ba683493cc015282d8a (diff)
downloadaccel-ppp-xebd-8557ca019041374d43712506eecc21479f83b9e6.tar.gz
accel-ppp-xebd-8557ca019041374d43712506eecc21479f83b9e6.zip
ipoe: apply offer-delay rules to arp initiated sessions
Diffstat (limited to 'accel-pppd/ctrl/ipoe/arp.c')
-rw-r--r--accel-pppd/ctrl/ipoe/arp.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/accel-pppd/ctrl/ipoe/arp.c b/accel-pppd/ctrl/ipoe/arp.c
index 4818c3b..36b0344 100644
--- a/accel-pppd/ctrl/ipoe/arp.c
+++ b/accel-pppd/ctrl/ipoe/arp.c
@@ -39,6 +39,8 @@ struct arp_tree {
static mempool_t arp_pool;
static mempool_t arp_hdr_pool;
+static uint8_t bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
#define HASH_BITS 0xff
static struct arp_tree *arp_tree;
@@ -63,6 +65,12 @@ static void arp_ctx_read(struct _arphdr *ah)
ah2.ar_op = htons(ARPOP_REPLY);
pthread_mutex_lock(&ipoe->lock);
+ if (ah->ar_op == htons(ARPOP_REPLY)) {
+ ipoe_serv_recv_arp(ipoe, ah);
+ pthread_mutex_unlock(&ipoe->lock);
+ goto out;
+ }
+
list_for_each_entry(ses, &ipoe->sessions, entry) {
if (ses->yiaddr == ah->ar_spa) {
ses1 = ses;
@@ -80,8 +88,14 @@ static void arp_ctx_read(struct _arphdr *ah)
break;
}
- if (!ses1 || (ses1->ses.state != AP_STATE_ACTIVE) ||
- (ses2 && ses2->ses.state != AP_STATE_ACTIVE)) {
+ if (!ses1 && ipoe->opt_up) {
+ ipoe_serv_recv_arp(ipoe, ah);
+ pthread_mutex_unlock(&ipoe->lock);
+ goto out;
+ }
+
+ if (!ipoe->opt_arp || !ses1 || ses1->arph ||
+ (ses2 && ses2->ses.state != AP_STATE_ACTIVE)) {
pthread_mutex_unlock(&ipoe->lock);
goto out;
}
@@ -112,7 +126,7 @@ out:
mempool_free(ah);
}
-void arp_send(int ifindex, struct _arphdr *arph)
+void arp_send(int ifindex, struct _arphdr *arph, int broadcast)
{
struct sockaddr_ll dst;
@@ -120,7 +134,10 @@ void arp_send(int ifindex, struct _arphdr *arph)
dst.sll_family = AF_PACKET;
dst.sll_ifindex = ifindex;
dst.sll_protocol = htons(ETH_P_ARP);
- memcpy(dst.sll_addr, arph->ar_tha, ETH_ALEN);
+ if (broadcast)
+ memcpy(dst.sll_addr, bc_addr, ETH_ALEN);
+ else
+ memcpy(dst.sll_addr, arph->ar_tha, ETH_ALEN);
arph->ar_op = htons(ARPOP_REPLY);
@@ -151,8 +168,13 @@ static int arp_read(struct triton_md_handler_t *h)
if (r < sizeof(*ah))
continue;
- if (ah->ar_op != htons(ARPOP_REQUEST))
- continue;
+ if (ah->ar_op != htons(ARPOP_REQUEST)) {
+ if (ah->ar_op != htons(ARPOP_REPLY))
+ continue;
+
+ if (memcmp(src.sll_addr, bc_addr, ETH_ALEN))
+ continue;
+ }
if (ah->ar_pln != 4)
continue;