PUD: cfg: return default port when addr is NULL in getOlsrSockaddrPort
[olsrd.git] / lib / pud / src / configuration.c
index 4ad8ad9..1d3a3c3 100644 (file)
 
 /* Plugin includes */
 #include "pud.h"
-#include "netTools.h"
 #include "networkInterfaces.h"
+#include "netTools.h"
+#include "posFile.h"
+#include "configTools.h"
 
 /* OLSR includes */
-#include "olsr_types.h"
-#include "olsr_cfg.h"
+#include <olsr_protocol.h>
 
 /* System includes */
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
 #include <unistd.h>
 #include <nmea/util.h>
+#include <OlsrdPudWireFormat/nodeIdConversion.h>
+#include <limits.h>
 
 /*
- * Utility functions
- */
-
-/**
- Determine the address of the port in an OLSR socket address
-
- @param ipVersion
- The IP version (AF_INET or AF_INET6)
- @param addr
- A pointer to OLSR socket address
- @param port
- A pointer to the location where the pointer to the port will be stored
- */
-static void getOlsrSockaddrPortAddress(int ipVersion,
-               union olsr_sockaddr * addr, in_port_t ** port) {
-       if (ipVersion == AF_INET) {
-               *port = &addr->in4.sin_port;
-       } else {
-               *port = &addr->in6.sin6_port;
-       }
-}
-
-/**
- Get pointers to the IP address and port in an OLSR socket address
- @param ipVersion
- The IP version (AF_INET or AF_INET6)
- @param addr
- A pointer to OLSR socket address
- @param ipAddress
- A pointer to the location where the pointer to the IP address will be stored
- @param port
- A pointer to the location where the pointer to the port will be stored
- */
-static void getOlsrSockAddrAndPortAddresses(int ipVersion,
-               union olsr_sockaddr * addr, void ** ipAddress, in_port_t ** port) {
-       if (ipVersion == AF_INET) {
-               *ipAddress = (void *) &addr->in4.sin_addr;
-               *port = (void *) &addr->in4.sin_port;
-       } else {
-               *ipAddress = (void *) &addr->in6.sin6_addr;
-               *port = (void *) &addr->in6.sin6_port;
-       }
-}
-
-/**
- Read an unsigned long long number from a value string
-
- @param valueName
- the name of the value
- @param value
- the string to convert to a number
- @param valueNumber
- a pointer to the location where to store the number upon successful conversion
-
- @return
- - true on success
- - false otherwise
- */
-static bool readULL(const char * valueName, const char * value,
-               unsigned long long * valueNumber) {
-       char * endPtr = NULL;
-       unsigned long long valueNew;
-
-       errno = 0;
-       valueNew = strtoull(value, &endPtr, 10);
-
-       if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
-               /* invalid conversion */
-               pudError(true, "Configured %s (%s) could not be converted to a number",
-                               valueName, value);
-               return false;
-       }
-
-       *valueNumber = valueNew;
-
-       return true;
-}
-
-/**
- Read a double number from a value string
-
- @param valueName
- the name of the value
- @param value
- the string to convert to a number
- @param valueNumber
- a pointer to the location where to store the number upon successful conversion
-
- @return
- - true on success
- - false otherwise
+ * Note:
+ * Setters must return true when an error is detected, false otherwise
  */
-static bool readDouble(const char * valueName, const char * value,
-               double * valueNumber) {
-       char * endPtr = NULL;
-       double valueNew;
-
-       errno = 0;
-       valueNew = strtod(value, &endPtr);
-
-       if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
-               /* invalid conversion */
-               pudError(true, "Configured %s (%s) could not be converted to a number",
-                               valueName, value);
-               return false;
-       }
-
-       *valueNumber = valueNew;
-
-       return true;
-}
 
 /*
  * nodeIdType
@@ -150,33 +36,17 @@ NodeIdType getNodeIdTypeNumber(void) {
        return nodeIdType;
 }
 
-/**
- Set the node ID type.
-
- @param value
- The value of the node ID type to set (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setNodeIdType(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_NODE_ID_TYPE_NAME;
        unsigned long long nodeIdTypeNew;
 
-       assert (value != NULL);
-
        if (!readULL(valueName, value, &nodeIdTypeNew)) {
                return true;
        }
 
        if (!isValidNodeIdType(nodeIdTypeNew)) {
-               pudError(false, "Configured %s (%llu) is reserved", valueName,
+               pudError(false, "Value of parameter %s (%llu) is reserved", valueName,
                                nodeIdTypeNew);
                return true;
        }
@@ -190,21 +60,8 @@ int setNodeIdType(const char *value, void *data __attribute__ ((unused)),
  * nodeId
  */
 
-/** The maximum length of a nodeId */
-#define PUD_NODEIDMAXLENGTH 255
-
-/**
- The type that is used to store the nodeId as a binary representation
- */
-typedef union _nodeIdBinaryType {
-               unsigned long long longValue;
-               unsigned char stringValue[PUD_NODEIDMAXLENGTH + 1];
-               union olsr_ip_addr ip;
-               unsigned char mac[PUD_NODEIDTYPE_MAC_BYTES];
-} nodeIdBinaryType;
-
 /** The nodeId buffer */
-static unsigned char nodeId[PUD_NODEIDMAXLENGTH + 1];
+static unsigned char nodeId[PUD_TX_NODEID_BUFFERSIZE + 1];
 
 /** The length of the string in the nodeId buffer */
 static size_t nodeIdLength = 0;
@@ -212,15 +69,9 @@ static size_t nodeIdLength = 0;
 /** True when the nodeId is set */
 static bool nodeIdSet = false;
 
-/** The nodeId as a binary representation */
+/** The nodeId as a binary representation, with status */
 static nodeIdBinaryType nodeIdBinary;
 
-/** The length of the string in the nodeIdBinary buffer */
-static size_t nodeIdBinaryLength = 0;
-
-/** True when the nodeIdBinary is set */
-static bool nodeIdBinarySet = false;
-
 /**
  @return
  The node ID
@@ -252,29 +103,28 @@ unsigned char * getNodeIdWithLength(size_t *length) {
 }
 
 /**
- Set the node ID.
-
- @param value
- The value of the node ID to set (in string representation)
- @param data
- Unused
- @param addon
- Unused
+ Get the nodeIdBinary
 
  @return
- - true when an error is detected
- - false otherwise
+ The node ID in binary representation
  */
