diff options
Diffstat (limited to 'accel-pppd/ctrl/ipoe')
-rw-r--r-- | accel-pppd/ctrl/ipoe/CMakeLists.txt | 5 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/backup.c | 53 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 8 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.h | 9 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe_netlink.c | 81 |
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"); |