# HG changeset patch
# Node ID 3a0f0ee652b5
# Parent  08b6b45431c9
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -628,6 +628,8 @@
 		* PurplePmpType
 		* purple_pmp_create_map
 		* purple_pmp_destroy_map
+		* purple_pmp_init
+		* purple_pmp_get_public_ip
 		* purple_pounce_action_get_attribute
 		* purple_pounce_action_is_enabled
 		* purple_pounce_action_register
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -26,7 +26,6 @@
 	'media/enum-types.c',
 	'media.c',
 	'mediamanager.c',
-	'nat-pmp.c',
 	'network.c',
 	'notify.c',
 	'plugins.c',
@@ -132,7 +131,6 @@
 	'media.h',
 	'media-gst.h',
 	'mediamanager.h',
-	'nat-pmp.h',
 	'network.h',
 	'notify.h',
 	'plugins.h',
diff --git a/libpurple/nat-pmp.h b/libpurple/nat-pmp.h
deleted file mode 100644
--- a/libpurple/nat-pmp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * Most code in nat-pmp.h copyright (C) 2007, R. Tyler Ballance, bleep, LLC.
- * This file is distributed under the 3-clause (modified) BSD license:
- * Redistribution and use in source and binary forms, with or without modification, are permitted
- * provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of conditions and
- * the following disclaimer.
- * Neither the name of the bleep. LLC nor the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
-# error "only <purple.h> may be included directly"
-#endif
-
-#ifndef PURPLE_NAT_PMP_H
-#define PURPLE_NAT_PMP_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/**
- * purple_pmp_init:
- *
- * Initialize nat-pmp
- */
-void purple_pmp_init(void);
-
-char *purple_pmp_get_public_ip(void);
-
-G_END_DECLS
-
-#endif /* PURPLE_NAT_PMP_H */
diff --git a/libpurple/nat-pmp.c b/libpurple/nat-pmp.c
deleted file mode 100644
--- a/libpurple/nat-pmp.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * Most code in nat-pmp.c copyright (C) 2007, R. Tyler Ballance, bleep, LLC.
- * This file is distributed under the 3-clause (modified) BSD license:
- * Redistribution and use in source and binary forms, with or without modification, are permitted
- * provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of conditions and
- * the following disclaimer.
- * Neither the name of the bleep. LLC nor the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-#include <gio/gio.h>
-
-#include "internal.h"
-#include "nat-pmp.h"
-#include "debug.h"
-#include "signals.h"
-#include "network.h"
-
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_SYSCTL_H
-# include <sys/sysctl.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-/* We will need sysctl() and NET_RT_DUMP, both of which are not present
- * on all platforms, to continue. */
-#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
-
-#include <net/route.h>
-
-#define PMP_DEBUG	1
-
-typedef struct {
-	guint8	version;
-	guint8 opcode;
-} PurplePmpIpRequest;
-
-typedef struct {
-	guint8		version;
-	guint8		opcode; /* 128 + n */
-	guint16		resultcode;
-	guint32		epoch;
-	guint32		address;
-} PurplePmpIpResponse;
-
-typedef enum {
-	PURPLE_PMP_STATUS_UNDISCOVERED = -1,
-	PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER,
-	PURPLE_PMP_STATUS_DISCOVERING,
-	PURPLE_PMP_STATUS_DISCOVERED
-} PurpleUPnPStatus;
-
-typedef struct {
-	PurpleUPnPStatus status;
-	gchar *publicip;
-} PurplePmpInfo;
-
-static PurplePmpInfo pmp_info = {PURPLE_PMP_STATUS_UNDISCOVERED, NULL};
-
-/*
- *	Thanks to R. Matthew Emerson for the fixes on this
- */
-
-#define PMP_VERSION			0
-#define PMP_PORT			5351
-#define PMP_TIMEOUT			250000	/* 250000 useconds */
-
-/* alignment constraint for routing socket */
-#define ROUNDUP(a)			((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-#define ADVANCE(x, n)		(x += ROUNDUP((n)->sa_len))
-
-static void
-get_rtaddrs(int bitmask, struct sockaddr *sa, struct sockaddr *addrs[])
-{
-	int i;
-
-	for (i = 0; i < RTAX_MAX; i++)
-	{
-		if (bitmask & (1 << i))
-		{
-			addrs[i] = sa;
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-			sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
-#else
-			if (sa->sa_family == AF_INET)
-				sa = (struct sockaddr*)(sizeof(struct sockaddr_in) + (char *)sa);
-#ifdef AF_INET6
-			else if (sa->sa_family == AF_INET6)
-				sa = (struct sockaddr*)(sizeof(struct sockaddr_in6) + (char *)sa);
-#endif
-#endif
-		}
-		else
-		{
-			addrs[i] = NULL;
-		}
-	}
-}
-
-static int
-is_default_route(struct sockaddr *sa, struct sockaddr *mask)
-{
-    struct sockaddr_in *sin;
-
-    if (sa->sa_family != AF_INET)
-		return 0;
-
-    sin = (struct sockaddr_in *)sa;
-    if ((sin->sin_addr.s_addr == INADDR_ANY) &&
-		mask &&
-		(g_ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) == 0L ||
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-		 mask->sa_len == 0
-#else
-		0
-#endif
-		))
-		return 1;
-    else
-		return 0;
-}
-
-/*!
- * The return sockaddr_in must be g_free()'d when no longer needed
- */
-static struct sockaddr_in *
-default_gw(void)
-{
-	int mib[6];
-	size_t needed;
-	char *buf, *next, *lim;
-	struct rt_msghdr *rtm;
-	struct sockaddr *sa;
-	struct sockaddr_in *sin = NULL;
-
-	mib[0] = CTL_NET;
-	mib[1] = PF_ROUTE; /* entire routing table or a subset of it */
-	mib[2] = 0; /* protocol number - always 0 */
-	mib[3] = 0; /* address family - 0 for all address families */
-	mib[4] = NET_RT_DUMP;
-	mib[5] = 0;
-
-	/* Determine the buffer side needed to get the full routing table */
-	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
-	{
-		purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump estimate\n");
-		return NULL;
-	}
-
-	if (!(buf = malloc(needed)))
-	{
-		purple_debug_warning("nat-pmp", "Failed to malloc %" G_GSIZE_FORMAT "\n", needed);
-		return NULL;
-	}
-
-	/* Read the routing table into buf */
-	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
-	{
-		free(buf);
-		purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump\n");
-		return NULL;
-	}
-
-	lim = buf + needed;
-
-	for (next = buf; next < lim; next += rtm->rtm_msglen)
-	{
-		rtm = (struct rt_msghdr *)next;
-		sa = (struct sockaddr *)(rtm + 1);
-
-		if (sa->sa_family == AF_INET)
-		{
-			struct sockaddr_in *cursin = (struct sockaddr_in*) sa;
-
-			if ((rtm->rtm_flags & RTF_GATEWAY)
-			    && cursin->sin_addr.s_addr == INADDR_ANY)
-			{
-				/* We found the default route. Now get the destination address and netmask. */
-				struct sockaddr *rti_info[RTAX_MAX];
-				struct sockaddr addr, mask;
-
-				get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-				memset(&addr, 0, sizeof(addr));
-
-				if (rtm->rtm_addrs & RTA_DST)
-					memcpy(&addr, rti_info[RTAX_DST], sizeof(addr));
-
-				memset(&mask, 0, sizeof(mask));
-
-				if (rtm->rtm_addrs & RTA_NETMASK)
-					memcpy(&mask, rti_info[RTAX_NETMASK], sizeof(mask));
-
-				if (rtm->rtm_addrs & RTA_GATEWAY &&
-					is_default_route(&addr, &mask))
-				{
-					if (rti_info[RTAX_GATEWAY]) {
-						struct sockaddr_in *rti_sin = (struct sockaddr_in *)rti_info[RTAX_GATEWAY];
-						sin = g_new0(struct sockaddr_in, 1);
-						sin->sin_family = rti_sin->sin_family;
-						sin->sin_port = rti_sin->sin_port;
-						sin->sin_addr.s_addr = rti_sin->sin_addr.s_addr;
-						memcpy(sin, rti_info[RTAX_GATEWAY], sizeof(struct sockaddr_in));
-
-						purple_debug_info("nat-pmp", "Found a default gateway\n");
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	free(buf);
-	return sin;
-}
-
-/*!
- *	purple_pmp_get_public_ip() will return the publicly facing IP address of the
- *	default NAT gateway. The function will return NULL if:
- *		- The gateway doesn't support NAT-PMP
- *		- The gateway errors in some other spectacular fashion
- */
-char *
-purple_pmp_get_public_ip(void)
-{
-	struct sockaddr_in addr, *gateway, *publicsockaddr = NULL;
-	struct timeval req_timeout;
-	socklen_t len;
-
-	PurplePmpIpRequest req;
-	PurplePmpIpResponse resp;
-	int sendfd;
-
-	if (pmp_info.status == PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER)
-		return NULL;
-
-	if ((pmp_info.status == PURPLE_PMP_STATUS_DISCOVERED) && (pmp_info.publicip != NULL))
-	{
-#ifdef PMP_DEBUG
-		purple_debug_info("nat-pmp", "Returning cached publicip %s\n",pmp_info.publicip);
-#endif
-		return pmp_info.publicip;
-	}
-
-	gateway = default_gw();
-
-	if (!gateway)
-	{
-		purple_debug_info("nat-pmp", "Cannot request public IP from a NULL gateway!\n");
-		/* If we get a NULL gateway, don't try again next time */
-		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-		return NULL;
-	}
-
-	/* Default port for NAT-PMP is 5351 */
-	if (gateway->sin_port != PMP_PORT)
-		gateway->sin_port = g_htons(PMP_PORT);
-
-	req_timeout.tv_sec = 0;
-	req_timeout.tv_usec = PMP_TIMEOUT;
-
-	sendfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-
-	/* Clean out both req and resp structures */
-	memset(&req, 0, sizeof(PurplePmpIpRequest));
-	memset(&resp, 0, sizeof(PurplePmpIpResponse));
-	req.version = 0;
-	req.opcode = 0;
-
-	/* The NAT-PMP spec says we should attempt to contact the gateway 9 times, doubling the time we wait each time.
-	 * Even starting with a timeout of 0.1 seconds, that means that we have a total waiting of 204.6 seconds.
-	 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes).
-	 *
-	 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present.
-	 */
-#ifdef PMP_DEBUG
-	purple_debug_info("nat-pmp", "Attempting to retrieve the public ip address for the NAT device at: %s\n", inet_ntoa(gateway->sin_addr));
-	purple_debug_info("nat-pmp", "\tTimeout: %ds %dus\n", req_timeout.tv_sec, req_timeout.tv_usec);
-#endif
-
-	/* TODO: Non-blocking! */
-
-	if (sendto(sendfd, &req, sizeof(req), 0, (struct sockaddr *)(gateway), sizeof(struct sockaddr)) < 0)
-	{
-		purple_debug_info("nat-pmp", "There was an error sending the NAT-PMP public IP request! (%s)\n", g_strerror(errno));
-		g_free(gateway);
-		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-		return NULL;
-	}
-
-	if (setsockopt(sendfd, SOL_SOCKET, SO_RCVTIMEO, &req_timeout, sizeof(req_timeout)) < 0)
-	{
-		purple_debug_info("nat-pmp", "There was an error setting the socket's options! (%s)\n", g_strerror(errno));
-		g_free(gateway);
-		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-		return NULL;
-	}
-
-	/* TODO: Non-blocking! */
-	len = sizeof(struct sockaddr_in);
-	if (recvfrom(sendfd, &resp, sizeof(PurplePmpIpResponse), 0, (struct sockaddr *)(&addr), &len) < 0)
-	{
-		if (errno != EAGAIN)
-		{
-			purple_debug_info("nat-pmp", "There was an error receiving the response from the NAT-PMP device! (%s)\n", g_strerror(errno));
-			g_free(gateway);
-			pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-			return NULL;
-		}
-	}
-
-	if (addr.sin_addr.s_addr == gateway->sin_addr.s_addr)
-		publicsockaddr = &addr;
-	else
-	{
-		purple_debug_info("nat-pmp", "Response was not received from our gateway! Instead from: %s\n", inet_ntoa(addr.sin_addr));
-		g_free(gateway);
-
-		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-		return NULL;
-	}
-
-	if (!publicsockaddr) {
-		g_free(gateway);
-
-		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
-		return NULL;
-	}
-
-#ifdef PMP_DEBUG
-	purple_debug_info("nat-pmp", "Response received from NAT-PMP device:\n");
-	purple_debug_info("nat-pmp", "version: %d\n", resp.version);
-	purple_debug_info("nat-pmp", "opcode: %d\n", resp.opcode);
-	purple_debug_info("nat-pmp", "resultcode: %d\n", g_ntohs(resp.resultcode));
-	purple_debug_info("nat-pmp", "epoch: %d\n", g_ntohl(resp.epoch));
-	struct in_addr in;
-	in.s_addr = resp.address;
-	purple_debug_info("nat-pmp", "address: %s\n", inet_ntoa(in));
-#endif
-
-	publicsockaddr->sin_addr.s_addr = resp.address;
-
-	g_free(gateway);
-
-	g_free(pmp_info.publicip);
-	pmp_info.publicip = g_strdup(inet_ntoa(publicsockaddr->sin_addr));
-	pmp_info.status = PURPLE_PMP_STATUS_DISCOVERED;
-
-	return inet_ntoa(publicsockaddr->sin_addr);
-}
-
-static void
-purple_pmp_network_config_changed_cb(GNetworkMonitor *monitor, gboolean available, gpointer data)
-{
-	pmp_info.status = PURPLE_PMP_STATUS_UNDISCOVERED;
-	g_free(pmp_info.publicip);
-	pmp_info.publicip = NULL;
-}
-
-void
-purple_pmp_init(void)
-{
-	g_signal_connect(g_network_monitor_get_default(),
-	                 "network-changed",
-	                 G_CALLBACK(purple_pmp_network_config_changed_cb),
-	                 NULL);
-}
-#else /* #ifdef NET_RT_DUMP */
-char *
-purple_pmp_get_public_ip(void)
-{
-	return NULL;
-}
-
-void
-purple_pmp_init(void)
-{
-
-}
-#endif /* #if !(defined(HAVE_SYS_SYCTL_H) && defined(NET_RT_DUMP)) */
diff --git a/libpurple/network.c b/libpurple/network.c
--- a/libpurple/network.c
+++ b/libpurple/network.c
@@ -42,7 +42,6 @@
 
 #include "debug.h"
 #include "account.h"
-#include "nat-pmp.h"
 #include "network.h"
 #include "prefs.h"
 #include "stun.h"
@@ -132,12 +131,6 @@
 	if (stun != NULL && stun->status == PURPLE_STUN_STATUS_DISCOVERED) {
 		return;
 	}
-
-	/* Attempt to get the IP from a NAT device using NAT-PMP */
-	ip = purple_pmp_get_public_ip();
-	if (ip != NULL) {
-		return;
-	}
 }
 
 gchar *
@@ -159,12 +152,6 @@
 		if ((stun != NULL) && (stun->status == PURPLE_STUN_STATUS_DISCOVERED)) {
 			return g_strdup(stun->publicip);
 		}
-
-		/* Attempt to get the IP from a NAT device using NAT-PMP */
-		ip = purple_pmp_get_public_ip();
-		if (ip != NULL) {
-			return g_strdup(ip);
-		}
 	}
 
 	/* Just fetch the IP of the local system */
@@ -312,8 +299,6 @@
 	purple_prefs_add_int   ("/purple/network/ports_range_start", 1024);
 	purple_prefs_add_int   ("/purple/network/ports_range_end", 2048);
 
-	purple_pmp_init();
-
 	purple_network_set_stun_server(
 		purple_prefs_get_string("/purple/network/stun_server"));
 	purple_network_set_turn_server(
diff --git a/meson.build b/meson.build
--- a/meson.build
+++ b/meson.build
@@ -486,19 +486,6 @@
 #AC_MSG_CHECKING(for me pot o' gold)
 #AC_MSG_RESULT(no)
 
-# OpenBSD 6.7 and FreeBSD 12 require including sys/types.h before sys/sysctl.h.
-# NetBSD 9.0 doesn't care.
-if host_machine.system() in ['freebsd', 'openbsd']
-	prefix = '''
-#include <sys/types.h>
-'''
-
-	conf.set('HAVE_SYS_SYSCTL_H',
-	    compiler.has_header('sys/sysctl.h', prefix : prefix))
-	conf.set('HAVE_SYS_SOCKET_H',
-	    compiler.has_header('sys/socket.h'))
-endif
-
 #######################################################################
 # Documentation
 #######################################################################
diff --git a/pidgin/prefs/pidginnetworkprefs.c b/pidgin/prefs/pidginnetworkprefs.c
--- a/pidgin/prefs/pidginnetworkprefs.c
+++ b/pidgin/prefs/pidginnetworkprefs.c
@@ -115,11 +115,7 @@
 		if ((stun != NULL) && (stun->status == PURPLE_STUN_STATUS_DISCOVERED)) {
 			ip = stun->publicip;
 		} else {
-			/* Attempt to get the IP from a NAT device using NAT-PMP */
-			ip = purple_pmp_get_public_ip();
-			if (ip == NULL) {
-				ip = "0.0.0.0";
-			}
+			ip = "0.0.0.0";
 		}
 	} else {
 		ip = _("Disabled");
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -48,7 +48,6 @@
 libpurple/media/codec.c
 libpurple/media/enum-types.c
 libpurple/mediamanager.c
-libpurple/nat-pmp.c
 libpurple/network.c
 libpurple/notify.c
 libpurple/pluginpref.c
