diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
commit | 80c32d237e01b1c05663ccfa34003d2f49aa7eee (patch) | |
tree | a49da21b5219e4bc89d9794918f054f3620cb140 /accel-pppd/ctrl/ipoe | |
parent | 64b5b693764c4f36870fd988ccbb53bcb188e74d (diff) | |
download | accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.tar.gz accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.zip |
initial session backup implementation
Diffstat (limited to 'accel-pppd/ctrl/ipoe')
-rw-r--r-- | accel-pppd/ctrl/ipoe/CMakeLists.txt | 4 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/backup.c | 168 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 59 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.h | 4 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe_netlink.c | 1 |
5 files changed, 235 insertions, 1 deletions
diff --git a/accel-pppd/ctrl/ipoe/CMakeLists.txt b/accel-pppd/ctrl/ipoe/CMakeLists.txt index 297d81b1..7be18cc0 100644 --- a/accel-pppd/ctrl/ipoe/CMakeLists.txt +++ b/accel-pppd/ctrl/ipoe/CMakeLists.txt @@ -17,6 +17,10 @@ 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 new file mode 100644 index 00000000..b2d0c0c4 --- /dev/null +++ b/accel-pppd/ctrl/ipoe/backup.c @@ -0,0 +1,168 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netinet/in.h> +#include <net/ethernet.h> + +#include "log.h" +#include "memdebug.h" + +#include "ipoe.h" +#include "backup.h" +#include "ap_session_backup.h" + +#define IPOE_TAG_HWADDR 1 +#define IPOE_TAG_CLIENT_ID 2 +#define IPOE_TAG_AGENT_CIRCUIT_ID 3 +#define IPOE_TAG_AGENT_REMOTE_ID 4 +#define IPOE_TAG_XID 5 +#define IPOE_TAG_GIADDR 6 +#define IPOE_TAG_CALLING_SID 7 +#define IPOE_TAG_CALLED_SID 8 +#define IPOE_TAG_IFNAME 9 + +#define IPOE_TAG_IFINDEX 100 + + +#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; + +static int session_save(struct ap_session *ses, struct backup_mod *m) +{ + struct ipoe_session *conn = container_of(ses, typeof(*conn), ses); + + add_tag(IPOE_TAG_HWADDR, conn->hwaddr, 6); + add_tag(IPOE_TAG_CALLING_SID, ses->ctrl->calling_station_id, strlen(ses->ctrl->calling_station_id)); + add_tag(IPOE_TAG_CALLED_SID, ses->ctrl->called_station_id, strlen(ses->ctrl->called_station_id)); + add_tag(IPOE_TAG_XID, &conn->xid, 4); + add_tag(IPOE_TAG_GIADDR, &conn->giaddr, 4); + + if (conn->client_id) + add_tag(IPOE_TAG_CLIENT_ID, conn->client_id->data, conn->client_id->len); + if (conn->agent_circuit_id) + add_tag(IPOE_TAG_AGENT_CIRCUIT_ID, conn->agent_circuit_id->data, conn->agent_circuit_id->len); + 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); + + return 0; +} + +static int session_restore(struct ap_session *ses, struct backup_mod *m) +{ + struct ipoe_session *conn = container_of(ses, typeof(*conn), ses); + + + return 0; +} + +static void set_dhcpv4_opt(struct dhcp_opt **opt, struct backup_tag *t, uint8_t **ptr) +{ + *opt = (struct dhcp_opt *)(*ptr); + (*opt)->len = t->size; + memcpy((*opt)->data, t->data, t->size); + (*ptr) += sizeof(**opt) + t->size; +} + +static struct ap_session *ctrl_restore(struct backup_mod *m) +{ + struct backup_tag *t; + struct ipoe_session *ses; + struct ipoe_serv *serv; + struct backup_tag *ifname = NULL; + int dlen = 0; + uint8_t *ptr; + + //if (!m->data->internal) + // return NULL; + + list_for_each_entry(t, &m->tag_list, entry) { + switch(t->id) { + case IPOE_TAG_CLIENT_ID: + case IPOE_TAG_AGENT_CIRCUIT_ID: + case IPOE_TAG_AGENT_REMOTE_ID: + dlen += sizeof(struct dhcp_opt) + t->size; + break; + case IPOE_TAG_IFNAME: + ifname = t; + break; + } + } + + if (!ifname) + return NULL; + + serv = ipoe_find_serv((char *)ifname->data); + if (!serv) + return NULL; + + ses = ipoe_session_alloc(); + if (!ses) + return NULL; + + if (dlen) + ses->data = _malloc(dlen); + + ptr = ses->data; + + list_for_each_entry(t, &m->tag_list, entry) { + switch(t->id) { + case IPOE_TAG_HWADDR: + memcpy(ses->hwaddr, t->data, 6); + break; + case IPOE_TAG_CALLING_SID: + ses->ctrl.calling_station_id = _malloc(t->size + 1); + memcpy(ses->ctrl.calling_station_id, t->data, t->size); + ses->ctrl.calling_station_id[t->size] = 0; + break; + case IPOE_TAG_CALLED_SID: + ses->ctrl.called_station_id = _malloc(t->size + 1); + memcpy(ses->ctrl.called_station_id, t->data, t->size); + ses->ctrl.called_station_id[t->size] = 0; + break; + case IPOE_TAG_XID: + ses->xid = *(uint32_t *)t->data; + break; + case IPOE_TAG_GIADDR: + ses->giaddr = *(uint32_t *)t->data; + break; + case IPOE_TAG_CLIENT_ID: + set_dhcpv4_opt(&ses->client_id, t, &ptr); + break; + case IPOE_TAG_AGENT_CIRCUIT_ID: + set_dhcpv4_opt(&ses->agent_circuit_id, t, &ptr); + break; + case IPOE_TAG_AGENT_REMOTE_ID: + set_dhcpv4_opt(&ses->agent_remote_id, t, &ptr); + break; + } + } + + ses->serv = serv; + + triton_context_register(&ses->ctx, &ses->ses); + triton_context_wakeup(&ses->ctx); + + pthread_mutex_lock(&serv->lock); + list_add_tail(&ses->entry, &serv->sessions); + pthread_mutex_unlock(&serv->lock); + + return &ses->ses; +} + +static struct backup_module mod = { + .id = MODID_IPOE, + .save = session_save, + .restore = session_restore, + .ctrl_restore = ctrl_restore, +}; + +static void init(void) +{ + backup_register_module(&mod); +} + +DEFINE_INIT(100, init); + diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 5878b0c4..fea61a8b 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -73,6 +73,7 @@ struct iplink_arg 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 struct ipoe_session *ipoe_session_lookup(struct ipoe_serv *serv, struct dhcpv4_packet *pack) { @@ -321,13 +322,18 @@ static void ipoe_session_free(struct ipoe_session *ses) static void ipoe_session_finished(struct ap_session *s) { struct ipoe_session *ses = container_of(s, typeof(*ses), ses); + int serv_close; log_ppp_debug("ipoe: session finished\n"); pthread_mutex_lock(&ses->serv->lock); list_del(&ses->entry); + serv_close = ses->serv->need_close && list_empty(&ses->serv->sessions); pthread_mutex_unlock(&ses->serv->lock); + if (serv_close) + ipoe_serv_close(&ses->serv->ctx); + triton_context_call(&ses->ctx, (triton_event_func)ipoe_session_free, ses); } @@ -590,6 +596,37 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc return ses; } +struct ipoe_session *ipoe_session_alloc(void) +{ + struct ipoe_session *ses; + + ses = mempool_alloc(ses_pool); + if (!ses) { + log_emerg("out of memery\n"); + return NULL; + } + + memset(ses, 0, sizeof(*ses)); + + ap_session_init(&ses->ses); + + ses->ifindex = -1; + + ses->ctx.before_switch = log_switch; + ses->ctx.close = ipoe_session_close; + ses->ctrl.ctx = &ses->ctx; + ses->ctrl.started = ipoe_session_started; + ses->ctrl.finished = ipoe_session_finished; + ses->ctrl.terminate = ipoe_session_terminate; + ses->ctrl.type = CTRL_TYPE_IPOE; + ses->ctrl.name = "ipoe"; + + ses->ses.ctrl = &ses->ctrl; + ses->ses.chan_name = ses->ctrl.calling_station_id; + + return ses; +} + void ipoe_recv_up(int ifindex, struct ethhdr *eth, struct iphdr *iph) { struct ipoe_serv *serv; @@ -619,6 +656,14 @@ static void ipoe_serv_close(struct triton_context_t *ctx) { struct ipoe_serv *serv = container_of(ctx, typeof(*serv), ctx); + pthread_mutex_lock(&serv->lock); + if (!list_empty(&serv->sessions)) { + serv->need_close = 1; + pthread_mutex_unlock(&serv->lock); + return; + } + pthread_mutex_unlock(&serv->lock); + if (serv->dhcpv4) dhcpv4_free(serv->dhcpv4); @@ -663,6 +708,18 @@ static void ipoe_drop_sessions(struct ipoe_serv *serv, struct ipoe_session *skip } } +struct ipoe_serv *ipoe_find_serv(const char *ifname) +{ + struct ipoe_serv *serv; + + list_for_each_entry(serv, &serv_list, entry) { + if (strcmp(serv->ifname, ifname) == 0) + return serv; + } + + return NULL; +} + static void add_interface(const char *ifname, int ifindex, const char *opt) { char *str0, *str, *ptr1, *ptr2; @@ -758,6 +815,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt) serv = _malloc(sizeof(*serv)); memset(serv, 0, sizeof(*serv)); + serv->ctx.close = ipoe_serv_close; serv->ifname = _strdup(ifname); serv->ifindex = ifindex; serv->opt_shared = opt_shared; @@ -873,6 +931,7 @@ static void load_interfaces(struct conf_sect_t *sect) list_for_each_safe(pos, n, &serv_list) { serv = list_entry(pos, typeof(*serv), entry); if (!serv->active) { + ipoe_drop_sessions(serv, NULL); list_del(&serv->entry); triton_context_call(&serv->ctx, (triton_event_func)ipoe_serv_close, &serv->ctx); } diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h index 97b13e63..a2efd374 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.h +++ b/accel-pppd/ctrl/ipoe/ipoe.h @@ -22,6 +22,7 @@ struct ipoe_serv int opt_shared:1; int opt_dhcpv4:1; int opt_up:1; + int need_close:1; }; struct dhcp_opt @@ -57,6 +58,9 @@ struct iphdr; struct ethhdr; void ipoe_recv_up(int ifindex, struct ethhdr *eth, struct iphdr *iph); +struct ipoe_session *ipoe_session_alloc(void); + +struct ipoe_serv *ipoe_find_serv(const char *ifname); void ipoe_nl_add_net(uint32_t addr, int mask); void ipoe_nl_delete_nets(void); diff --git a/accel-pppd/ctrl/ipoe/ipoe_netlink.c b/accel-pppd/ctrl/ipoe/ipoe_netlink.c index ec603d5d..525dc0b3 100644 --- a/accel-pppd/ctrl/ipoe/ipoe_netlink.c +++ b/accel-pppd/ctrl/ipoe/ipoe_netlink.c @@ -364,7 +364,6 @@ static int ipoe_up_read(struct triton_md_handler_t *h) static void ipoe_up_close(struct triton_context_t *ctx) { - rtnl_close(&rth); triton_md_unregister_handler(&up_hnd); triton_context_unregister(ctx); } |