summaryrefslogtreecommitdiff
path: root/accel-pppd/ctrl/ipoe
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/ctrl/ipoe')
-rw-r--r--accel-pppd/ctrl/ipoe/CMakeLists.txt5
-rw-r--r--accel-pppd/ctrl/ipoe/backup.c53
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c8
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h9
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe_netlink.c81
5 files changed, 148 insertions, 8 deletions
diff --git a/accel-pppd/ctrl/ipoe/CMakeLists.txt b/accel-pppd/ctrl/ipoe/CMakeLists.txt
index 7be18cc..fdcb3a4 100644
--- a/accel-pppd/ctrl/ipoe/CMakeLists.txt
+++ b/accel-pppd/ctrl/ipoe/CMakeLists.txt
@@ -5,6 +5,7 @@ SET(sources
dhcpv4.c
dhcpv4_options.c
ipoe_netlink.c
+ backup.c
)
IF (LUA)
@@ -17,10 +18,6 @@ IF (LUA)
SET(sources ${sources} lua.c lua_lpack.c)
ENDIF (LUA)
-IF (BACKUP)
- SET(sources ${sources} backup.c)
-ENDIF (BACKUP)
-
ADD_LIBRARY(ipoe SHARED ${sources})
IF (LUA)
TARGET_LINK_LIBRARIES(ipoe ${LUA_LIBRARIES})
diff --git a/accel-pppd/ctrl/ipoe/backup.c b/accel-pppd/ctrl/ipoe/backup.c
index b2d0c0c..8347a4e 100644
--- a/accel-pppd/ctrl/ipoe/backup.c
+++ b/accel-pppd/ctrl/ipoe/backup.c
@@ -4,6 +4,8 @@
#include <netinet/in.h>
#include <net/ethernet.h>
+#include "triton.h"
+#include "events.h"
#include "log.h"
#include "memdebug.h"
@@ -25,8 +27,13 @@
#define add_tag(id, data, size) if (!backup_add_tag(m, id, 0, data, size)) return -1;
-#define add_tag_int(id, data, size) if (!backup_add_tag(m, id, 1, data, size)) return -1;
+#define add_tag_i(id, data, size) if (!backup_add_tag(m, id, 1, data, size)) return -1;
+static LIST_HEAD(ds_list);
+
+static void restore_complete(void);
+
+#ifdef USE_BACKUP
static int session_save(struct ap_session *ses, struct backup_mod *m)
{
struct ipoe_session *conn = container_of(ses, typeof(*conn), ses);
@@ -44,9 +51,10 @@ static int session_save(struct ap_session *ses, struct backup_mod *m)
if (conn->agent_circuit_id)
add_tag(IPOE_TAG_AGENT_REMOTE_ID, conn->agent_remote_id->data, conn->agent_remote_id->len);
- //add_tag_int(IPOE_TAG_IFNAME, conn->serv->ifname, strlen(conn->serv->ifname) + 1);
add_tag(IPOE_TAG_IFNAME, conn->serv->ifname, strlen(conn->serv->ifname) + 1);
+ add_tag_i(IPOE_TAG_IFINDEX, &conn->ifindex, 4);
+
return 0;
}
@@ -74,6 +82,7 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
struct backup_tag *ifname = NULL;
int dlen = 0;
uint8_t *ptr;
+ struct ipoe_session_info *info;
//if (!m->data->internal)
// return NULL;
@@ -137,6 +146,9 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
case IPOE_TAG_AGENT_REMOTE_ID:
set_dhcpv4_opt(&ses->agent_remote_id, t, &ptr);
break;
+ case IPOE_TAG_IFINDEX:
+ ses->ifindex = *(uint32_t *)t->data;
+ break;
}
}
@@ -149,6 +161,16 @@ static struct ap_session *ctrl_restore(struct backup_mod *m)
list_add_tail(&ses->entry, &serv->sessions);
pthread_mutex_unlock(&serv->lock);
+ if (ses->ifindex != -1) {
+ list_for_each_entry(info, &ds_list, entry) {
+ if (info->ifindex == ses->ifindex) {
+ list_del(&info->entry);
+ _free(info);
+ break;
+ }
+ }
+ }
+
return &ses->ses;
}
@@ -157,11 +179,38 @@ static struct backup_module mod = {
.save = session_save,
.restore = session_restore,
.ctrl_restore = ctrl_restore,
+ .restore_complete = restore_complete,
};
+#endif
+
+static void dump_sessions(void)
+{
+ ipoe_nl_get_sessions(&ds_list);
+
+#ifndef USE_BACKUP
+ restore_complete();
+#endif
+}
+
+static void restore_complete(void)
+{
+ struct ipoe_session_info *info;
+
+ while (!list_empty(&ds_list)) {
+ info = list_entry(ds_list.next, typeof(*info), entry);
+ ipoe_nl_delete(info->ifindex);
+ list_del(&info->entry);
+ _free(info);
+ }
+}
static void init(void)
{
+ dump_sessions();
+
+#ifdef USE_BACKUP
backup_register_module(&mod);
+#endif
}
DEFINE_INIT(100, init);
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index fea61a8..2f9cf12 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -166,7 +166,7 @@ static void ipoe_session_start(struct ipoe_session *ses)
if (ses->serv->opt_shared == 0)
strncpy(ses->ses.ifname, ses->serv->ifname, AP_IFNAME_LEN);
- else {
+ else if (ses->ifindex == -1) {
ses->ifindex = ipoe_nl_create(0, 0, ses->dhcpv4_request ? ses->serv->ifname : NULL, ses->hwaddr);
if (ses->ifindex == -1) {
log_ppp_error("ipoe: failed to create interface\n");
@@ -455,6 +455,9 @@ static void ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *p
struct ipoe_session *ses;
//struct dhcpv4_packet *reply;
+ if (ap_shutdown)
+ return;
+
pthread_mutex_lock(&serv->lock);
if (pack->msg_type == DHCPDISCOVER) {
ses = ipoe_session_lookup(serv, pack);
@@ -546,6 +549,9 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc
{
struct ipoe_session *ses;
+ if (ap_shutdown)
+ return NULL;
+
ses = mempool_alloc(ses_pool);
if (!ses) {
log_emerg("out of memery\n");
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index a2efd37..48bd631 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -50,6 +50,14 @@ struct ipoe_session
int ifindex;
};
+struct ipoe_session_info
+{
+ struct list_head entry;
+ int ifindex;
+ uint32_t addr;
+ uint32_t peer_addr;
+};
+
#ifdef USE_LUA
int ipoe_lua_set_username(struct ipoe_session *, const char *func);
#endif
@@ -67,6 +75,7 @@ void ipoe_nl_delete_nets(void);
int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr);
void ipoe_nl_delete(int ifindex);
int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr);
+void ipoe_nl_get_sessions(struct list_head *list);
#endif
diff --git a/accel-pppd/ctrl/ipoe/ipoe_netlink.c b/accel-pppd/ctrl/ipoe/ipoe_netlink.c
index 525dc0b..74db52d 100644
--- a/accel-pppd/ctrl/ipoe/ipoe_netlink.c
+++ b/accel-pppd/ctrl/ipoe/ipoe_netlink.c
@@ -21,6 +21,8 @@
#include "ipoe.h"
#include "if_ipoe.h"
+#include "memdebug.h"
+
#define PKT_ATTR_MAX 256
static struct rtnl_handle rth;
@@ -217,6 +219,84 @@ int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *i
return ret;
}
+static int dump_session(const struct sockaddr_nl *addr, struct nlmsghdr *n, void *arg)
+{
+ struct list_head *list = arg;
+ struct ipoe_session_info *info;
+ struct rtattr *tb[IPOE_ATTR_MAX + 1];
+ struct genlmsghdr *ghdr = NLMSG_DATA(n);
+ int len = n->nlmsg_len;
+ struct rtattr *attrs;
+
+ if (ghdr->cmd != IPOE_CMD_GET) {
+ log_error("ipoe: dump_session: got unexpected command %d\n", ghdr->cmd);
+ return 0;
+ }
+
+ len -= NLMSG_LENGTH(GENL_HDRLEN);
+ if (len < 0 ) {
+ log_error("ipoe: dump_session: wrong message length %i\n", len);
+ return -1;
+ }
+
+ attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN);
+ parse_rtattr(tb, IPOE_ATTR_MAX, attrs, len);
+
+ info = _malloc(sizeof(*info));
+ if (!info) {
+ log_emerg("out of memory\n");
+ return -1;
+ }
+
+ memset(info, 0, sizeof(*info));
+
+ if (tb[IPOE_ATTR_IFINDEX])
+ info->ifindex = *(uint32_t *)(RTA_DATA(tb[IPOE_ATTR_IFINDEX]));
+ else {
+ log_error("ipoe: dump_session: IPOE_ATTR_IFINDEX is absent\n");
+ _free(info);
+ return 0;
+ }
+
+ if (tb[IPOE_ATTR_ADDR])
+ info->addr = *(uint32_t *)(RTA_DATA(tb[IPOE_ATTR_ADDR]));
+
+ if (tb[IPOE_ATTR_PEER_ADDR])
+ info->peer_addr = *(uint32_t *)(RTA_DATA(tb[IPOE_ATTR_PEER_ADDR]));
+
+ list_add_tail(&info->entry, list);
+
+ return 0;
+}
+
+void ipoe_nl_get_sessions(struct list_head *list)
+{
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *ghdr;
+ struct {
+ struct nlmsghdr n;
+ char buf[1024];
+ } req;
+
+ if (rth.fd == -1)
+ return;
+
+ nlh = &req.n;
+ nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ nlh->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ nlh->nlmsg_type = ipoe_genl_id;
+ nlh->nlmsg_seq = rth.dump = ++rth.seq;
+
+ ghdr = NLMSG_DATA(&req.n);
+ ghdr->cmd = IPOE_CMD_GET;
+
+ if (rtnl_send(&rth, (char *)nlh, nlh->nlmsg_len) < 0) {
+ log_emerg("ipoe: failed to send dump request: %s\n", strerror(errno));
+ return;
+ }
+
+ rtnl_dump_filter(&rth, dump_session, list, NULL, NULL);
+}
void ipoe_nl_delete(int ifindex)
{
@@ -378,7 +458,6 @@ static struct triton_md_handler_t up_hnd = {
static void init(void)
{
-
int mcg_id = genl_resolve_mcg(IPOE_GENL_NAME, IPOE_GENL_MCG_PKT, &ipoe_genl_id);
if (mcg_id == -1) {
log_warn("ipoe: unclassified packet handling is disabled\n");