From 7492fe42c280b57d9579db4f3a2a34366874f743 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Nov 2017 23:04:22 +0100 Subject: [PATCH] pcpserver.c: send ANNOUNCE when IP changed see #254 --- miniupnpd/miniupnpd.c | 6 ++++- miniupnpd/pcpserver.c | 56 ++++++++++++++++++++++++++++++++++++++++++- miniupnpd/pcpserver.h | 6 ++++- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 1c5275d..55a3d31 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -2064,7 +2064,11 @@ main(int argc, char * * argv) #ifdef ENABLE_PCP if(GETFLAG(ENABLENATPMPMASK)) { - PCPPublicAddressChanged(); +#ifdef ENABLE_IPV6 + PCPPublicAddressChanged(snatpmp, addr_count, spcp_v6); +#else /* IPv4 only */ + PCPPublicAddressChanged(snatpmp, addr_count); +#endif } #endif should_send_public_address_change_notif = 0; diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 8faccb2..0c34bca 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1636,11 +1636,65 @@ int OpenAndConfPCPv6Socket(void) } #endif /*ENABLE_IPV6*/ -void PCPPublicAddressChanged(void) +#ifdef ENABLE_IPV6 +static void PCPSendUnsolicitedAnnounce(int * sockets, int n_sockets, int socket6) +#else /* IPv4 only */ +static void PCPSendUnsolicitedAnnounce(int * sockets, int n_sockets) +#endif +{ + int i; + unsigned char buff[PCP_MIN_LEN]; + pcp_info_t info; + ssize_t len; + struct sockaddr_in addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 addr6; +#endif /* ENABLE_IPV6 */ + /* this is an Unsolicited ANNOUNCE response */ + + info.version = this_server_info.server_version; + info.opcode = PCP_OPCODE_ANNOUNCE; + info.result_code = PCP_SUCCESS; + info.lifetime = 0; + createPCPResponse(buff, &info); + /* Multicast PCP restart announcements are sent to + * 224.0.0.1:5350 and/or [ff02::1]:5350 */ + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("224.0.0.1"); + addr.sin_port = htons(5350); + for(i = 0; i < n_sockets; i++) { + len = sendto_or_schedule(sockets[i], buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); + if( len < 0 ) { + syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce() sendto(): %m"); + } + } +#ifdef ENABLE_IPV6 + memset(&addr6, 0, sizeof(struct sockaddr_in6)); + addr6.sin6_family = AF_INET6; + inet_pton(AF_INET6, "FF02::1", &(addr6.sin6_addr)); + addr6.sin6_port = htons(5350); + len = sendto_or_schedule(socket6, buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)); + if( len < 0 ) { + syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce() IPv6 sendto(): %m"); + } +#endif /* ENABLE_IPV6 */ +} + +#ifdef ENABLE_IPV6 +void PCPPublicAddressChanged(int * sockets, int n_sockets, int socket6) +#else /* IPv4 only */ +void PCPPublicAddressChanged(int * sockets, int n_sockets) +#endif { /* 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); +#ifdef ENABLE_IPV6 + PCPSendUnsolicitedAnnounce(sockets, n_sockets, socket6); +#else /* IPv4 Only */ + PCPSendUnsolicitedAnnounce(sockets, n_sockets); +#endif } #endif /*ENABLE_PCP*/ diff --git a/miniupnpd/pcpserver.h b/miniupnpd/pcpserver.h index 7974c22..3357e4f 100644 --- a/miniupnpd/pcpserver.h +++ b/miniupnpd/pcpserver.h @@ -56,6 +56,10 @@ int OpenAndConfPCPv6Socket(void); /* * To be called when Public IP address changed (IPv4) */ -void PCPPublicAddressChanged(void); +#ifdef ENABLE_IPV6 +void PCPPublicAddressChanged(int * sockets, int n_sockets, int socket6); +#else /* IPV4 Only */ +void PCPPublicAddressChanged(int * sockets, int n_sockets); +#endif #endif /* PCPSERVER_H_INCLUDED */