diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-11 15:01:23 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-11 15:01:23 +0400 |
commit | 641e9de3e2ccbd7607ffb90e258c02635fe2616b (patch) | |
tree | f8df517d6dd536551f94942c03454505da480182 | |
parent | 80c32d237e01b1c05663ccfa34003d2f49aa7eee (diff) | |
download | accel-ppp-641e9de3e2ccbd7607ffb90e258c02635fe2616b.tar.gz accel-ppp-641e9de3e2ccbd7607ffb90e258c02635fe2616b.zip |
futher session backup implementation
cli: introduced 'restart' command to restrat daemon
-rw-r--r-- | accel-pppd/backup/backup.c | 9 | ||||
-rw-r--r-- | accel-pppd/backup/backup.h | 1 | ||||
-rw-r--r-- | accel-pppd/cli/std_cmd.c | 84 | ||||
-rw-r--r-- | accel-pppd/cli/telnet.c | 2 | ||||
-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 | ||||
-rw-r--r-- | accel-pppd/include/ap_session.h | 2 | ||||
-rw-r--r-- | accel-pppd/main.c | 115 | ||||
-rw-r--r-- | accel-pppd/session.c | 21 | ||||
-rw-r--r-- | drivers/ipoe/ipoe.c | 49 | ||||
-rw-r--r-- | drivers/ipoe/ipoe.h | 1 |
14 files changed, 360 insertions, 80 deletions
diff --git a/accel-pppd/backup/backup.c b/accel-pppd/backup/backup.c index d045f0c..16349fc 100644 --- a/accel-pppd/backup/backup.c +++ b/accel-pppd/backup/backup.c @@ -2,6 +2,7 @@ #include <string.h> #include "triton.h" +#include "log.h" #include "events.h" #include "ap_session.h" #include "backup.h" @@ -184,6 +185,8 @@ static void __restore_session(struct ap_session *ses) } } + log_ppp_info1("session restored\n"); + if (ctrl) ctrl->ctrl_start(ses); else { @@ -235,11 +238,17 @@ void backup_restore_fd() void backup_restore(int internal) { struct backup_storage *storage; + struct backup_module *module; list_for_each_entry(storage, &storage_list, entry) { if (storage->restore) storage->restore(internal); } + + list_for_each_entry(module, &module_list, entry) { + if (module->restore_complete) + module->restore_complete(); + } } #endif diff --git a/accel-pppd/backup/backup.h b/accel-pppd/backup/backup.h index 39c4ed7..0037596 100644 --- a/accel-pppd/backup/backup.h +++ b/accel-pppd/backup/backup.h @@ -52,6 +52,7 @@ struct backup_module struct ap_session *(*ctrl_restore)(struct backup_mod *); void (*ctrl_start)(struct ap_session *ses); + void (*restore_complete)(void); }; struct backup_storage diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c index 0e1a7b2..01e0157 100644 --- a/accel-pppd/cli/std_cmd.c +++ b/accel-pppd/cli/std_cmd.c @@ -15,6 +15,8 @@ #include "log.h" #include "memdebug.h" +void core_restart(int); + static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { struct timespec ts; @@ -68,7 +70,7 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, cli_sendv(client, " timer_pending: %u\r\n", triton_stat.timer_pending); //=========== - cli_send(client, "ppp:\r\n"); + cli_send(client, "sessions:\r\n"); cli_sendv(client, " starting: %u\r\n", ap_session_stat.starting); cli_sendv(client, " active: %u\r\n", ap_session_stat.active); cli_sendv(client, " finishing: %u\r\n", ap_session_stat.finishing); @@ -268,14 +270,27 @@ static void __terminate_hard2(struct ap_session *ses) ap_session_terminate(ses, TERM_NAS_REBOOT, 1); } +static void terminate_all_sessions(int hard) +{ + struct ap_session *ses; + + pthread_rwlock_rdlock(&ses_lock); + list_for_each_entry(ses, &ses_list, entry) { + if (hard) + triton_context_call(ses->ctrl->ctx, (triton_event_func)__terminate_hard2, ses); + else + triton_context_call(ses->ctrl->ctx, (triton_event_func)__terminate_soft2, ses); + } + pthread_rwlock_unlock(&ses_lock); +} + static int shutdown_exec(const char *cmd, char * const *f, int f_cnt, void *cli) { int hard = 0; - struct ap_session *ses; if (f_cnt == 2) { if (!strcmp(f[1], "soft")) { - ap_shutdown_soft(); + ap_shutdown_soft(NULL); return CLI_CMD_OK; } else if (!strcmp(f[1], "hard")) hard = 1; @@ -286,16 +301,9 @@ static int shutdown_exec(const char *cmd, char * const *f, int f_cnt, void *cli) return CLI_CMD_SYNTAX; } - ap_shutdown_soft(); + ap_shutdown_soft(NULL); - pthread_rwlock_rdlock(&ses_lock); - list_for_each_entry(ses, &ses_list, entry) { - if (hard) - triton_context_call(ses->ctrl->ctx, (triton_event_func)__terminate_hard2, ses); - else - triton_context_call(ses->ctrl->ctx, (triton_event_func)__terminate_soft2, ses); - } - pthread_rwlock_unlock(&ses_lock); + terminate_all_sessions(hard); return CLI_CMD_OK; } @@ -328,11 +336,63 @@ static void reload_help(char * const *fields, int fields_cnt, void *client) cli_send(client, "reload - reload config file\r\n"); } + +//========================== + +static void __do_restart(void) +{ + core_restart(0); + _exit(0); +} + +static int restart_exec(const char *cmd, char * const *f, int f_cnt, void *cli) +{ + int hard; + + if (f_cnt == 2) { + if (strcmp(f[1], "soft") == 0) + hard = 0; + else if (strcmp(f[1], "gracefully") == 0) + hard = 1; + else if (strcmp(f[1], "hard") == 0) + __do_restart(); + else + return CLI_CMD_SYNTAX; + } else if (f_cnt == 1) + hard = 0; + else + return CLI_CMD_SYNTAX; + +#ifndef USE_BACKUP + hard = 1; +#endif + + if (hard) { + ap_shutdown_soft(__do_restart); + terminate_all_sessions(0); + } else { + core_restart(1); + _exit(0); + } + + return CLI_CMD_OK; +} + +static void restart_help(char * const *fields, int fields_cnt, void *client) +{ + cli_send(client, "restart [soft|gracefully|hard] - restart daemon\r\n"); + cli_send(client, "\t\tsoft - restart daemon softly, e.g. keep existing connections if session backup is enabled (default)\r\n"); + cli_send(client, "\t\tgracefully - terminate all connections then restart\r\n"); + cli_send(client, "\t\thard - restart immediatly\r\n"); +} + + static void init(void) { cli_register_simple_cmd2(show_stat_exec, show_stat_help, 2, "show", "stat"); cli_register_simple_cmd2(terminate_exec, terminate_help, 1, "terminate"); cli_register_simple_cmd2(reload_exec, reload_help, 1, "reload"); + cli_register_simple_cmd2(restart_exec, restart_help, 1, "restart"); cli_register_simple_cmd2(shutdown_exec, shutdown_help, 1, "shutdown"); cli_register_simple_cmd2(exit_exec, exit_help, 1, "exit"); } diff --git a/accel-pppd/cli/telnet.c b/accel-pppd/cli/telnet.c index 543e32c..5cb75c7 100644 --- a/accel-pppd/cli/telnet.c +++ b/accel-pppd/cli/telnet.c @@ -555,6 +555,8 @@ static int serv_read(struct triton_md_handler_t *h) continue; } + fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC); + conn = _malloc(sizeof(*conn)); memset(conn, 0, sizeof(*conn)); conn->hnd.fd = sock; 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"); diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h index 075058c..ab6f699 100644 --- a/accel-pppd/include/ap_session.h +++ b/accel-pppd/include/ap_session.h @@ -109,6 +109,6 @@ void ap_session_activate(struct ap_session *ses); void ap_session_ifup(struct ap_session *ses); void ap_session_ifdown(struct ap_session *ses); -void ap_shutdown_soft(void); +void ap_shutdown_soft(void (*cb)(void)); #endif diff --git a/accel-pppd/main.c b/accel-pppd/main.c index 9e51556..1418060 100644 --- a/accel-pppd/main.c +++ b/accel-pppd/main.c @@ -27,7 +27,7 @@ static char *pid_file; static char *conf_file; static char *conf_dump; -static char *exec_file; +static sigset_t orig_set; static void change_limits(void) { @@ -68,11 +68,12 @@ static void config_reload(int num) triton_conf_reload(config_reload_notify); } -static void close_all_fd(void) +/*static void close_all_fd(void) { DIR *dirp; struct dirent ent, *res; char path[128]; + int fd; sprintf(path, "/proc/%u/fd", getpid()); @@ -85,28 +86,30 @@ static void close_all_fd(void) return; if (!res) break; - close((unsigned long)atol(ent.d_name)); + + fd = atol(ent.d_name); + if (fd > 2) + close(fd); } closedir(dirp); -} +}*/ void core_restart(int soft) { char fname[128]; - int fd, n; + int fd, n, f = 0; char cmdline[ARG_MAX]; - char *args[16]; + char exe[PATH_MAX]; + char *argv[16]; char *ptr = cmdline, *endptr; - sigset_t set; if (fork()) { - close_all_fd(); + //close_all_fd(); return; } - sigfillset(&set); - pthread_sigmask(SIG_SETMASK, &set, NULL); + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); sprintf(fname, "/proc/%i/cmdline", getpid()); @@ -116,65 +119,82 @@ void core_restart(int soft) endptr = ptr + n; n = 0; - while (ptr < endptr) { - args[n++] = ptr; + while (ptr < endptr && n < 14) { + if (strcmp(ptr, "--internal")) + argv[n++] = ptr; + else if (soft) { + f = 1; + argv[n++] = ptr; + } + while (ptr < endptr && *ptr++); } - - args[n++] = NULL; #ifdef USE_BACKUP if (soft) backup_restore_fd(); - else #endif - if (fork()) { - close_all_fd(); - _exit(0); - } + sprintf(exe, "/proc/%u/exe", getpid()); + readlink(exe, exe, PATH_MAX); + + if (!f) + argv[n++] = "--internal"; + + argv[n++] = NULL; while (1) { + execv(exe, argv); sleep(3); - execv(args[0], args); } } static void sigsegv(int num) { char cmd[PATH_MAX]; - char fname[PATH_MAX]; + char fname[128]; + char exec_file[PATH_MAX]; struct rlimit lim; -#ifdef USE_BACKUP - core_restart(1); -#else - core_restart(0); -#endif - + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + if (conf_dump) { FILE *f; unsigned int t = time(NULL); - sprintf(fname, "%s/cmd-%u", conf_dump, t); + + chdir(conf_dump); + + sprintf(fname, "cmd-%u", t); f = fopen(fname, "w"); if (!f) goto out; fprintf(f, "thread apply all bt full\ndetach\nquit\n"); fclose(f); - sprintf(cmd, "gdb -x %s %s %d > %s/dump-%u", fname, exec_file, getpid(), conf_dump, t); + sprintf(exec_file, "/proc/%u/exe", getpid()); + readlink(exec_file, exec_file, PATH_MAX); + + sprintf(cmd, "gdb -x %s %s %d > dump-%u", fname, exec_file, getpid(), t); + system(cmd); - unlink(fname); - + + unlink(fname); + } + +out: +#ifdef USE_BACKUP + core_restart(1); +#else + core_restart(0); +#endif + + if (conf_dump) { lim.rlim_cur = RLIM_INFINITY; lim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &lim); - - chdir(conf_dump); } -out: abort(); } @@ -185,15 +205,11 @@ int main(int argc, char **argv) pid_t pid = 0; struct sigaction sa; int pagesize = sysconf(_SC_PAGE_SIZE); -#ifdef USE_BACKUP int internal = 0; -#endif if (argc < 2) goto usage; - exec_file = argv[0]; - for(i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d")) goto_daemon = 1; @@ -212,27 +228,18 @@ int main(int argc, char **argv) conf_dump = memalign(pagesize, len); strcpy(conf_dump, argv[++i]); mprotect(conf_dump, len, PROT_READ); - } + } else if (!strcmp(argv[i], "--internal")) + internal = 1; } if (!conf_file) goto usage; - if (pid_file) { - FILE *f = fopen(pid_file, "r"); - if (f) { - fscanf(f, "%u", &pid); - fclose(f); - } -#ifdef USE_BACKUP - internal = pid == getppid(); -#endif - /*if (pid) { - printf("%i %i %i\n", pid, getppid(), getpid()); - return 0; - }*/ + if (internal) { + while (getppid() != 1) + sleep(1); } - + if (triton_init(conf_file)) _exit(EXIT_FAILURE); @@ -299,7 +306,7 @@ int main(int argc, char **argv) sigdelset(&set, SIGUSR1); sigdelset(&set, 35); sigdelset(&set, 36); - pthread_sigmask(SIG_SETMASK, &set, NULL); + pthread_sigmask(SIG_SETMASK, &set, &orig_set); sigemptyset(&set); //sigaddset(&set, SIGINT); diff --git a/accel-pppd/session.c b/accel-pppd/session.c index d24dcd7..0ca115c 100644 --- a/accel-pppd/session.c +++ b/accel-pppd/session.c @@ -39,6 +39,8 @@ static long long unsigned seq; struct ap_session_stat __export ap_session_stat; +static void (*shutdown_cb)(void); + static void generate_sessionid(struct ap_session *ses); void __export ap_session_init(struct ap_session *ses) @@ -139,8 +141,12 @@ void __export ap_session_finished(struct ap_session *ses) ses->backup->storage->free(ses->backup); #endif - if (ap_shutdown && !ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) - kill(getpid(), SIGTERM); + if (ap_shutdown && !ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) { + if (shutdown_cb) + shutdown_cb(); + else + kill(getpid(), SIGTERM); + } } void __export ap_session_terminate(struct ap_session *ses, int cause, int hard) @@ -178,12 +184,17 @@ void __export ap_session_terminate(struct ap_session *ses, int cause, int hard) ses->ctrl->terminate(ses, hard); } -void ap_shutdown_soft(void) +void ap_shutdown_soft(void (*cb)(void)) { ap_shutdown = 1; + shutdown_cb = cb; - if (!ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) - kill(getpid(), SIGTERM); + if (!ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) { + if (shutdown_cb) + shutdown_cb(); + else + kill(getpid(), SIGTERM); + } } static void generate_sessionid(struct ap_session *ses) diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c index d9ba4f4..d5f52b3 100644 --- a/drivers/ipoe/ipoe.c +++ b/drivers/ipoe/ipoe.c @@ -1226,6 +1226,50 @@ out_unlock: return ret; } +static int fill_info(struct sk_buff *skb, struct ipoe_session *ses, u32 pid, u32 seq) +{ + void *hdr; + + hdr = genlmsg_put(skb, pid, seq, &ipoe_nl_family, NLM_F_MULTI, IPOE_CMD_GET); + if (!hdr) + return -EMSGSIZE; + + NLA_PUT_U32(skb, IPOE_ATTR_IFINDEX, ses->dev->ifindex); + NLA_PUT_U32(skb, IPOE_ATTR_PEER_ADDR, ses->peer_addr); + NLA_PUT_U32(skb, IPOE_ATTR_ADDR, ses->addr); + + return genlmsg_end(skb, hdr); + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +static int ipoe_nl_cmd_dump_sessions(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct ipoe_session *ses; + int idx = 0, start_idx = cb->args[0]; + + down(&ipoe_wlock); + + list_for_each_entry(ses, &ipoe_list2, entry2) { + if (idx > start_idx) + start_idx = 0; + + if (idx++ < start_idx) + continue; + + if (fill_info(skb, ses, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq) < 0) + break; + } + + up(&ipoe_wlock); + + cb->args[0] = idx; + + return skb->len; +} + static int ipoe_nl_cmd_add_net(struct sk_buff *skb, struct genl_info *info) { struct ipoe_network *n; @@ -1314,6 +1358,11 @@ static struct genl_ops ipoe_nl_ops[] = { .flags = GENL_ADMIN_PERM, }, { + .cmd = IPOE_CMD_GET, + .dumpit = ipoe_nl_cmd_dump_sessions, + .policy = ipoe_nl_policy, + }, + { .cmd = IPOE_CMD_ADD_NET, .doit = ipoe_nl_cmd_add_net, .policy = ipoe_nl_policy, diff --git a/drivers/ipoe/ipoe.h b/drivers/ipoe/ipoe.h index 1483310..d40ac21 100644 --- a/drivers/ipoe/ipoe.h +++ b/drivers/ipoe/ipoe.h @@ -8,6 +8,7 @@ enum { IPOE_CMD_CREATE, IPOE_CMD_DELETE, IPOE_CMD_MODIFY, + IPOE_CMD_GET, IPOE_CMD_ADD_NET, IPOE_CMD_DEL_NET, IPOE_REP_PKT, |