summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c68
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h1
-rw-r--r--accel-pppd/ifcfg.c16
-rw-r--r--drivers/ipoe/ipoe.c2
4 files changed, 77 insertions, 10 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index 46c5372..8044ad0 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -123,6 +123,7 @@ static void ipoe_session_finished(struct ap_session *s);
static void ipoe_drop_sessions(struct ipoe_serv *serv, struct ipoe_session *skip);
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)
{
@@ -331,8 +332,7 @@ static void ipoe_session_start(struct ipoe_session *ses)
struct unit_cache *uc;
if (!ses->ses.username) {
- if (!ses->serv->opt_shared)
- strncpy(ses->ses.ifname, ses->serv->ifname, AP_IFNAME_LEN);
+ strncpy(ses->ses.ifname, ses->serv->ifname, AP_IFNAME_LEN);
ipoe_session_set_username(ses);
@@ -584,9 +584,12 @@ static void __ipoe_session_activate(struct ipoe_session *ses)
if (ses->ifindex != -1) {
addr = 0;
- if (!ses->ses.ipv4)
- addr = 1;
- else if (ses->ses.ipv4->peer_addr != ses->yiaddr)
+ if (!ses->ses.ipv4) {
+ if (ses->serv->opt_mode == MODE_L3) {
+ addr = 1;
+ ses->ctrl.dont_ifcfg = 1;
+ }
+ } else if (ses->ses.ipv4->peer_addr != ses->yiaddr)
addr = ses->ses.ipv4->peer_addr;
if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, addr, NULL, NULL)) {
@@ -687,6 +690,15 @@ static void ipoe_session_started(struct ap_session *s)
if (ses->timer.tpd)
triton_timer_mod(&ses->timer, 0);
+
+ if (ses->ifindex != -1 && ses->xid) {
+ ses->dhcpv4 = dhcpv4_create(ses->ctrl.ctx, ses->ses.ifname, "");
+ if (!ses->dhcpv4) {
+ //terminate
+ return;
+ }
+ ses->dhcpv4->recv = ipoe_ses_recv_dhcpv4;
+ }
}
static void ipoe_session_free(struct ipoe_session *ses)
@@ -748,6 +760,9 @@ static void ipoe_session_finished(struct ap_session *s)
if (serv_close)
ipoe_serv_close(&ses->serv->ctx);
+
+ if (ses->dhcpv4)
+ dhcpv4_free(ses->dhcpv4);
triton_context_call(&ses->ctx, (triton_event_func)ipoe_session_free, ses);
}
@@ -869,6 +884,48 @@ static void __ipoe_session_terminate(struct ap_session *ses)
ap_session_terminate(ses, TERM_USER_REQUEST, 0);
}
+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);
+
+ if (ap_shutdown)
+ return;
+
+ if (conf_verbose) {
+ log_ppp_info2("recv ");
+ dhcpv4_print_packet(pack, 0, log_info2);
+ }
+
+ if (pack->msg_type == DHCPDISCOVER) {
+ 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);
+ }
+ } else if (pack->msg_type == DHCPREQUEST) {
+ 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))) {
+
+ if (pack->server_id == ses->siaddr)
+ dhcpv4_send_nak(dhcpv4, pack);
+ else if (ses->serv->dhcpv4_relay)
+ dhcpv4_relay_send(ses->serv->dhcpv4_relay, pack, 0, ses->serv->ifname, conf_agent_remote_id);
+
+ ap_session_terminate(&ses->ses, TERM_USER_REQUEST, 0);
+ } else {
+ dhcpv4_packet_ref(pack);
+ ipoe_session_keepalive(pack);
+ }
+ } else if (pack->msg_type == DHCPDECLINE || pack->msg_type == DHCPRELEASE) {
+ dhcpv4_packet_ref(pack);
+ ipoe_session_decline(pack);
+ }
+}
+
static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack)
{
struct ipoe_serv *serv = container_of(dhcpv4->ctx, typeof(*serv), ctx);
@@ -882,7 +939,6 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p
if (pack->msg_type == DHCPDISCOVER) {
ses = ipoe_session_lookup(serv, pack);
if (!ses) {
-
if (serv->opt_shared == 0)
ipoe_drop_sessions(serv, NULL);
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index bb5841e..96920a3 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -35,6 +35,7 @@ struct ipoe_session
struct triton_context_t ctx;
struct triton_timer_t timer;
struct ipoe_serv *serv;
+ struct dhcpv4_serv *dhcpv4;
struct ap_ctrl ctrl;
struct ap_session ses;
uint8_t hwaddr[6];
diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c
index 127d776..ea1ac2f 100644
--- a/accel-pppd/ifcfg.c
+++ b/accel-pppd/ifcfg.c
@@ -70,11 +70,21 @@ void ap_session_ifup(struct ap_session *ses)
triton_event_fire(EV_SES_PRE_UP, ses);
if (ses->stop_time)
return;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ses->ifname);
- if (!ses->ctrl->dont_ifcfg) {
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ses->ifname);
+ if (ses->ctrl->dont_ifcfg) {
+ if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr))
+ log_ppp_error("failed to get interface flags: %s\n", strerror(errno));
+
+ if (!(ifr.ifr_flags & IFF_UP)) {
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr))
+ log_ppp_error("failed to set interface flags: %s\n", strerror(errno));
+ }
+ } else {
#ifdef USE_BACKUP
if (!ses->backup || !ses->backup->internal) {
#endif
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index 3ab44e0..98ea7ff 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -1274,7 +1274,7 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[IPOE_ATTR_ADDR]) {
ses->addr = nla_get_be32(info->attrs[IPOE_ATTR_ADDR]);
- if (ses->addr)
+ if (ses->addr && !ses->link_dev)
dev->flags |= IFF_NOARP;
else
dev->flags &= ~IFF_NOARP;