diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 2db3d16..c5a2618 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.432 2017/05/24 22:47:53 nanard Exp $ +$Id: Changelog.txt,v 1.437 2018/03/12 22:45:13 nanard Exp $ + +2018/03/13: + Use monotonic clock for timeouts, etc. 2018/02/22: Add option force_igd_desc_v1 to force devices and services versions diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 7d32f86..df79199 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.221 2017/05/27 07:47:55 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.226 2018/03/13 10:35:55 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -794,43 +794,39 @@ sigusr1(int sig) /* record the startup time, for returning uptime */ static void -set_startup_time(int sysuptime) +set_startup_time(void) { - startup_time = time(NULL); + startup_time = upnp_time(); #ifdef USE_TIME_AS_BOOTID - if(startup_time > 60*60*24 && upnp_bootid == 1) { - /* We know we are not January the 1st 1970 */ - upnp_bootid = (unsigned int)startup_time; + if(upnp_bootid == 1) { + upnp_bootid = (unsigned int)time(NULL); /* from UDA v1.1 : * A convenient mechanism is to set this field value to the time * that the device sends its initial announcement, expressed as * seconds elapsed since midnight January 1, 1970; */ } #endif /* USE_TIME_AS_BOOTID */ - if(sysuptime) + if(GETFLAG(SYSUPTIMEMASK)) { /* use system uptime instead of daemon uptime */ #if defined(__linux__) - char buff[64]; - int uptime = 0, fd; - fd = open("/proc/uptime", O_RDONLY); - if(fd < 0) + unsigned long uptime = 0; + FILE * f = fopen("/proc/uptime", "r"); + if(f == NULL) { - syslog(LOG_ERR, "open(\"/proc/uptime\" : %m"); + syslog(LOG_ERR, "fopen(\"/proc/uptime\") : %m"); } else { - memset(buff, 0, sizeof(buff)); - if(read(fd, buff, sizeof(buff) - 1) < 0) + if(fscanf(f, "%lu", &uptime) != 1) { - syslog(LOG_ERR, "read(\"/proc/uptime\" : %m"); + syslog(LOG_ERR, "fscanf(\"/proc/uptime\") : %m"); } else { - uptime = atoi(buff); - syslog(LOG_INFO, "system uptime is %d seconds", uptime); + syslog(LOG_INFO, "system uptime is %lu seconds", uptime); } - close(fd); + fclose(f); startup_time -= uptime; } #elif defined(SOLARIS_KSTATS) @@ -1632,7 +1628,7 @@ init(int argc, char * * argv, struct runtime_vars * v) syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started"); #endif /* TOMATO */ - set_startup_time(GETFLAG(SYSUPTIMEMASK)); + set_startup_time(); /* presentation url */ if(presurl) @@ -2063,11 +2059,13 @@ main(int argc, char * * argv) /* main loop */ while(!quitting) { +#ifdef USE_TIME_AS_BOOTID /* Correct startup_time if it was set with a RTC close to 0 */ - if((startup_time<60*60*24) && (time(NULL)>60*60*24)) + if((upnp_bootid<60*60*24) && (time(NULL)>60*60*24)) { - set_startup_time(GETFLAG(SYSUPTIMEMASK)); + upnp_bootid = time(NULL); } +#endif /* send public address change notifications if needed */ if(should_send_public_address_change_notif) { diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 6b94428..0ed09e0 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.52 2015/05/27 12:43:14 nanard Exp $ */ +/* $Id: natpmp.c,v 1.55 2018/03/12 22:41:54 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2017 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -247,7 +247,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, if(epoch_origin == 0) { epoch_origin = startup_time; } - WRITENU32(resp+4, time(NULL) - epoch_origin); + WRITENU32(resp+4, upnp_time() - epoch_origin); if(req[0] > 0) { /* invalid version */ syslog(LOG_WARNING, "unsupported NAT-PMP version : %u", @@ -382,15 +382,9 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } } /* do the redirection */ -#if 0 - timestamp = (unsigned)(time(NULL) - startup_time) - + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); -#else - timestamp = time(NULL) + lifetime; + timestamp = upnp_time() + lifetime; snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", eport, (proto==IPPROTO_TCP)?"tcp":"udp"); -#endif /* TODO : check return code */ if(upnp_redirect_internal(NULL, eport, senderaddrstr, iport, proto, desc, @@ -439,7 +433,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets) if(epoch_origin == 0) { epoch_origin = startup_time; } - WRITENU32(notif+4, time(NULL) - epoch_origin); + WRITENU32(notif+4, upnp_time() - epoch_origin); #ifndef MULTIPLE_EXTERNAL_IP FillPublicAddressResponse(notif, 0); if(notif[3]) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 0c96eea..7930fa5 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.39 2015/06/22 07:28:21 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.47 2018/03/13 10:21:19 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -684,7 +684,7 @@ static int CreatePCPPeer_NAT(pcp_info_t *pcp_msg_info) uint16_t eport = pcp_msg_info->ext_port; /* public port */ char peerip_s[INET6_ADDRSTRLEN], extip_s[INET6_ADDRSTRLEN]; - time_t timestamp = time(NULL) + pcp_msg_info->lifetime; + time_t timestamp = upnp_time() + pcp_msg_info->lifetime; int r; FillSA((struct sockaddr*)&intip, pcp_msg_info->mapped_ip, @@ -890,7 +890,7 @@ static int CreatePCPMap_NAT(pcp_info_t *pcp_msg_info) char iaddr_old[INET6_ADDRSTRLEN]; uint16_t iport_old, eport_first = 0; int any_eport_allowed = 0; - unsigned int timestamp = time(NULL) + pcp_msg_info->lifetime; + unsigned int timestamp = upnp_time() + pcp_msg_info->lifetime; if (pcp_msg_info->ext_port == 0) { pcp_msg_info->ext_port = pcp_msg_info->int_port; @@ -1450,7 +1450,7 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) if(epoch_origin == 0) { epoch_origin = startup_time; } - WRITENU32(response + 8, time(NULL) - epoch_origin); /* epochtime */ + WRITENU32(response + 8, upnp_time() - epoch_origin); /* epochtime */ switch (pcp_msg_info->result_code) { /*long lifetime errors*/ case PCP_ERR_UNSUPP_VERSION: @@ -1690,7 +1690,7 @@ void PCPPublicAddressChanged(int * sockets, int n_sockets) /* according to RFC 6887 8.5 : * if the external IP address(es) of the NAT (controlled by * the PCP server) changes, the Epoch time MUST be reset. */ - epoch_origin = time(NULL); + epoch_origin = upnp_time(); #ifdef ENABLE_IPV6 PCPSendUnsolicitedAnnounce(sockets, n_sockets, socket6); #else /* IPv4 Only */ diff --git a/miniupnpd/testasyncsendto.c b/miniupnpd/testasyncsendto.c index 51a58e2..6d441ea 100644 --- a/miniupnpd/testasyncsendto.c +++ b/miniupnpd/testasyncsendto.c @@ -1,4 +1,4 @@ -/* $Id: testasyncsendto.c,v 1.4 2018/01/16 00:50:49 nanard Exp $ */ +/* $Id: testasyncsendto.c,v 1.5 2018/03/13 10:25:52 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ @@ -21,6 +21,8 @@ #include "asyncsendto.h" struct lan_addr_list lan_addrs; +int runtime_flags = 0; +time_t startup_time = 0; #define DEST_IP "239.255.255.250" #define DEST_PORT 1900 diff --git a/miniupnpd/testgetroute.c b/miniupnpd/testgetroute.c index 43e7edb..61491be 100644 --- a/miniupnpd/testgetroute.c +++ b/miniupnpd/testgetroute.c @@ -1,7 +1,7 @@ -/* $Id: testgetroute.c,v 1.5 2013/02/06 12:07:36 nanard Exp $ */ +/* $Id: testgetroute.c,v 1.7 2018/03/13 10:25:52 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard + * (c) 2006-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -23,6 +23,8 @@ #endif struct lan_addr_list lan_addrs; +int runtime_flags = 0; +time_t startup_time = 0; int main(int argc, char ** argv) diff --git a/miniupnpd/upnpevents.c b/miniupnpd/upnpevents.c index ce8364d..dd73487 100644 --- a/miniupnpd/upnpevents.c +++ b/miniupnpd/upnpevents.c @@ -1,8 +1,8 @@ -/* $Id: upnpevents.c,v 1.38 2017/11/02 15:50:35 nanard Exp $ */ +/* $Id: upnpevents.c,v 1.39 2018/03/12 22:41:54 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2008-2017 Thomas Bernard + * (c) 2008-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -182,7 +182,7 @@ upnpevents_addSubscriber(const char * eventurl, if(!tmp) return NULL; if(timeout) - tmp->timeout = time(NULL) + timeout; + tmp->timeout = upnp_time() + timeout; LIST_INSERT_HEAD(&subscriberlist, tmp, entries); upnp_event_create_notify(tmp); return tmp->uuid; @@ -197,10 +197,10 @@ upnpevents_renewSubscription(const char * sid, int sidlen, int timeout) if((sidlen == 41) && (memcmp(sid, sub->uuid, 41) == 0)) { #ifdef UPNP_STRICT /* check if the subscription already timeouted */ - if(sub->timeout && time(NULL) > sub->timeout) + if(sub->timeout && upnp_time() > sub->timeout) continue; #endif - sub->timeout = (timeout ? time(NULL) + timeout : 0); + sub->timeout = (timeout ? upnp_time() + timeout : 0); return sub->uuid; } } @@ -624,7 +624,7 @@ void upnpevents_processfds(fd_set *readset, fd_set *writeset) obj = next; } /* remove timeouted subscribers */ - curtime = time(NULL); + curtime = upnp_time(); for(sub = subscriberlist.lh_first; sub != NULL; ) { subnext = sub->entries.le_next; if(sub->timeout && curtime > sub->timeout && sub->notify == NULL) { diff --git a/miniupnpd/upnppinhole.c b/miniupnpd/upnppinhole.c index 9a4a131..71880a3 100644 --- a/miniupnpd/upnppinhole.c +++ b/miniupnpd/upnppinhole.c @@ -1,7 +1,7 @@ -/* $Id: upnppinhole.c,v 1.7 2014/12/09 09:13:53 nanard Exp $ */ +/* $Id: upnppinhole.c,v 1.12 2018/03/13 10:24:55 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard + * (c) 2006-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -130,7 +130,7 @@ upnp_add_inboundpinhole(const char * raddr, AF_INET6, iaddr, &address); return -4; } - current = time(NULL); + current = upnp_time(); timestamp = current + leasetime; r = 0; @@ -252,7 +252,7 @@ upnp_get_pinhole_info(unsigned short uid, if(r >= 0) { if(leasetime) { time_t current_time; - current_time = time(NULL); + current_time = upnp_time(); if(timestamp > (unsigned int)current_time) *leasetime = timestamp - current_time; else @@ -289,7 +289,7 @@ upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime) #if defined(USE_PF) || defined(USE_NETFILTER) unsigned int timestamp; - timestamp = time(NULL) + leasetime; + timestamp = upnp_time() + leasetime; return update_pinhole(uid, timestamp); #else UNUSED(uid); UNUSED(leasetime); @@ -331,7 +331,7 @@ upnp_check_pinhole_working(const char * uid, /* TODO : to be implemented */ #if 0 FILE * fd; - time_t expire = time(NULL); + time_t expire = upnp_time(); char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]=""; int res = -4, str_len; diff --git a/miniupnpd/upnpredirect.c b/miniupnpd/upnpredirect.c index a45f98a..f4071ef 100644 --- a/miniupnpd/upnpredirect.c +++ b/miniupnpd/upnpredirect.c @@ -1,4 +1,4 @@ -/* $Id: upnpredirect.c,v 1.92 2018/01/16 00:50:49 nanard Exp $ */ +/* $Id: upnpredirect.c,v 1.93 2018/03/12 22:41:53 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ @@ -25,6 +25,7 @@ #include "upnpglobalvars.h" #include "upnpevents.h" #include "portinuse.h" +#include "upnputils.h" #if defined(USE_NETFILTER) #include "netfilter/iptcrdr.h" #endif @@ -202,7 +203,7 @@ int reload_from_lease_file() syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file); } - current_time = time(NULL); + current_time = upnp_time(); while(fgets(line, sizeof(line), fd)) { syslog(LOG_DEBUG, "parsing lease file line '%s'", line); proto = line; @@ -353,7 +354,7 @@ upnp_redirect(const char * rhost, unsigned short eport, (rhost && (strcmp(rhost, rhost_old) == 0)))) { syslog(LOG_INFO, "updating existing port mapping %hu %s (rhost '%s') => %s:%hu", eport, protocol, rhost_old, iaddr_old, iport_old); - timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; + timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0; if(iport != iport_old) { r = update_portmapping(ext_if_name, eport, proto, iport, desc, timestamp); } else { @@ -378,7 +379,7 @@ upnp_redirect(const char * rhost, unsigned short eport, return -4; #endif /* CHECK_PORTINUSE */ } else { - timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; + timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0; syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s", eport, iaddr, iport, protocol, desc); return upnp_redirect_internal(rhost, eport, iaddr, iport, proto, @@ -448,7 +449,7 @@ upnp_get_redirection_infos(unsigned short eport, const char * protocol, 0, 0); if(r == 0 && timestamp > 0 && - timestamp > (unsigned int)(current_time = time(NULL))) { + timestamp > (unsigned int)(current_time = upnp_time())) { *leaseduration = timestamp - current_time; } else { *leaseduration = 0; @@ -481,7 +482,7 @@ upnp_get_redirection_infos_by_index(int index, return -1; else { - current_time = time(NULL); + current_time = upnp_time(); *leaseduration = (timestamp > (unsigned int)current_time) ? (timestamp - current_time) : 0; @@ -567,7 +568,7 @@ get_upnp_rules_state_list(int max_rules_number_target) tmp = malloc(sizeof(struct rule_state)); if(!tmp) return 0; - current_time = time(NULL); + current_time = upnp_time(); nextruletoclean_timestamp = 0; while(get_redirect_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0, &iport, &proto, 0, 0, 0,0, ×tamp, diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index 0ace576..b4f156c 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -1,4 +1,4 @@ -/* $Id: upnpsoap.c,v 1.149 2018/01/16 00:50:49 nanard Exp $ */ +/* $Id: upnpsoap.c,v 1.151 2018/03/13 10:32:53 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ @@ -32,6 +32,7 @@ #include "getifstats.h" #include "getconnstatus.h" #include "upnpurns.h" +#include "upnputils.h" /* utility function */ static int is_numeric(const char * s) @@ -274,7 +275,7 @@ GetStatusInfo(struct upnphttp * h, const char * action, const char * ns) * Disconnecting, Disconnected */ status = get_wan_connection_status_str(ext_if_name); - uptime = (time(NULL) - startup_time); + uptime = upnp_get_uptime(); bodylen = snprintf(body, sizeof(body), resp, action, ns, /*SERVICE_TYPE_WANIPC,*/ status, (long)uptime, action); diff --git a/miniupnpd/upnputils.c b/miniupnpd/upnputils.c index 71bbe1e..010150f 100644 --- a/miniupnpd/upnputils.c +++ b/miniupnpd/upnputils.c @@ -1,7 +1,7 @@ -/* $Id: upnputils.c,v 1.10 2014/11/07 11:53:39 nanard Exp $ */ +/* $Id: upnputils.c,v 1.12 2018/03/13 10:25:20 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard + * (c) 2006-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -184,3 +185,38 @@ get_lan_for_peer(const struct sockaddr * peer) return lan_addr; } +time_t upnp_time(void) +{ +#if defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC) +#if defined(CLOCK_MONOTONIC_FAST) +#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST +#else +#define UPNP_CLOCKID CLOCK_MONOTONIC +#endif + struct timespec ts; + if (clock_gettime(UPNP_CLOCKID, &ts) < 0) + return time(NULL); + else + return ts.tv_sec; +#else + return time(NULL); +#endif +} + +time_t upnp_get_uptime(void) +{ +#if defined(CLOCK_UPTIME_FAST) || defined(CLOCK_UPTIME) +#if defined(CLOCK_UPTIME_FAST) +#define UPNP_CLOCKID_UPTIME CLOCK_UPTIME_FAST +#else +#define UPNP_CLOCKID_UPTIME CLOCK_UPTIME +#endif + if(GETFLAG(SYSUPTIMEMASK)) + { + struct timespec ts; + if (clock_gettime(UPNP_CLOCKID_UPTIME, &ts) >= 0) + return ts.tv_sec; + } +#endif + return upnp_time() - startup_time; +} diff --git a/miniupnpd/upnputils.h b/miniupnpd/upnputils.h index 6031425..66f3fc9 100644 --- a/miniupnpd/upnputils.h +++ b/miniupnpd/upnputils.h @@ -1,7 +1,7 @@ -/* $Id: upnputils.h,v 1.6 2014/03/31 12:32:57 nanard Exp $ */ +/* $Id: upnputils.h,v 1.9 2018/03/13 10:25:20 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2013 Thomas Bernard + * (c) 2011-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -29,6 +29,16 @@ set_non_blocking(int fd); struct lan_addr_s * get_lan_for_peer(const struct sockaddr * peer); +/** + * get the time for upnp (release expiration, etc.) + * Similar to a monotonic time(NULL) + */ +time_t upnp_time(void); + +/** + * return either the machine or the daemon uptime + */ +time_t upnp_get_uptime(void); /** * define portability macros