diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 9cfd2a9..6cf6d51 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -49,6 +49,7 @@ #include #endif +#include #include "macros.h" #include "upnpglobalvars.h" #include "upnphttp.h" @@ -109,6 +110,181 @@ int get_udp_dst_port (char *payload); static volatile sig_atomic_t quitting = 0; volatile sig_atomic_t should_send_public_address_change_notif = 0; +#ifdef TOMATO +#if 1 +/* Tomato specific code */ +static volatile int gotusr2 = 0; + +static void +sigusr2(int sig) +{ + gotusr2 = 1; +} + +static void +tomato_save(const char *fname) +{ + unsigned short eport; + unsigned short iport; + unsigned int leaseduration; + unsigned int timestamp; + char proto[4]; + char iaddr[32]; + char desc[64]; + char rhost[32]; + int n; + FILE *f; + int t; + char tmp[128]; + + strcpy(tmp, "/etc/upnp/saveXXXXXX"); + if ((t = mkstemp(tmp)) != -1) + { + if ((f = fdopen(t, "w")) != NULL) + { + n = 0; + while (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) + { + timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; + fprintf(f, "%s %u %s %u [%s] %u\n", proto, eport, iaddr, iport, desc, timestamp); + ++n; + } + fclose(f); + rename(tmp, fname); + } + else + { + close(t); + } + unlink(tmp); + } +} + +static void +tomato_load(void) +{ + FILE *f; + char s[256]; + unsigned short eport; + unsigned short iport; + unsigned int leaseduration; + unsigned int timestamp; + time_t current_time; + char proto[4]; + char iaddr[32]; + char *rhost; + char *a, *b; + + if ((f = fopen("/etc/upnp/data", "r")) != NULL) + { + current_time = time(NULL); + s[sizeof(s) - 1] = 0; + while (fgets(s, sizeof(s) - 1, f)) { + if (sscanf(s, "%3s %hu %31s %hu [%*s] %u", proto, &eport, iaddr, &iport, ×tamp) >= 4) + { + if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL)) + { + if (timestamp > 0) + { + if (timestamp > current_time) + leaseduration = current_time - timestamp; + else + continue; + } + else + { + leaseduration = 0; /* default value */ + } + *b = 0; + rhost = NULL; + upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration); + } + } + } + fclose(f); + } +#ifdef ENABLE_NATPMP +#if 0 + ScanNATPMPforExpiration(); +#endif +#endif + unlink("/etc/upnp/load"); +} + +static void +tomato_delete(void) +{ + FILE *f; + char s[128]; + unsigned short eport; + unsigned short iport; + unsigned int leaseduration; + char proto[4]; + char iaddr[32]; + char desc[64]; + char rhost[32]; + int n; + + if ((f = fopen("/etc/upnp/delete", "r")) != NULL) + { + s[sizeof(s) - 1] = 0; + while (fgets(s, sizeof(s) - 1, f)) + { + if (sscanf(s, "%3s %hu", proto, &eport) == 2) + { + if (proto[0] == '*') + { + n = upnp_get_portmapping_number_of_entries(); + while (--n >= 0) + { + if (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) + { + upnp_delete_redirection(eport, proto); + } + } + break; + } + else + { + upnp_delete_redirection(eport, proto); + } + } + } + fclose(f); + unlink("/etc/upnp/delete"); + } +} + +static void +tomato_helper(void) +{ + struct stat st; + + if (stat("/etc/upnp/delete", &st) == 0) + { + tomato_delete(); + } + + if (stat("/etc/upnp/load", &st) == 0) + { + tomato_load(); + } + + if (stat("/etc/upnp/save", &st) == 0) + { + tomato_save("/etc/upnp/data"); + unlink("/etc/upnp/save"); + } + + if (stat("/etc/upnp/info", &st) == 0) + { + tomato_save("/etc/upnp/data.info"); + unlink("/etc/upnp/info"); + } +} +#endif /* 1 (tomato) */ +#endif /* TOMATO */ + /* OpenAndConfHTTPSocket() : * setup the socket used to handle incoming HTTP connections. */ static int @@ -1412,6 +1588,10 @@ init(int argc, char * * argv, struct runtime_vars * v) syslog(LOG_ERR, "MiniUPnPd is already running. EXITING"); return 1; } + +#ifdef TOMATO + syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started"); +#endif set_startup_time(GETFLAG(SYSUPTIMEMASK)); @@ -1442,8 +1622,14 @@ init(int argc, char * * argv, struct runtime_vars * v) syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT"); return 1; } +#ifdef TOMATO + sa.sa_handler = sigusr2; + sigaction(SIGUSR2, &sa, NULL); + if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) +#else sa.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &sa, NULL) < 0) +#endif { syslog(LOG_ERR, "Failed to ignore SIGPIPE signals"); } @@ -1477,6 +1663,10 @@ init(int argc, char * * argv, struct runtime_vars * v) reload_from_lease_file(); #endif +#ifdef TOMATO + tomato_load(); +#endif + return 0; print_usage: fprintf(stderr, "Usage:\n\t" @@ -1810,6 +2000,10 @@ main(int argc, char * * argv) } #endif +#ifdef TOMATO + tomato_helper(); +#endif + /* main loop */ while(!quitting) { @@ -2064,6 +2258,14 @@ main(int argc, char * * argv) if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) { if(quitting) goto shutdown; +#ifdef TOMATO + if (gotusr2) + { + gotusr2 = 0; + tomato_helper(); + continue; + } +#endif if(errno == EINTR) continue; /* interrupted by a signal, start again */ syslog(LOG_ERR, "select(all): %m"); syslog(LOG_ERR, "Failed to select open sockets. EXITING"); @@ -2349,6 +2551,9 @@ shutdown: /* try to send pending packets */ finalize_sendto(); +#ifdef TOMATO + tomato_save("/etc/upnp/data"); +#endif /* close out open sockets */ while(upnphttphead.lh_first != NULL) {