+nodeIdBinaryType * getNodeIdBinary(void) {
+       if (!nodeIdBinary.set) {
+               setNodeId("", NULL, (set_plugin_parameter_addon) {.pc = NULL});
+       }
+
+       return &nodeIdBinary;
+}
+
 int setNodeId(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_NODE_ID_NAME;
        size_t valueLength;
 
        assert (value != NULL);
 
        valueLength = strlen(value);
-       if (valueLength > PUD_NODEIDMAXLENGTH) {
-               pudError(false, "Configured %s is too long, maximum length is"
-                       " %u, current length is %lu", valueName, PUD_NODEIDMAXLENGTH,
+       if (valueLength > PUD_TX_NODEID_BUFFERSIZE) {
+               pudError(false, "Value of parameter %s is too long, maximum length is"
+                       " %u, current length is %lu", PUD_NODE_ID_NAME, PUD_TX_NODEID_BUFFERSIZE,
                                (unsigned long) valueLength);
                return true;
        }
@@ -298,22 +148,13 @@ int setNodeId(const char *value, void *data __attribute__ ((unused)), set_plugin
  - true when ok
  - false on failure
  */
-static bool setupNodeIdBinaryMAC(void) {
+static bool intSetupNodeIdBinaryMAC(void) {
        unsigned char * mac = getMainIpMacAddress();
        if (!mac) {
                return false;
        }
 
-       memcpy(&nodeIdBinary.mac, mac, PUD_NODEIDTYPE_MAC_BYTES);
-       nodeIdBinaryLength = PUD_NODEIDTYPE_MAC_BYTES;
-       nodeIdBinarySet = true;
-
-       if (setupNodeIdBinaryBufferForOlsrCache(mac, PUD_NODEIDTYPE_MAC_BYTES)) {
-               return true;
-       }
-
-       pudError(false, "%s value \"MAC address\" could not be setup", PUD_NODE_ID_NAME);
-       return false;
+       return setupNodeIdBinaryMAC(&nodeIdBinary, mac);
 }
 
 /**
@@ -331,28 +172,20 @@ static bool setupNodeIdBinaryMAC(void) {
  - true when ok
  - false on failure
  */
-static bool setupNodeIdBinaryLongLong(unsigned long long min,
+static bool intSetupNodeIdBinaryLongLong(unsigned long long min,
                unsigned long long max, unsigned int bytes) {
-       if (!nodeIdBinarySet) {
-               if (!readULL(PUD_NODE_ID_NAME, (char *) getNodeId(),
-                               &nodeIdBinary.longValue)) {
-                       return false;
-               }
-               nodeIdBinaryLength = bytes;
-               nodeIdBinarySet = true;
+       unsigned long long longValue = 0;
+       if (!readULL(PUD_NODE_ID_NAME, (char *) getNodeId(), &longValue)) {
+               return false;
        }
 
-       if ((nodeIdBinary.longValue < min) || (nodeIdBinary.longValue > max)) {
+       if ((longValue < min) || (longValue > max)) {
                pudError(false, "%s value %llu is out of range [%llu,%llu]",
-                               PUD_NODE_ID_NAME, nodeIdBinary.longValue, min, max);
+                               PUD_NODE_ID_NAME, longValue, min, max);
                return false;
        }
 
-       if (setupNodeIdBinaryLongForOlsrCache(nodeIdBinary.longValue, bytes)) {
-               return true;
-       }
-
-       return false;
+       return setupNodeIdBinaryLongLong(&nodeIdBinary, longValue, bytes);
 }
 
 /**
@@ -363,36 +196,22 @@ static bool setupNodeIdBinaryLongLong(unsigned long long min,
  - true when ok
  - false on failure
  */
-static bool setupNodeIdBinaryString(void) {
-       bool invalidChars;
+static bool intSetupNodeIdBinaryString(void) {
        char report[256];
        size_t nodeidlength;
        char * nodeid = (char *)getNodeIdWithLength(&nodeidlength);
 
-       invalidChars = nmea_string_has_invalid_chars(nodeid,
-                       PUD_NODE_ID_NAME, &report[0], sizeof(report));
-       if (invalidChars) {
-               pudError(false, &report[0]);
+       if (nmea_string_has_invalid_chars(nodeid, PUD_NODE_ID_NAME, &report[0], sizeof(report))) {
+               pudError(false, "%s", &report[0]);
                return false;
        }
 
-       if (nodeidlength > PUD_NODEIDMAXLENGTH) {
-               pudError(false, "%s value \"%s\" is too long", PUD_NODE_ID_NAME, &nodeid[0]);
+       if (nodeidlength > PUD_TX_NODEID_BUFFERSIZE) {
+               pudError(false, "Length of parameter %s (%s) is too great", PUD_NODE_ID_NAME, &nodeid[0]);
                return false;
        }
 
-       /* including trailing \0 */
-       memcpy(&nodeIdBinary.stringValue[0], &nodeid[0], nodeidlength + 1);
-       nodeIdBinaryLength = nodeIdLength + 1;
-       nodeIdBinarySet = true;
-
-       /* including trailing \0 */
-       if (setupNodeIdBinaryBufferForOlsrCache(&nodeid[0], nodeidlength + 1)) {
-               return true;
-       }
-
-       pudError(false, "%s value \"%s\" is too long", PUD_NODE_ID_NAME, &nodeid[0]);
-       return false;
+       return setupNodeIdBinaryString(&nodeIdBinary, nodeid, nodeidlength);
 }
 
 /**
@@ -403,7 +222,7 @@ static bool setupNodeIdBinaryString(void) {
  - true when ok
  - false on failure
  */
-static bool setupNodeIdBinaryIp(void) {
+static bool intSetupNodeIdBinaryIp(void) {
        void * src;
        size_t length;
        if (olsr_cnf->ip_version == AF_INET) {
@@ -414,21 +233,12 @@ static bool setupNodeIdBinaryIp(void) {
                length = sizeof(struct in6_addr);
        }
 
-       memcpy(&nodeIdBinary.ip, src, length);
-       nodeIdBinaryLength = length;
-       nodeIdBinarySet = true;
-
-       if (setupNodeIdBinaryBufferForOlsrCache(src, length)) {
-               return true;
-       }
-
-       pudError(false, "%s value \"OLSRd main IP address\" could not be setup", PUD_NODE_ID_NAME);
-       return false;
+       return setupNodeIdBinaryIp(&nodeIdBinary, src, length);
 }
 
 /**
  Validate whether the configured nodeId is valid w.r.t. the configured
- nodeIdType
+ nodeIdType and setup the binary value
 
  @return
  - true when ok
@@ -437,43 +247,43 @@ static bool setupNodeIdBinaryIp(void) {
 static bool setupNodeIdBinaryAndValidate(NodeIdType nodeIdTypeNumber) {
        switch (nodeIdTypeNumber) {
                case PUD_NODEIDTYPE_MAC: /* hardware address */
-                       return setupNodeIdBinaryMAC();
+                       return intSetupNodeIdBinaryMAC();
 
                case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_MSISDN_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_MSISDN_MIN,
                                PUD_NODEIDTYPE_MSISDN_MAX, PUD_NODEIDTYPE_MSISDN_BYTES);
 
                case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_TETRA_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_TETRA_MIN,
                                PUD_NODEIDTYPE_TETRA_MAX, PUD_NODEIDTYPE_TETRA_BYTES);
 
                case PUD_NODEIDTYPE_DNS: /* DNS name */
-                       return setupNodeIdBinaryString();
+                       return intSetupNodeIdBinaryString();
 
                case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_MMSI_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_MMSI_MIN,
                                PUD_NODEIDTYPE_MMSI_MAX, PUD_NODEIDTYPE_MMSI_BYTES);
 
                case PUD_NODEIDTYPE_URN: /* a URN number */
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_URN_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_URN_MIN,
                                PUD_NODEIDTYPE_URN_MAX, PUD_NODEIDTYPE_URN_BYTES);
 
                case PUD_NODEIDTYPE_192:
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_192_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_192_MIN,
                                PUD_NODEIDTYPE_192_MAX, PUD_NODEIDTYPE_192_BYTES);
 
                case PUD_NODEIDTYPE_193:
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_193_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_193_MIN,
                                PUD_NODEIDTYPE_193_MAX, PUD_NODEIDTYPE_193_BYTES);
 
                case PUD_NODEIDTYPE_194:
-                       return setupNodeIdBinaryLongLong(PUD_NODEIDTYPE_194_MIN,
+                       return intSetupNodeIdBinaryLongLong(PUD_NODEIDTYPE_194_MIN,
                                PUD_NODEIDTYPE_194_MAX, PUD_NODEIDTYPE_194_BYTES);
 
                case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
                case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
                default: /* unsupported */
-                       return setupNodeIdBinaryIp();
+                       return intSetupNodeIdBinaryIp();
        }
 
        return false;
@@ -519,41 +329,27 @@ bool isRxNonOlsrInterface(const char *ifName) {
        return false;
 }
 
-/**
- Add a receive non-OLSR interface
-
- @param value
- The name of the non-OLSR interface to add
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int addRxNonOlsrInterface(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       unsigned long valueLength;
+       size_t valueLength;
+
+       if (rxNonOlsrInterfaceCount >= PUD_RX_NON_OLSR_IF_MAX) {
+               pudError(false, "Can't configure more than %u receive interfaces",
+                               PUD_RX_NON_OLSR_IF_MAX);
+               return true;
+       }
 
        assert (value != NULL);
 
        valueLength = strlen(value);
        if (valueLength > IFNAMSIZ) {
-               pudError(false, "Configured %s (%s) is too long,"
+               pudError(false, "Value of parameter %s (%s) is too long,"
                        " maximum length is %u, current length is %lu",
                                PUD_RX_NON_OLSR_IF_NAME, value, IFNAMSIZ, valueLength);
                return true;
        }
 
        if (!isRxNonOlsrInterface(value)) {
-               if (rxNonOlsrInterfaceCount >= PUD_RX_NON_OLSR_IF_MAX) {
-                       pudError(false, "Can't configure more than %u receive interfaces",
-                                       PUD_RX_NON_OLSR_IF_MAX);
-                       return true;
-               }
-
                strcpy((char *) &rxNonOlsrInterfaceNames[rxNonOlsrInterfaceCount][0],
                                value);
                rxNonOlsrInterfaceCount++;
@@ -570,7 +366,7 @@ int addRxNonOlsrInterface(const char *value, void *data __attribute__ ((unused))
 #define PUD_RX_ALLOWED_SOURCE_IP_MAX 32
 
 /** Array with RX allowed source IP addresses */
-static struct sockaddr rxAllowedSourceIpAddresses[PUD_RX_ALLOWED_SOURCE_IP_MAX];
+static union olsr_sockaddr rxAllowedSourceIpAddresses[PUD_RX_ALLOWED_SOURCE_IP_MAX];
 
 /** The number of RX allowed source IP addresses in the array */
 static unsigned int rxAllowedSourceIpAddressesCount = 0;
@@ -587,9 +383,7 @@ static unsigned int rxAllowedSourceIpAddressesCount = 0;
  address
  - false otherwise
  */
-bool isRxAllowedSourceIpAddress(struct sockaddr * sender) {
-       void * addr;
-       unsigned int addrSize;
+bool isRxAllowedSourceIpAddress(union olsr_sockaddr * sender) {
        unsigned int i;
 
        if (rxAllowedSourceIpAddressesCount == 0) {
@@ -600,68 +394,45 @@ bool isRxAllowedSourceIpAddress(struct sockaddr * sender) {
                return false;
        }
 
-       if (sender->sa_family == AF_INET) {
-               addr = (void *) (&((struct sockaddr_in *) sender)->sin_addr);
-               addrSize = sizeof(struct in_addr);
-       } else {
-               addr = (void *) (&((struct sockaddr_in6 *) sender)->sin6_addr);
-               addrSize = sizeof(struct in6_addr);
-       }
-
        for (i = 0; i < rxAllowedSourceIpAddressesCount; i++) {
-               if ((rxAllowedSourceIpAddresses[i].sa_family == sender->sa_family)
-                               && (memcmp(&rxAllowedSourceIpAddresses[i].sa_data, addr,
-                                               addrSize) == 0)) {
-                       return true;
+               if (sender->in.sa_family != rxAllowedSourceIpAddresses[i].in.sa_family) {
+                       continue;
+               }
+
+               if (sender->in.sa_family == AF_INET) {
+                       if (memcmp(&rxAllowedSourceIpAddresses[i].in4.sin_addr, &sender->in4.sin_addr, sizeof(struct in_addr))
+                                       == 0) {
+                               return true;
+                       }
+               } else {
+                       if (memcmp(&rxAllowedSourceIpAddresses[i].in6.sin6_addr, &sender->in6.sin6_addr, sizeof(struct in6_addr))
+                                       == 0) {
+                               return true;
+                       }
                }
        }
 
        return false;
 }
 
-/**
- Set the RX allowed source IP addresses.
-
- @param value
- The RX allowed source IP address (in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int addRxAllowedSourceIpAddress(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_RX_ALLOWED_SOURCE_IP_NAME;
-       const char * valueInternal = value;
-       int conversion;
-       struct sockaddr addr;
-
-       assert (value != NULL);
-
-       memset(&addr, 0, sizeof(addr));
+       union olsr_sockaddr addr;
+       bool addrSet = false;
 
-       addr.sa_family = olsr_cnf->ip_version;
-       conversion = inet_pton(olsr_cnf->ip_version, valueInternal, &addr.sa_data);
-       if (conversion != 1) {
-               pudError((conversion == -1) ? true : false,
-                               "Configured %s (%s) is not an IP address", valueName,
-                               valueInternal);
+       if (rxAllowedSourceIpAddressesCount >= PUD_RX_ALLOWED_SOURCE_IP_MAX) {
+               pudError(false, "Can't configure more than %u allowed source IP"
+                       " addresses", PUD_RX_ALLOWED_SOURCE_IP_MAX);
                return true;
        }
 
-       if ((rxAllowedSourceIpAddressesCount == 0) || !isRxAllowedSourceIpAddress(&addr)) {
-               if (rxAllowedSourceIpAddressesCount >= PUD_RX_ALLOWED_SOURCE_IP_MAX) {
-                       pudError(false, "Can't configure more than %u allowed source IP"
-                               " addresses", PUD_RX_ALLOWED_SOURCE_IP_MAX);
-                       return true;
-               }
+       if (!readIPAddress(valueName, value, 0, &addr, &addrSet)) {
+               return true;
+       }
 
-               memcpy(&rxAllowedSourceIpAddresses[rxAllowedSourceIpAddressesCount],
-                               &addr, sizeof(addr));
+       if (!isRxAllowedSourceIpAddress(&addr)) {
+               rxAllowedSourceIpAddresses[rxAllowedSourceIpAddressesCount] = addr;
                rxAllowedSourceIpAddressesCount++;
        }
 
@@ -669,7 +440,7 @@ int addRxAllowedSourceIpAddress(const char *value, void *data __attribute__ ((un
 }
 
 /*
- * rxMcAddr
+ * rxMcAddr + rxMcPort
  */
 
 /** The rx multicast address */
@@ -685,118 +456,96 @@ static bool rxMcAddrSet = false;
  */
 union olsr_sockaddr * getRxMcAddr(void) {
        if (!rxMcAddrSet) {
-               setRxMcAddr(NULL, NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
+               setRxMcAddr((olsr_cnf->ip_version == AF_INET) ? PUD_RX_MC_ADDR_4_DEFAULT : PUD_RX_MC_ADDR_6_DEFAULT,
+                               NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
        }
        return &rxMcAddr;
 }
 
-/**
- Set the receive multicast address. Sets the address to its default value when
- the value is NULL. Also sets the port to its default value when the address
- was not yet set.
-
- @param value
- The receive multicast address (in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setRxMcAddr(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_RX_MC_ADDR_NAME;
-       void * ipAddress;
-       in_port_t * port;
-       const char * valueInternal = value;
-       int conversion;
 
-       getOlsrSockAddrAndPortAddresses(olsr_cnf->ip_version, &rxMcAddr, &ipAddress,
-                       &port);
-       if (olsr_cnf->ip_version == AF_INET) {
-               rxMcAddr.in4.sin_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_RX_MC_ADDR_4_DEFAULT;
-               }
-       } else {
-               rxMcAddr.in6.sin6_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_RX_MC_ADDR_6_DEFAULT;
-               }
+       if (!readIPAddress(valueName, value, PUD_RX_MC_PORT_DEFAULT, &rxMcAddr, &rxMcAddrSet)) {
+                       return true;
        }
 
-       if (!rxMcAddrSet) {
-               *port = htons(PUD_RX_MC_PORT_DEFAULT);
+       if (!isMulticast(&rxMcAddr)) {
+               pudError(false, "Value of parameter %s (%s) is not a multicast address",
+                               valueName, value);
+               return true;
        }
 
-       conversion = inet_pton(olsr_cnf->ip_version, valueInternal, ipAddress);
-       if (conversion != 1) {
-               pudError((conversion == -1) ? true : false,
-                               "Configured %s (%s) is not an IP address", valueName,
-                               valueInternal);
+       return false;
+}
+
+/**
+ @return
+ The receive multicast port (in network byte order)
+ */
+unsigned short getRxMcPort(void) {
+       return getOlsrSockaddrPort(getRxMcAddr(), PUD_RX_MC_PORT_DEFAULT);
+}
+
+int setRxMcPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       static const char * valueName = PUD_RX_MC_PORT_NAME;
+       unsigned short rxMcPortNew;
+
+       if (!readUS(valueName, value, &rxMcPortNew)) {
                return true;
        }
 
-       if (!isMulticast(olsr_cnf->ip_version, &rxMcAddr)) {
-               pudError(false, "Configured %s (%s) is not a multicast address",
-                               valueName, valueInternal);
+       if (rxMcPortNew < 1) {
+               pudError(false, "Value of parameter %s (%u) is outside of valid range 1-65535", valueName, rxMcPortNew);
                return true;
        }
 
-       rxMcAddrSet = true;
+       setOlsrSockaddrPort(getRxMcAddr(), htons((in_port_t) rxMcPortNew));
+
        return false;
 }
 
 /*
- * rxMcPort
+ * positionFile
  */
 
+/** The positionFile buffer */
+static char positionFile[PATH_MAX + 1];
+
+/** True when the positionFile is set */
+static bool positionFileSet = false;
+
 /**
  @return
- The receive multicast port (in network byte order)
+ The positionFile (NULL when not set)
  */
-unsigned short getRxMcPort(void) {
-       in_port_t * port;
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, getRxMcAddr(), &port);
-       return *port;
-}
-
-/**
- Set the receive multicast port
+char * getPositionFile(void) {
+       if (!positionFileSet) {
+               return NULL;
+       }
 
- @param value
- The receive multicast port (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
+       return &positionFile[0];
+}
 
- @return
- - true when an error is detected
- - false otherwise
- */
-int setRxMcPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_RX_MC_PORT_NAME;
-       unsigned long long rxMcPortNew;
-       in_port_t * port;
-       union olsr_sockaddr * addr = getRxMcAddr();
+int setPositionFile(const char *value, void *data __attribute__ ((unused)),
+               set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       size_t valueLength;
 
-       assert (value != NULL);
+       assert(value != NULL);
 
-       if (!readULL(valueName, value, &rxMcPortNew)) {
+       if (!startPositionFile()) {
+               stopPositionFile();
                return true;
        }
 
-       if ((rxMcPortNew < 1) || (rxMcPortNew > 65535)) {
-               pudError(false, "Configured %s (%llu) is outside of"
-                       " valid range 1-65535", valueName, rxMcPortNew);
+       valueLength = strlen(value);
+       if (valueLength > PATH_MAX) {
+               pudError(false, "Value of parameter %s is too long, maximum length is"
+                               " %u, current length is %lu", PUD_POSFILE_NAME, PATH_MAX, (unsigned long) valueLength);
                return true;
        }
 
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, addr, &port);
-       *port = htons((uint16_t) rxMcPortNew);
+       strcpy((char *) &positionFile[0], value);
+       positionFileSet = true;
 
        return false;
 }
@@ -805,7 +554,7 @@ int setRxMcPort(const char *value, void *data __attribute__ ((unused)), set_plug
  * txNonOlsrIf
  */
 
-/** The maximum number of rx non-olsr interfaces */
+/** The maximum number of tx non-olsr interfaces */
 #define PUD_TX_NON_OLSR_IF_MAX 32
 
 /** Array with tx non-olsr interface names */
@@ -832,8 +581,7 @@ bool isTxNonOlsrInterface(const char *ifName) {
        assert (ifName != NULL);
 
        for (i = 0; i < txNonOlsrInterfaceCount; i++) {
-               if (strncmp((char *) &txNonOlsrInterfaceNames[i][0], ifName, IFNAMSIZ
-                               + 1) == 0) {
+               if (strncmp((char *) &txNonOlsrInterfaceNames[i][0], ifName, IFNAMSIZ + 1) == 0) {
                        return true;
                }
        }
@@ -841,43 +589,26 @@ bool isTxNonOlsrInterface(const char *ifName) {
        return false;
 }
 
-/**
- Add a transmit non-OLSR interface
-
- @param value
- The name of the non-OLSR interface to add
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int addTxNonOlsrInterface(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       unsigned long valueLength;
+       size_t valueLength;
 
        assert (value != NULL);
 
+       if (txNonOlsrInterfaceCount >= PUD_TX_NON_OLSR_IF_MAX) {
+               pudError(false, "Can not configure more than %u transmit interfaces", PUD_TX_NON_OLSR_IF_MAX);
+               return true;
+       }
+
        valueLength = strlen(value);
        if (valueLength > IFNAMSIZ) {
-               pudError(false, "Configured %s (%s) is too long,"
-                       " maximum length is %u, current length is %lu",
+               pudError(false, "Value of parameter %s (%s) is too long, maximum length is %u, current length is %lu",
                                PUD_TX_NON_OLSR_IF_NAME, value, IFNAMSIZ, valueLength);
                return true;
        }
 
        if (!isTxNonOlsrInterface(value)) {
-               if (txNonOlsrInterfaceCount >= PUD_TX_NON_OLSR_IF_MAX) {
-                       pudError(false, "Can not configure more than %u transmit"
-                               " interfaces", PUD_TX_NON_OLSR_IF_MAX);
-                       return true;
-               }
-
-               strcpy((char *) &txNonOlsrInterfaceNames[txNonOlsrInterfaceCount][0],
-                               value);
+               strcpy((char *) &txNonOlsrInterfaceNames[txNonOlsrInterfaceCount][0], value);
                txNonOlsrInterfaceCount++;
        }
 
@@ -885,7 +616,7 @@ int addTxNonOlsrInterface(const char *value, void *data __attribute__ ((unused))
 }
 
 /*
- * txMcAddr
+ * txMcAddr + txMcPort
  */
 
 /** The tx multicast address */
@@ -901,450 +632,243 @@ static bool txMcAddrSet = false;
  */
 union olsr_sockaddr * getTxMcAddr(void) {
        if (!txMcAddrSet) {
-               setTxMcAddr(NULL, NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
+               setTxMcAddr((olsr_cnf->ip_version == AF_INET) ? PUD_TX_MC_ADDR_4_DEFAULT : PUD_TX_MC_ADDR_6_DEFAULT,
+                               NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
        }
        return &txMcAddr;
 }
 
-/**
- Set the transmit multicast address. Sets the address to its default value when
- the value is NULL. Also sets the port to its default value when the address
- was not yet set.
-
- @param value
- The transmit multicast address (in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setTxMcAddr(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_TX_MC_ADDR_NAME;
-       void * ipAddress;
-       in_port_t * port;
-       const char * valueInternal = value;
-       int conversion;
-
-       getOlsrSockAddrAndPortAddresses(olsr_cnf->ip_version, &txMcAddr, &ipAddress,
-                       &port);
-       if (olsr_cnf->ip_version == AF_INET) {
-               txMcAddr.in4.sin_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_TX_MC_ADDR_4_DEFAULT;
-               }
-       } else {
-               txMcAddr.in6.sin6_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_TX_MC_ADDR_6_DEFAULT;
-               }
-       }
-
-       if (!txMcAddrSet) {
-               *port = htons(PUD_TX_MC_PORT_DEFAULT);
-       }
 
-       conversion = inet_pton(olsr_cnf->ip_version, valueInternal, ipAddress);
-       if (conversion != 1) {
-               pudError((conversion == -1) ? true : false,
-                               "Configured %s (%s) is not an IP address", valueName,
-                               valueInternal);
-               return true;
+       if (!readIPAddress(valueName, value, PUD_TX_MC_PORT_DEFAULT, &txMcAddr, &txMcAddrSet)) {
+                       return true;
        }
 
-       if (!isMulticast(olsr_cnf->ip_version, &txMcAddr)) {
-               pudError(false, "Configured %s (%s) is not a multicast address",
-                               valueName, valueInternal);
+       if (!isMulticast(&txMcAddr)) {
+               pudError(false, "Value of parameter %s (%s) is not a multicast address",
+                               valueName, value);
                return true;
        }
 
-       txMcAddrSet = true;
        return false;
 }
 
-/*
- * txMcPort
- */
-
 /**
  @return
  The transmit multicast port (in network byte order)
  */
 unsigned short getTxMcPort(void) {
-       in_port_t * port;
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, getTxMcAddr(), &port);
-       return *port;
+       return getOlsrSockaddrPort(getTxMcAddr(), PUD_TX_MC_PORT_DEFAULT);
 }
 
-/**
- Set the transmit multicast port
-
- @param value
- The transmit multicast port (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setTxMcPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_TX_MC_PORT_NAME;
-       unsigned long long txMcPortNew;
-       in_port_t * port;
-       union olsr_sockaddr * addr = getTxMcAddr();
+       unsigned short txMcPortNew;
 
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &txMcPortNew)) {
+       if (!readUS(valueName, value, &txMcPortNew)) {
                return true;
        }
 
-       if ((txMcPortNew < 1) || (txMcPortNew > 65535)) {
-               pudError(false, "Configured %s (%llu) is outside of"
-                       " valid range 1-65535", valueName, txMcPortNew);
+       if (txMcPortNew < 1) {
+               pudError(false, "Value of parameter %s (%u) is outside of valid range 1-65535", valueName, txMcPortNew);
                return true;
        }
 
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, addr, &port);
-       *port = htons((uint16_t) txMcPortNew);
+       setOlsrSockaddrPort(getTxMcAddr(), htons((in_port_t) txMcPortNew));
 
        return false;
 }
 
 /*
- * uplinkAddr
+ * txTtl
  */
 
-/** The uplink address */
-static union olsr_sockaddr uplinkAddr;
-
-/** True when the uplink address is set */
-static bool uplinkAddrSet = false;
-
-/** True when the uplink address is set */
-static bool uplinkPortSet = false;
-
-/**
- @return
- - true when the uplink address is set
- - false otherwise
- */
-bool isUplinkAddrSet(void) {
-       return uplinkAddrSet;
-}
+/** The tx TTL */
+static unsigned char txTtl = PUD_TX_TTL_DEFAULT;
 
 /**
  @return
- The uplink address (in network byte order). Sets both the address
- and the port to their default values when the address was not yet set.
+ The transmit multicast IP packet time-to-live
  */
-union olsr_sockaddr * getUplinkAddr(void) {
-       if (!uplinkAddrSet) {
-               setUplinkAddr(NULL, NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
-       }
-       return &uplinkAddr;
+unsigned char getTxTtl(void) {
+       return txTtl;
 }
 
-/**
- Set the uplink address. Sets the address to its default value when
- the value is NULL. Also sets the port to its default value when the address
- was not yet set.
-
- @param value
- The uplink address (in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
-int setUplinkAddr(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_UPLINK_ADDR_NAME;
-       void * ipAddress;
-       in_port_t * port;
-       const char * valueInternal = value;
-       int conversion;
-       bool defaultValue = false;
-
-       getOlsrSockAddrAndPortAddresses(olsr_cnf->ip_version, &uplinkAddr,
-                       &ipAddress, &port);
-       if (olsr_cnf->ip_version == AF_INET) {
-               uplinkAddr.in4.sin_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_UPLINK_ADDR_4_DEFAULT;
-                       defaultValue = true;
-               }
-       } else {
-               uplinkAddr.in6.sin6_family = olsr_cnf->ip_version;
-               if (valueInternal == NULL) {
-                       valueInternal = PUD_UPLINK_ADDR_6_DEFAULT;
-                       defaultValue = true;
-               }
-       }
-
-       if (!uplinkPortSet) {
-               *port = htons(PUD_UPLINK_PORT_DEFAULT);
-               uplinkPortSet = true;
-       }
+int setTxTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       static const char * valueName = PUD_TX_TTL_NAME;
 
-       conversion = inet_pton(olsr_cnf->ip_version, valueInternal, ipAddress);
-       if (conversion != 1) {
-               pudError((conversion == -1) ? true : false,
-                               "Configured %s (%s) is not an IP address", valueName,
-                               valueInternal);
+       if (!readUC(valueName, value, &txTtl)) {
                return true;
        }
 
-       if (!defaultValue) {
-               uplinkAddrSet = true;
+       if ((txTtl < 1) /* || (txTtl > MAX_TTL) */) {
+               pudError(false, "Value of parameter %s (%u) is outside of"
+                       " valid range 1-%u", valueName, txTtl, MAX_TTL);
+               return true;
        }
 
        return false;
 }
 
 /*
- * uplinkPort
+ * txNmeaMessagePrefix
  */
 
-/**
- @return
- The uplink port (in network byte order)
- */
-unsigned short getUplinkPort(void) {
-       in_port_t * port;
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, getUplinkAddr(), &port);
-       return *port;
-}
+/** The exact length of the tx NMEA message prefix */
+#define PUD_TXNMEAMESSAGEPREFIXLENGTH 4
 
-/**
- Set the uplink port
+/** The tx NMEA message prefix buffer */
+static unsigned char txNmeaMessagePrefix[PUD_TXNMEAMESSAGEPREFIXLENGTH + 1];
 
- @param value
- The uplink port (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
+/** True when the tx NMEA message prefix is set */
+static bool txNmeaMessagePrefixSet = false;
 
+/**
  @return
- - true when an error is detected
- - false otherwise
+ The transmit multicast NMEA message prefix
  */
-int setUplinkPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_UPLINK_PORT_NAME;
-       unsigned long long uplinkPortNew;
-       in_port_t * port;
-       union olsr_sockaddr * addr = getUplinkAddr();
+unsigned char * getTxNmeaMessagePrefix(void) {
+       if (!txNmeaMessagePrefixSet) {
+               setTxNmeaMessagePrefix(PUD_TX_NMEAMESSAGEPREFIX_DEFAULT, NULL,
+                               (set_plugin_parameter_addon) {.pc = NULL});
+       }
+       return &txNmeaMessagePrefix[0];
+}
+
+int setTxNmeaMessagePrefix(const char *value, void *data __attribute__ ((unused)),
+               set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       static const char * valueName = PUD_TX_NMEAMESSAGEPREFIX_NAME;
+       size_t valueLength;
+       char report[256];
 
        assert (value != NULL);
 
-       if (!readULL(valueName, value, &uplinkPortNew)) {
+       valueLength = strlen(value);
+       if (valueLength != PUD_TXNMEAMESSAGEPREFIXLENGTH) {
+               pudError(false, "Length of parameter %s (%s) must be exactly %u characters",
+                               valueName, value, PUD_TXNMEAMESSAGEPREFIXLENGTH);
                return true;
        }
 
-       if ((uplinkPortNew < 1) || (uplinkPortNew > 65535)) {
-               pudError(false, "Configured %s (%llu) is outside of"
-                       " valid range 1-65535", valueName, uplinkPortNew);
+       if (nmea_string_has_invalid_chars(value, valueName, &report[0], sizeof(report))) {
+               pudError(false, "%s", &report[0]);
                return true;
        }
 
-       getOlsrSockaddrPortAddress(olsr_cnf->ip_version, addr, &port);
-       *port = htons((uint16_t) uplinkPortNew);
-       uplinkPortSet = true;
+       if ((strchr(value, ' ') != NULL) || (strchr(value, '\t') != NULL)) {
+               pudError(false, "Value of parameter %s (%s) can not contain whitespace",
+                               valueName, value);
+               return true;
+       }
 
+       strcpy((char *) &txNmeaMessagePrefix[0], value);
+       txNmeaMessagePrefixSet = true;
        return false;
 }
 
-
 /*
- * downlinkPort
+ * uplinkAddr + uplinkPort
  */
 
-/** the downlink port */
-unsigned short downlinkPort = 0;
+/** The uplink address */
+static union olsr_sockaddr uplinkAddr;
 
-/** true when the downlinkPort is set */
-bool downlinkPortSet = false;
+/** True when the uplink address is set */
+static bool uplinkAddrSet = false;
 
 /**
  @return
- The downlink port (in network byte order)
+ - true when the uplink address is set
+ - false otherwise
  */
-unsigned short getDownlinkPort(void) {
-       if (!downlinkPortSet) {
-               downlinkPort = htons(PUD_DOWNLINK_PORT_DEFAULT);
-               downlinkPortSet = true;
-       }
-
-       return downlinkPort;
+bool isUplinkAddrSet(void) {
+       return uplinkAddrSet;
 }
 
 /**
- Set the downlink port
-
- @param value
- The downlink port (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
-
  @return
- - true when an error is detected
- - false otherwise
+ The uplink address (in network byte order). Sets both the address
+ and the port to their default values when the address was not yet set.
  */
-int setDownlinkPort(const char *value, void *data __attribute__ ((unused)),
-               set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_DOWNLINK_PORT_NAME;
-       unsigned long long downlinkPortNew;
-
-       assert(value != NULL);
-
-       if (!readULL(valueName, value, &downlinkPortNew)) {
-               return true;
-       }
-
-       if ((downlinkPortNew < 1) || (downlinkPortNew > 65535)) {
-               pudError(false, "Configured %s (%llu) is outside of"
-                               " valid range 1-65535", valueName, downlinkPortNew);
-               return true;
+union olsr_sockaddr * getUplinkAddr(void) {
+       if (!uplinkAddrSet) {
+               setUplinkAddr((olsr_cnf->ip_version == AF_INET) ? PUD_UPLINK_ADDR_4_DEFAULT : PUD_UPLINK_ADDR_6_DEFAULT,
+                               NULL, ((set_plugin_parameter_addon) {.pc = NULL}));
        }
-
-       downlinkPort = htons(downlinkPortNew);
-       downlinkPortSet = true;
-
-       return false;
+       return &uplinkAddr;
 }
 
-/*
- * txTtl
- */
-
-/** The tx TTL */
-static unsigned char txTtl = PUD_TX_TTL_DEFAULT;
-
-/**
- @return
- The transmit multicast IP packet time-to-live
- */
-unsigned char getTxTtl(void) {
-       return txTtl;
+int setUplinkAddr(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       return !readIPAddress(PUD_UPLINK_ADDR_NAME, value, PUD_UPLINK_PORT_DEFAULT, &uplinkAddr, &uplinkAddrSet);
 }
 
 /**
- Set the transmit multicast IP packet time-to-live
-
- @param value
- The transmit multicast IP packet time-to-live (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
-
  @return
- - true when an error is detected
- - false otherwise
+ The uplink port (in network byte order)
  */
-int setTxTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_TX_TTL_NAME;
-       unsigned long long txTtlNew;
+unsigned short getUplinkPort(void) {
+       return getOlsrSockaddrPort(getUplinkAddr(), PUD_UPLINK_PORT_DEFAULT);
+}
 
-       assert (value != NULL);
+int setUplinkPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       static const char * valueName = PUD_UPLINK_PORT_NAME;
+       unsigned short uplinkPortNew;
 
-       if (!readULL(valueName, value, &txTtlNew)) {
+       if (!readUS(valueName, value, &uplinkPortNew)) {
                return true;
        }
 
-       if ((txTtlNew < 1) || (txTtlNew > MAX_TTL)) {
-               pudError(false, "Configured %s (%llu) is outside of"
-                       " valid range 1-%u", valueName, txTtlNew, MAX_TTL);
+       if (uplinkPortNew < 1) {
+               pudError(false, "Value of parameter %s (%u) is outside of valid range 1-65535", valueName, uplinkPortNew);
                return true;
        }
 
-       txTtl = txTtlNew;
+       setOlsrSockaddrPort(getUplinkAddr(), htons((in_port_t) uplinkPortNew));
 
        return false;
 }
 
 /*
- * txNmeaMessagePrefix
+ * downlinkPort
  */
 
-/** The exact length of the tx NMEA message prefix */
-#define PUD_TXNMEAMESSAGEPREFIXLENGTH 4
-
-/** The tx NMEA message prefix buffer */
-static unsigned char txNmeaMessagePrefix[PUD_TXNMEAMESSAGEPREFIXLENGTH + 1];
+/** the downlink port */
+unsigned short downlinkPort = 0;
 
-/** True when the tx NMEA message prefix is set */
-static bool txNmeaMessagePrefixSet = false;
+/** true when the downlinkPort is set */
+bool downlinkPortSet = false;
 
 /**
  @return
- The transmit multicast NMEA message prefix
+ The downlink port (in network byte order)
  */
-unsigned char * getTxNmeaMessagePrefix(void) {
-       if (!txNmeaMessagePrefixSet) {
-               setTxNmeaMessagePrefix(PUD_TX_NMEAMESSAGEPREFIX_DEFAULT, NULL,
-                               (set_plugin_parameter_addon) {.pc = NULL});
+unsigned short getDownlinkPort(void) {
+       if (!downlinkPortSet) {
+               downlinkPort = htons(PUD_DOWNLINK_PORT_DEFAULT);
+               downlinkPortSet = true;
        }
-       return &txNmeaMessagePrefix[0];
-}
-
-/**
- Set the transmit multicast NMEA message prefix
 
- @param value
- The transmit multicast NMEA message prefix (in string representation)
- @param data
- Unused
- @param addon
- Unused
+       return downlinkPort;
+}
 
- @return
- - true when an error is detected
- - false otherwise
- */
-int setTxNmeaMessagePrefix(const char *value, void *data __attribute__ ((unused)),
+int setDownlinkPort(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_TX_NMEAMESSAGEPREFIX_NAME;
-       size_t valueLength;
-       bool invalidChars;
-       char report[256];
-
-       assert (value != NULL);
+       static const char * valueName = PUD_DOWNLINK_PORT_NAME;
+       unsigned short downlinkPortNew;
 
-       valueLength = strlen(value);
-       if (valueLength != PUD_TXNMEAMESSAGEPREFIXLENGTH) {
-               pudError(false, "Configured %s (%s) must be %u exactly characters",
-                               valueName, value, PUD_TXNMEAMESSAGEPREFIXLENGTH);
+       if (!readUS(valueName, value, &downlinkPortNew)) {
                return true;
        }
 
-       invalidChars = nmea_string_has_invalid_chars(value, valueName, &report[0],
-                       sizeof(report));
-       if (invalidChars) {
-               pudError(false, &report[0]);
+       if (downlinkPortNew < 1) {
+               pudError(false, "Value of parameter %s (%u) is outside of valid range 1-65535", valueName, downlinkPortNew);
                return true;
        }
 
-       if ((strchr(value, ' ') != NULL) || (strchr(value, '\t') != NULL)) {
-               pudError(false, "Configured %s (%s) can not contain whitespace",
-                               valueName, value);
-               return true;
-       }
+       downlinkPort = htons(downlinkPortNew);
+       downlinkPortSet = true;
 
-       strcpy((char *) &txNmeaMessagePrefix[0], value);
-       txNmeaMessagePrefixSet = true;
        return false;
 }
 
@@ -1363,38 +887,19 @@ unsigned char getOlsrTtl(void) {
        return olsrTtl;
 }
 
-/**
- Set the OLSR multicast IP packet time-to-live
-
- @param value
- The OLSR multicast IP packet time-to-live (a number in string representation)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setOlsrTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_OLSR_TTL_NAME;
-       unsigned long long olsrTtlNew;
 
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &olsrTtlNew)) {
+       if (!readUC(valueName, value, &olsrTtl)) {
                return true;
        }
 
-       if ((olsrTtlNew < 1) || (olsrTtlNew > MAX_TTL)) {
-               pudError(false, "Configured %s (%llu) is outside of valid range 1-%u",
-                               valueName, olsrTtlNew, MAX_TTL);
+       if ((olsrTtl < 1) /* || (olsrTtl > MAX_TTL) */) {
+               pudError(false, "Value of parameter %s (%u) is outside of valid range 1-%u",
+                               valueName, olsrTtl, MAX_TTL);
                return true;
        }
 
-       olsrTtl = olsrTtlNew;
-
        return false;
 }
 
@@ -1413,38 +918,19 @@ unsigned long long getUpdateIntervalStationary(void) {
        return updateIntervalStationary;
 }
 
-/**
- Set stationary interval update plugin parameter
-
- @param value
- The stationary interval update plugin parameter (in seconds)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUpdateIntervalStationary(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_UPDATE_INTERVAL_STATIONARY_NAME;
-       unsigned long long updateIntervalStationaryNew;
-
-       assert (value != NULL);
 
-       if (!readULL(valueName, value, &updateIntervalStationaryNew)) {
+       if (!readULL(valueName, value, &updateIntervalStationary)) {
                return true;
        }
 
-       if (updateIntervalStationaryNew < 1) {
-               pudError(false, "Configured %s must be at least 1", valueName);
+       if (updateIntervalStationary < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
                return true;
        }
 
-       updateIntervalStationary = updateIntervalStationaryNew;
-
        return false;
 }
 
@@ -1463,38 +949,19 @@ unsigned long long getUpdateIntervalMoving(void) {
        return updateIntervalMoving;
 }
 
-/**
- Set moving interval update plugin parameter
-
- @param value
- The moving interval update plugin parameter (in seconds)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUpdateIntervalMoving(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_UPDATE_INTERVAL_MOVING_NAME;
-       unsigned long long updateIntervalMovingNew;
-
-       assert (value != NULL);
 
-       if (!readULL(valueName, value, &updateIntervalMovingNew)) {
+       if (!readULL(valueName, value, &updateIntervalMoving)) {
                return true;
        }
 
-       if (updateIntervalMovingNew < 1) {
-               pudError(false, "Configured %s must be at least 1", valueName);
+       if (updateIntervalMoving < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
                return true;
        }
 
-       updateIntervalMoving = updateIntervalMovingNew;
-
        return false;
 }
 
@@ -1513,38 +980,19 @@ unsigned long long getUplinkUpdateIntervalStationary(void) {
        return uplinkUpdateIntervalStationary;
 }
 
-/**
- Set uplink stationary interval update plugin parameter
-
- @param value
- The uplink stationary interval update plugin parameter (in seconds)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUplinkUpdateIntervalStationary(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_UPLINK_UPDATE_INTERVAL_STATIONARY_NAME;
-       unsigned long long uplinkUpdateIntervalStationaryNew;
-
-       assert (value != NULL);
 
-       if (!readULL(valueName, value, &uplinkUpdateIntervalStationaryNew)) {
+       if (!readULL(valueName, value, &uplinkUpdateIntervalStationary)) {
                return true;
        }
 
-       if (uplinkUpdateIntervalStationaryNew < 1) {
-               pudError(false, "Configured %s must be at least 1", valueName);
+       if (uplinkUpdateIntervalStationary < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
                return true;
        }
 
-       uplinkUpdateIntervalStationary = uplinkUpdateIntervalStationaryNew;
-
        return false;
 }
 
@@ -1563,37 +1011,49 @@ unsigned long long getUplinkUpdateIntervalMoving(void) {
        return uplinkUpdateIntervalMoving;
 }
 
-/**
- Set uplink moving interval update plugin parameter
-
- @param value
- The uplink moving interval update plugin parameter (in seconds)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUplinkUpdateIntervalMoving(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_UPLINK_UPDATE_INTERVAL_MOVING_NAME;
-       unsigned long long uplinkUpdateIntervalMovingNew;
 
-       assert (value != NULL);
+       if (!readULL(valueName, value, &uplinkUpdateIntervalMoving)) {
+               return true;
+       }
 
-       if (!readULL(valueName, value, &uplinkUpdateIntervalMovingNew)) {
+       if (uplinkUpdateIntervalMoving < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
                return true;
        }
 
-       if (uplinkUpdateIntervalMovingNew < 1) {
-               pudError(false, "Configured %s must be at least 1", valueName);
+       return false;
+}
+
+/*
+ * gatewayDeterminationInterval
+ */
+
+/** The gateway determination interval plugin parameter (in seconds) */
+static unsigned long long gatewayDeterminationInterval = PUD_GATEWAY_DETERMINATION_INTERVAL_DEFAULT;
+
+/**
+ @return
+ The gateway determination interval plugin parameter (in seconds)
+ */
+unsigned long long getGatewayDeterminationInterval(void) {
+       return gatewayDeterminationInterval;
+}
+
+int setGatewayDeterminationInterval(const char *value, void *data __attribute__ ((unused)),
+               set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       static const char * valueName = PUD_GATEWAY_DETERMINATION_INTERVAL_NAME;
+
+       if (!readULL(valueName, value, &gatewayDeterminationInterval)) {
                return true;
        }
 
-       uplinkUpdateIntervalMoving = uplinkUpdateIntervalMovingNew;
+       if (gatewayDeterminationInterval < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
+               return true;
+       }
 
        return false;
 }
@@ -1613,34 +1073,9 @@ unsigned long long getMovingSpeedThreshold(void) {
        return movingSpeedThreshold;
 }
 
-/**
- Set moving speed threshold plugin parameter
-
- @param value
- The moving speed threshold plugin parameter (in kph)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setMovingSpeedThreshold(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_MOVING_SPEED_THRESHOLD_NAME;
-       unsigned long long movingSpeedThresholdNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &movingSpeedThresholdNew)) {
-               return true;
-       }
-
-       movingSpeedThreshold = movingSpeedThresholdNew;
-
-       return false;
+       return !readULL(PUD_MOVING_SPEED_THRESHOLD_NAME, value, &movingSpeedThreshold);
 }
 
 /*
@@ -1658,41 +1093,16 @@ unsigned long long getMovingDistanceThreshold(void) {
        return movingDistanceThreshold;
 }
 
-/**
- Set moving distance threshold plugin parameter
-
- @param value
- The moving distance threshold plugin parameter (in meter)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setMovingDistanceThreshold(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_MOVING_DISTANCE_THRESHOLD_NAME;
-       unsigned long long movingDistanceThresholdNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &movingDistanceThresholdNew)) {
-               return true;
-       }
-
-       movingDistanceThreshold = movingDistanceThresholdNew;
-
-       return false;
+       return !readULL(PUD_MOVING_DISTANCE_THRESHOLD_NAME, value, &movingDistanceThreshold);
 }
 
 /*
  * dopMultiplier
  */
 
-/* The DOP multiplier plugin parameter */
+/** The DOP multiplier plugin parameter */
 static double dopMultiplier = PUD_DOP_MULTIPLIER_DEFAULT;
 
 /**
@@ -1703,34 +1113,9 @@ double getDopMultiplier(void) {
        return dopMultiplier;
 }
 
-/**
- Set DOP multiplier plugin parameter
-
- @param value
- The DOP multiplier plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setDopMultiplier(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_DOP_MULTIPLIER_NAME;
-       double dopMultiplierNew;
-
-       assert (value != NULL);
-
-       if (!readDouble(valueName, value, &dopMultiplierNew)) {
-               return true;
-       }
-
-       dopMultiplier = dopMultiplierNew;
-
-       return false;
+       return !readDouble(PUD_DOP_MULTIPLIER_NAME, value, &dopMultiplier);
 }
 
 /*
@@ -1748,34 +1133,9 @@ unsigned long long getDefaultHdop(void) {
        return defaultHdop;
 }
 
-/**
- Set default HDOP plugin parameter
-
- @param value
- The default HDOP plugin parameter (in meters)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setDefaultHdop(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_MOVING_DISTANCE_THRESHOLD_NAME;
-       unsigned long long defaultHdopNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &defaultHdopNew)) {
-               return true;
-       }
-
-       defaultHdop = defaultHdopNew;
-
-       return false;
+       return !readULL(PUD_DEFAULT_HDOP_NAME, value, &defaultHdop);
 }
 
 /*
@@ -1793,34 +1153,9 @@ unsigned long long getDefaultVdop(void) {
        return defaultVdop;
 }
 
-/**
- Set default VDOP plugin parameter
-
- @param value
- The default VDOP plugin parameter (in meters)
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setDefaultVdop(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_MOVING_DISTANCE_THRESHOLD_NAME;
-       unsigned long long defaultVdopNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &defaultVdopNew)) {
-               return true;
-       }
-
-       defaultVdop = defaultVdopNew;
-
-       return false;
+       return !readULL(PUD_DEFAULT_VDOP_NAME, value, &defaultVdop);
 }
 
 /*
@@ -1838,38 +1173,19 @@ unsigned long long getAverageDepth(void) {
        return averageDepth;
 }
 
-/**
- Set average depth plugin parameter
-
- @param value
- The average depth plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setAverageDepth(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
        static const char * valueName = PUD_AVERAGE_DEPTH_NAME;
-       unsigned long long averageDepthNew;
-
-       assert (value != NULL);
 
-       if (!readULL(valueName, value, &averageDepthNew)) {
+       if (!readULL(valueName, value, &averageDepth)) {
                return true;
        }
 
-       if (averageDepthNew < 1) {
-               pudError(false, "Configured %s must be at least 1", valueName);
+       if (averageDepth < 1) {
+               pudError(false, "Value of parameter %s must be at least 1", valueName);
                return true;
        }
 
-       averageDepth = averageDepthNew;
-
        return false;
 }
 
@@ -1888,34 +1204,9 @@ unsigned long long getHysteresisCountToStationary(void) {
        return hysteresisCountToStationary;
 }
 
-/**
- Set hysteresis count plugin parameter
-
- @param value
- The hysteresis count plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setHysteresisCountToStationary(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_HYSTERESIS_COUNT_2STAT_NAME;
-       unsigned long long hysteresisCountNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &hysteresisCountNew)) {
-               return true;
-       }
-
-       hysteresisCountToStationary = hysteresisCountNew;
-
-       return false;
+       return !readULL(PUD_HYSTERESIS_COUNT_2STAT_NAME, value, &hysteresisCountToStationary);
 }
 
 /*
@@ -1933,41 +1224,56 @@ unsigned long long getHysteresisCountToMoving(void) {
        return hysteresisCountToMoving;
 }
 
-/**
- Set hysteresis count plugin parameter
+int setHysteresisCountToMoving(const char *value, void *data __attribute__ ((unused)),
+               set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       return !readULL(PUD_HYSTERESIS_COUNT_2MOV_NAME, value, &hysteresisCountToMoving);
+}
 
- @param value
- The hysteresis count plugin parameter
- @param data
- Unused
- @param addon
- Unused
+/*
+ * gatewayHysteresisCountToStationary
+ */
 
+/** The hysteresis count for changing state from moving to stationary */
+static unsigned long long gatewayHysteresisCountToStationary = PUD_GAT_HYSTERESIS_COUNT_2STAT_DEFAULT;
+
+/**
  @return
- - true when an error is detected
- - false otherwise
+ The hysteresis count for changing state from moving to stationary
  */
-int setHysteresisCountToMoving(const char *value, void *data __attribute__ ((unused)),
+unsigned long long getGatewayHysteresisCountToStationary(void) {
+       return gatewayHysteresisCountToStationary;
+}
+
+int setGatewayHysteresisCountToStationary(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_HYSTERESIS_COUNT_2MOV_NAME;
-       unsigned long long hysteresisCountNew;
+       return !readULL(PUD_GAT_HYSTERESIS_COUNT_2STAT_NAME, value, &gatewayHysteresisCountToStationary);
+}
 
-       assert (value != NULL);
+/*
+ * gatewayHysteresisCountToMoving
+ */
 
-       if (!readULL(valueName, value, &hysteresisCountNew)) {
-               return true;
-       }
+/** The hysteresis count for changing state from stationary to moving */
+static unsigned long long gatewayHysteresisCountToMoving = PUD_GAT_HYSTERESIS_COUNT_2MOV_DEFAULT;
 
-       hysteresisCountToMoving = hysteresisCountNew;
+/**
+ @return
+ The hysteresis count for changing state from stationary to moving
+ */
+unsigned long long getGatewayHysteresisCountToMoving(void) {
+       return gatewayHysteresisCountToMoving;
+}
 
-       return false;
+int setGatewayHysteresisCountToMoving(const char *value, void *data __attribute__ ((unused)),
+               set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       return !readULL(PUD_GAT_HYSTERESIS_COUNT_2MOV_NAME, value, &gatewayHysteresisCountToMoving);
 }
 
 /*
  * useDeDup
  */
 
-/* when true then duplicate message detection is performed */
+/** when true then duplicate message detection is performed */
 static bool useDeDup = PUD_USE_DEDUP_DEFAULT;
 
 /**
@@ -1978,92 +1284,36 @@ bool getUseDeDup(void) {
        return useDeDup;
 }
 
-/**
- Set duplicate message detection setting plugin parameter
-
- @param value
- The duplicate message detection setting plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUseDeDup(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_USE_DEDUP_NAME;
-       unsigned long long useDeDupNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &useDeDupNew)) {
-               return true;
-       }
-
-       if ((useDeDupNew != 0) && (useDeDupNew != 1)) {
-               pudError(false, "Configured %s must be 0 (false) or 1 (true)",
-                               valueName);
-               return true;
-       }
-
-       useDeDup = (useDeDupNew == 1);
-
-       return false;
+       return !readBool(PUD_USE_DEDUP_NAME, value, &useDeDup);
 }
 
 /*
  * deDupDepth
  */
 
-/** The hysteresis count for changing state from stationary to moving */
+/** The deduplication depth */
 static unsigned long long deDupDepth = PUD_DEDUP_DEPTH_DEFAULT;
 
 /**
  @return
- The hysteresis count for changing state from stationary to moving
+ The deduplication depth
  */
 unsigned long long getDeDupDepth(void) {
        return deDupDepth;
 }
 
-/**
- Set de-duplication depth plugin parameter
-
- @param value
- The de-duplication depth plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setDeDupDepth(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_DEDUP_DEPTH_NAME;
-       unsigned long long deDupDepthNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &deDupDepthNew)) {
-               return true;
-       }
-
-       deDupDepth = deDupDepthNew;
-
-       return false;
+       return !readULL(PUD_DEDUP_DEPTH_NAME, value, &deDupDepth);
 }
 
 /*
  * useLoopback
  */
 
-/* when true then loopback is performed */
+/** when true then loopback is performed */
 static bool useLoopback = PUD_USE_LOOPBACK_DEFAULT;
 
 /**
@@ -2074,40 +1324,9 @@ bool getUseLoopback(void) {
        return useLoopback;
 }
 
-/**
- Set loopback usage plugin parameter
-
- @param value
- The loopback usage plugin parameter
- @param data
- Unused
- @param addon
- Unused
-
- @return
- - true when an error is detected
- - false otherwise
- */
 int setUseLoopback(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
-       static const char * valueName = PUD_USE_LOOPBACK_NAME;
-       unsigned long long useLoopbackNew;
-
-       assert (value != NULL);
-
-       if (!readULL(valueName, value, &useLoopbackNew)) {
-               return true;
-       }
-
-       if ((useLoopbackNew != 0) && (useLoopbackNew != 1)) {
-               pudError(false, "Configured %s must be 0 (false) or 1 (true)",
-                               valueName);
-               return true;
-       }
-
-       useLoopback = (useLoopbackNew == 1);
-
-       return false;
+       return !readBool(PUD_USE_LOOPBACK_NAME, value, &useLoopback);
 }
 
 /*
@@ -2141,7 +1360,7 @@ unsigned int checkConfig(void) {
 
        if (!nodeIdSet) {
                if (nodeIdType == PUD_NODEIDTYPE_DNS) {
-                       char name[PUD_NODEIDMAXLENGTH + 1];
+                       char name[PUD_TX_NODEID_BUFFERSIZE + 1];
 
                        errno = 0;
                        if (gethostname(&name[0], sizeof(name)) < 0) {
@@ -2175,7 +1394,7 @@ unsigned int checkConfig(void) {
                retval = false;
        }
 
-       if (getUplinkPort() == getDownlinkPort()) {
+       if (isUplinkAddrSet() && (getUplinkPort() == getDownlinkPort())) {
                pudError(false, "The uplink port and the downlink port must not be the same");
                retval = false;
        }