PUD: include compiler.h where needed
[olsrd.git] / lib / pud / src / gpsConversion.c
index eebd146..1404066 100644 (file)
 #include "gpsConversion.h"
 
 /* Plugin includes */
-#include "wireFormat.h"
 #include "pud.h"
 #include "configuration.h"
-#include "nodeIdConversion.h"
-#include "nmeaTools.h"
+#include "compiler.h"
 
 /* OLSR includes */
 #include "olsr.h"
 
 /* System includes */
-#include <stdint.h>
-#include <nmea/time.h>
-#include <time.h>
-#include <nmea/gmath.h>
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
 #include <nmea/tok.h>
-#include <netinet/in.h>
-
-/*
- * GPS Information Conversion Functions For OLSR GPS Wire Format
- */
-
-/* ************************************************************************
- * TIME
- * ************************************************************************ */
-
-/**
- Convert the time of a nmeaINFO structure to the time for an OLSR message (the
- number of seconds after midnight).
-
- @param nmeaTime
- The NMEA info containing the time
-
- @return
- The time converted to the format for the wire format
- */
-static unsigned long getTimeForOlsr(nmeaTIME * nmeaTime) {
-       return ((nmeaTime->hour * 60 * 60) + (nmeaTime->min * 60) + nmeaTime->sec);
-}
-
-/**
- Convert the time of an OLSR message (the number of seconds after midnight) to
- a time structure, based on midnight of the current day.
-
- @param olsrTime
- The time from the wire format
- @param nowStruct
- A pointer to the time structure into which to put the converted time
- */
-static void getTimeFromOlsr(uint32_t olsrTime, struct tm *nowStruct) {
-       unsigned int secNow;
-
-       time_t now = time(NULL);
-       gmtime_r(&now, nowStruct);
-
-       secNow = ((nowStruct->tm_hour * 60 * 60) + (nowStruct->tm_min * 60)
-                       + nowStruct->tm_sec);
-
-       if (secNow <= (12 * 60 * 60)) {
-               /* we are now in the first 12h of the day */
-               if (unlikely(olsrTime > (secNow + (12 * 60 * 60)))) {
-                       /* the message was sent more than 12h later in time:
-                        the message was sent yesterday: adjust the date by -1 day */
-                       now -= (24 * 60 * 60);
-                       gmtime_r(&now, nowStruct);
-               }
-       } else {
-               /* we are now in the last 12h of the day */
-               if (unlikely(olsrTime < (secNow - (12 * 60 * 60)))) {
-                       /* the message was sent more than 12h earlier in time:
-                        the message was sent tomorrow: adjust the date by +1 day */
-                       now += (24 * 60 * 60);
-                       gmtime_r(&now, nowStruct);
-               }
-       }
-
-       nowStruct->tm_mon++;
-       nowStruct->tm_hour = ((olsrTime % (24 * 60 * 60)) / 3600);
-       nowStruct->tm_min = ((olsrTime % (60 * 60)) / 60);
-       nowStruct->tm_sec = (olsrTime % 60);
-}
-
-/* ************************************************************************
- * LATITUDE
- * ************************************************************************ */
-
-/**
- Convert the latitude of a nmeaINFO structure to the latitude for an OLSR
- message
-
- @param infoLat
- The latitude as contained in an NMEA info structure (in degrees)
-
- @return
- The latitude converted to the format for the wire format
- */
-static unsigned long getLatitudeForOlsr(double infoLat) {
-       double lat = infoLat;
-
-       /* lat is in [-90, 90] */
-       assert (lat >= -90.0);
-       assert (lat <= 90.0);
-
-       lat /= 180.0;
-       /* lat is now in [-0.5, 0.5] */
-
-       lat += 0.5;
-       /* lat is now in [0, 1] */
-
-       lat *= (double) (1 << PUD_LATITUDE_BITS);
-       /* lat is now in [0, LATITUDE_BITS] */
-
-       /* clip max */
-       if (unlikely(lat > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
-               lat = (double) ((1 << PUD_LATITUDE_BITS) - 1);
-       }
-       /* lat is now in [0, 2^LATITUDE_BITS> */
-
-       return lrint(lat);
-}
-
-/**
- Convert the latitude of an OLSR message to the latitude for a nmeaINFO
- structure
-
- @param olsrLat
- The latitude as contained in the wire format
-
- @return
- The latitude converted to the format for an NMEA info structure (in degrees)
- */
-static double getLatitudeFromOlsr(uint32_t olsrLat) {
-       double lat = (double) olsrLat;
-
-       /* lat is in [0, 2^LATITUDE_BITS> */
-
-       /* take half of the rounding error */
-       lat += 0.5;
-
-       lat /= (double) (1 << PUD_LATITUDE_BITS);
-       /* lat is now in [0, 1> */
-
-       lat -= 0.5;
-       /* lat is now in [-0.5, 0.5> */
-
-       lat *= 180.0;
-       /* lat is now in [-90, 90> */
-
-       return lat;
-}
-
-/* ************************************************************************
- * LONGITUDE
- * ************************************************************************ */
-
-/**
- Convert the longitude of a nmeaINFO structure to the longitude for an OLSR
- message
-
- @param infoLon
- The longitude as contained in an NMEA info structure (in degrees)
-
- @return
- The longitude converted to the format for the wire format
- */
-static unsigned long getLongitudeForOlsr(double infoLon) {
-       double lon = infoLon;
-
-       /* lon is in [-180, 180] */
-       assert (lon >= -180.0);
-       assert (lon <= 180.0);
-
-       lon /= 360.0;
-       /* lon is now in [-0.5, 0.5] */
-
-       lon += 0.5;
-       /* lon is now in [0, 1] */
-
-       lon *= (double) (1 << PUD_LONGITUDE_BITS);
-       /* lon is now in [0, LONGITUDE_BITS] */
-
-       /* clip max */
-       if (unlikely(lon > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
-               lon = (double) ((1 << PUD_LATITUDE_BITS) - 1);
-       }
-
-       /* lon is now in [0, 2^LONGITUDE_BITS> */
-
-       return lrint(lon);
-}
-
-/**
- Convert the longitude of an OLSR message to the longitude for a nmeaINFO
- structure
-
- @param olsrLon
- The longitude as contained in the wire format
-
- @return
- The longitude converted to the format for an NMEA info structure (in degrees)
- */
-static double getLongitudeFromOlsr(uint32_t olsrLon) {
-       double lon = (double) olsrLon;
-
-       /* lon is in [0, 2^LONGITUDE_BITS> */
-
-       /* take half of the rounding error */
-       lon += 0.5;
-
-       lon /= (1 << PUD_LONGITUDE_BITS);
-       /* lon is now in [0, 1> */
-
-       lon -= 0.5;
-       /* lon is now in [-0.5, 0.5> */
-
-       lon *= 360.0;
-       /* lon is now in [-180, 180> */
-
-       return lon;
-}
-
-/* ************************************************************************
- * ALTITIDE
- * ************************************************************************ */
-
-/**
- Convert the altitude of a nmeaINFO structure to the altitude for an OLSR
- message
-
- @param infoElv
- The altitude as contained in an NMEA info structure
-
- @return
- The altitude converted to the format for the wire format
- */
-static long getAltitudeForOlsr(double infoElv) {
-       double elv = infoElv;
-
-       if (unlikely(elv > PUD_ALTITUDE_MAX)) {
-               elv = PUD_ALTITUDE_MAX;
-       } else if (unlikely(elv < PUD_ALTITUDE_MIN)) {
-               elv = PUD_ALTITUDE_MIN;
-       }
-
-       elv -= PUD_ALTITUDE_MIN;
-
-       return lrint(elv);
-}
-
-/**
- Convert the altitude of an OLSR message to the altitude for a nmeaINFO
- structure
-
- @param olsrAlt
- The altitude as contained in the wire format
-
- @return
- The altitude converted to the format for an NMEA info structure
- */
-static long getAltitudeFromOlsr(uint32_t olsrAlt) {
-       return (olsrAlt + PUD_ALTITUDE_MIN);
-}
-
-/* ************************************************************************
- * SPEED
- * ************************************************************************ */
-
-/**
- Convert the speed of a nmeaINFO structure to the speed for an OLSR message
-
- @param infoSpeed
- The speed as contained in an NMEA info structure
-
- @return
- The speed converted to the format for the wire format
- */
-static long getSpeedForOlsr(double infoSpeed) {
-       if (unlikely(infoSpeed < 0)) {
-               return 0;
-       }
-       if (unlikely(infoSpeed > PUD_SPEED_MAX)) {
-               return PUD_SPEED_MAX;
-       }
-
-       return lrint(infoSpeed);
-}
-
-/**
- Convert the speed of an OLSR message to the speed for a nmeaINFO structure
-
- @param olsrSpeed
- The speed as contained in the wire format
-
- @return
- The speed converted to the format for an NMEA info structure
- */
-static unsigned long getSpeedFromOlsr(uint32_t olsrSpeed) {
-       return olsrSpeed;
-}
-
-/* ************************************************************************
- * TRACK
- * ************************************************************************ */
-
-/**
- Convert the track angle of a nmeaINFO structure to the track angle for an OLSR
- message
-
- @param infoTrack
- The track angle as contained in an NMEA info structure
-
- @return
- The track angle converted to the format for the wire format
- */
-static long getTrackForOlsr(double infoTrack) {
-       return lrint(infoTrack);
-}
-
-/**
- Convert the track angle of an OLSR message to the track angle for a nmeaINFO
- structure
-
- @param olsrTrack
- The track angle as contained in the wire format
-
- @return
- The track angle converted to the format for an NMEA info structure
- */
-static unsigned long getTrackFromOlsr(uint32_t olsrTrack) {
-       return olsrTrack;
-}
-
-/* ************************************************************************
- * HDOP
- * ************************************************************************ */
-
-/**
- Convert the HDOP of a nmeaINFO structure to the HDOP for an OLSR message
-
- @param infoHdop
- The HDOP as contained in an NMEA info structure
-
- @return
- The HDOP converted to the format for the wire format
- */
-static long getHdopForOlsr(double infoHdop) {
-       double infoHdopInternal = infoHdop;
-
-       if (unlikely(infoHdopInternal > PUD_HDOP_MAX)) {
-               infoHdopInternal = PUD_HDOP_MAX;
-       }
-
-       return lrint(infoHdopInternal / PUD_HDOP_RESOLUTION);
-}
-
-/**
- Convert the HDOP of an OLSR message to the HDOP for a nmeaINFO structure
-
- @param olsrHdop
- The HDOP as contained in the wire format
-
- @return
- The HDOP converted to the format for an NMEA info structure
- */
-static double getHdopFromOlsr(uint32_t olsrHdop) {
-       return (olsrHdop * PUD_HDOP_RESOLUTION);
-}
-
-/* ************************************************************************
- * VALIDITY TIME
- * ************************************************************************ */
-
-/** Determine the validity time in seconds from the OLSR wire format value */
-#define PUD_VALIDITY_TIME_FROM_OLSR(msn, lsn) ((((lsn) + 16) * (1 << (msn))) - 16)
-
-unsigned long long cachedValidityTimeMsn[16];
-
-/**
- Setup of cache of calculated most significant nibble results of the validity
- time calculation to speed up run-time calculations.
- */
-void setupCachedValidityTimeMsn(void) {
-       unsigned int msn;
-       for (msn = 0; msn < 16; msn++) {
-               cachedValidityTimeMsn[msn] = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
-       }
-}
-
-/**
- Convert the validity time to the validity time for an OLSR message
-
- @param validityTime
- The validity time (in seconds)
-
- @return
- The validity time converted to the format for the wire format
- */
-static unsigned char getValidityTimeForOlsr(unsigned long long validityTime) {
-       unsigned int msn = 1;
-       unsigned long long lsn = 0;
-       unsigned long long upperBound = cachedValidityTimeMsn[msn];
-       while ((msn < 16) && (validityTime >= upperBound)) {
-               msn++;
-               upperBound = cachedValidityTimeMsn[msn];
-       }
-       msn--;
-
-       if (unlikely(validityTime >= upperBound)) {
-               lsn = 15;
-       } else {
-               unsigned long lowerBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
-               unsigned long resolution = (1 << msn);
-               lsn = ((validityTime - lowerBound + (resolution >> 1)) / resolution);
-       }
-
-       assert (msn <= 15);
-       assert (lsn <= 15);
-
-       return (msn << 4) | lsn;
-}
-
-/**
- Convert the validity time of an OLSR message to the validity time for internal
- use.
-
- @param internal
- The validity time as contained in the wire format
-
- @return
- The validity time converted to seconds
- */
-static unsigned long getValidityTimeFromOlsr(unsigned char internal) {
-       return PUD_VALIDITY_TIME_FROM_OLSR(internal >> 4, internal % 16);
-}
+#include <nmea/gmath.h>
+#include <arpa/inet.h>
+#include <OlsrdPudWireFormat/nodeIdConversion.h>
 
 /* ************************************************************************
  * OLSR --> External
@@ -447,8 +23,6 @@ static unsigned long getValidityTimeFromOlsr(unsigned char internal) {
 
  @param olsrMessage
  A pointer to the OLSR message
- @param olsrMessagePayload
- A pointer to the GPS message in the OLSR message
  @param txGpsBuffer
  A pointer to the buffer in which the transmit string can be written
  @param txGpsBufferSize
@@ -458,13 +32,8 @@ static unsigned long getValidityTimeFromOlsr(unsigned char internal) {
  - the length of the transmit string placed in the txGpsBuffer
  - 0 (zero) in case of an error
  */
-unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
-               unsigned char *olsrMessagePayload, unsigned char * txGpsBuffer,
-               unsigned int txGpsBufferSize) {
-       PudOlsrWireFormat *olsrGpsMessage =
-                       (PudOlsrWireFormat *) olsrMessagePayload;
-       const GpsInfo* gpsMessage = &olsrGpsMessage->gpsInfo;
-
+unsigned int gpsFromOlsr(union olsr_message *olsrMessage,
+               unsigned char * txGpsBuffer, unsigned int txGpsBufferSize) {
        unsigned long validityTime;
 
        struct tm timeStruct;
@@ -476,29 +45,52 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
        char speedString[PUD_TX_SPEED_DIGITS + 1];
        char trackString[PUD_TX_TRACK_DIGITS + 1];
        char hdopString[PUD_TX_HDOP_DIGITS + 1];
+       uint8_t smask;
+       uint8_t flags;
+       char gateway[2] = { '0', '\0' };
 
        char nodeIdTypeString[PUD_TX_NODEIDTYPE_DIGITS + 1];
        char nodeIdString[PUD_TX_NODEID_BUFFERSIZE + 1];
        const char * nodeId;
+       const void * ipAddr;
+       char originatorBuffer[64];
+       const char * originator;
 
        unsigned int transmitStringLength;
 
-       if (unlikely(olsrGpsMessage->version != PUD_WIRE_FORMAT_VERSION)) {
+       PudOlsrPositionUpdate * olsrGpsMessage =
+                       getOlsrMessagePayload(olsr_cnf->ip_version, olsrMessage);
+
+       if (unlikely(getPositionUpdateVersion(olsrGpsMessage) != PUD_WIRE_FORMAT_VERSION)) {
                /* currently we can only handle our own version */
                pudError(false, "Can not handle version %u OLSR PUD messages"
-                       " (only version %u): message ignored", olsrGpsMessage->version,
-                               PUD_WIRE_FORMAT_VERSION);
+                       " (only version %u): message ignored",
+                       getPositionUpdateVersion(olsrGpsMessage), PUD_WIRE_FORMAT_VERSION);
                return 0;
        }
 
-       validityTime = getValidityTimeFromOlsr(olsrGpsMessage->validityTime);
+       ipAddr = (olsr_cnf->ip_version == AF_INET) ?
+                               (void *) &olsrMessage->v4.originator :
+                               (void *) &olsrMessage->v6.originator;
+       originator = inet_ntop(olsr_cnf->ip_version, ipAddr, &originatorBuffer[0],
+                       sizeof(originatorBuffer));
+
+       validityTime = getValidityTime(&olsrGpsMessage->validityTime);
+
+       smask = getPositionUpdateSmask(olsrGpsMessage);
+
+       flags = getPositionUpdateSmask(olsrGpsMessage);
+
+       if (flags & PUD_FLAGS_GATEWAY) {
+               gateway[0] = '1';
+       }
 
        /* time is ALWAYS present so we can just use it */
-       getTimeFromOlsr(gpsMessage->time, &timeStruct);
+       getPositionUpdateTime(olsrGpsMessage, time(NULL), &timeStruct);
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, LAT))) {
+       if (likely(nmea_INFO_has_field(smask, LAT))) {
                int chars;
-               double latitude = getLatitudeFromOlsr(gpsMessage->lat);
+               double latitude = getPositionUpdateLatitude(olsrGpsMessage);
 
                if (latitude >= 0) {
                        latitudeHemisphere = "N";
@@ -520,9 +112,9 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                latitudeString[0] = '\0';
        }
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, LON))) {
+       if (likely(nmea_INFO_has_field(smask, LON))) {
                int chars;
-               double longitude = getLongitudeFromOlsr(gpsMessage->lon);
+               double longitude = getPositionUpdateLongitude(olsrGpsMessage);
 
                if (longitude >= 0) {
                        longitudeHemisphere = "E";
@@ -544,9 +136,9 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                longitudeString[0] = '\0';
        }
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, ELV))) {
+       if (likely(nmea_INFO_has_field(smask, ELV))) {
                int chars = snprintf(&altitudeString[0], PUD_TX_ALTITUDE_DIGITS, "%ld",
-                               getAltitudeFromOlsr(gpsMessage->alt));
+                               getPositionUpdateAltitude(olsrGpsMessage));
                if (likely(chars < PUD_TX_ALTITUDE_DIGITS)) {
                        altitudeString[chars] = '\0';
                } else {
@@ -556,9 +148,9 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                altitudeString[0] = '\0';
        }
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, SPEED))) {
+       if (likely(nmea_INFO_has_field(smask, SPEED))) {
                int chars = snprintf(&speedString[0], PUD_TX_SPEED_DIGITS, "%lu",
-                               getSpeedFromOlsr(gpsMessage->speed));
+                               getPositionUpdateSpeed(olsrGpsMessage));
                if (likely(chars < PUD_TX_SPEED_DIGITS)) {
                        speedString[chars] = '\0';
                } else {
@@ -568,9 +160,9 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                speedString[0] = '\0';
        }
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, DIRECTION))) {
+       if (likely(nmea_INFO_has_field(smask, DIRECTION))) {
                int chars = snprintf(&trackString[0], PUD_TX_TRACK_DIGITS, "%lu",
-                               getTrackFromOlsr(gpsMessage->track));
+                               getPositionUpdateTrack(olsrGpsMessage));
                if (likely(chars < PUD_TX_TRACK_DIGITS)) {
                        trackString[chars] = '\0';
                } else {
@@ -580,10 +172,10 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                trackString[0] = '\0';
        }
 
-       if (likely(nmeaInfoHasField(olsrGpsMessage->smask, HDOP))) {
+       if (likely(nmea_INFO_has_field(smask, HDOP))) {
                int chars = snprintf(&hdopString[0], PUD_TX_HDOP_DIGITS,
-                               "%." PUD_TX_HDOP_DECIMALS "f", nmea_meters2dop(getHdopFromOlsr(
-                                               gpsMessage->hdop)));
+                               "%." PUD_TX_HDOP_DECIMALS "f", nmea_meters2dop(getPositionUpdateHdop(
+                                               olsrGpsMessage)));
                if (likely(chars < PUD_TX_HDOP_DIGITS)) {
                        hdopString[chars] = '\0';
                } else {
@@ -593,12 +185,16 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                hdopString[0] = '\0';
        }
 
-       getNodeInfoFromOlsr(olsrMessage, olsrGpsMessage, &nodeIdString[0],
-                       PUD_TX_NODEID_BUFFERSIZE, &nodeId, &nodeIdTypeString[0]);
+       getNodeTypeStringFromOlsr(olsr_cnf->ip_version, olsrGpsMessage,
+                       &nodeIdTypeString[0], sizeof(nodeIdTypeString));
+       getNodeIdStringFromOlsr(olsr_cnf->ip_version, olsrMessage, &nodeId,
+                       &nodeIdString[0], sizeof(nodeIdString));
 
        transmitStringLength = nmea_printf((char *) txGpsBuffer, txGpsBufferSize
                        - 1, "$P%s," /* prefix (always) */
                "%u," /* sentence version (always) */
+               "%s," /* gateway flag (always) */
+               "%s," /* OLSR originator (always) */
                "%s,%s," /* nodeIdType/nodeId (always) */
                "%02u%02u%02u," /* date (always) */
                "%02u%02u%02u," /* time (always) */
@@ -609,8 +205,9 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
                "%s," /* speed (optional) */
                "%s," /* track (optional) */
                "%s" /* hdop (optional) */
-       , getTxNmeaMessagePrefix(), PUD_TX_SENTENCE_VERSION, &nodeIdTypeString[0],
-                       nodeId, timeStruct.tm_mday, timeStruct.tm_mon, (timeStruct.tm_year
+       , getTxNmeaMessagePrefix(), PUD_TX_SENTENCE_VERSION, &gateway[0],
+                       originator , &nodeIdTypeString[0],
+                       nodeId, timeStruct.tm_mday, timeStruct.tm_mon + 1, (timeStruct.tm_year
                                        % 100), timeStruct.tm_hour, timeStruct.tm_min,
                        timeStruct.tm_sec, validityTime, &latitudeString[0],
                        latitudeHemisphere, &longitudeString[0], longitudeHemisphere,
@@ -646,7 +243,7 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
  @param olsrMessageSize
  The maximum number of bytes available for the olsrMessage
  @param validityTime
- the validity time of the message
+ the validity time of the message in seconds
 
  @return
  - the aligned size of the converted information
@@ -654,65 +251,69 @@ unsigned int gpsFromOlsr(const union olsr_message *olsrMessage,
  */
 unsigned int gpsToOlsr(nmeaINFO *nmeaInfo, union olsr_message *olsrMessage,
                unsigned int olsrMessageSize, unsigned long long validityTime) {
-       PudOlsrWireFormat * olsrGpsMessage;
        unsigned int aligned_size;
        unsigned int aligned_size_remainder;
        size_t nodeLength;
+       nodeIdBinaryType * nodeIdBinary = NULL;
 
-       if (olsr_cnf->ip_version == AF_INET) {
-               olsrGpsMessage = (PudOlsrWireFormat *) &olsrMessage->v4.message;
-       } else {
-               olsrGpsMessage = (PudOlsrWireFormat *) &olsrMessage->v6.message;
-       }
+       PudOlsrPositionUpdate * olsrGpsMessage =
+                       getOlsrMessagePayload(olsr_cnf->ip_version, olsrMessage);
 
        /*
         * Compose message contents
         */
+       memset(olsrGpsMessage, 0, sizeof (PudOlsrPositionUpdate));
 
-       olsrGpsMessage->version = PUD_WIRE_FORMAT_VERSION;
-       olsrGpsMessage->validityTime = getValidityTimeForOlsr(validityTime);
-       olsrGpsMessage->smask = nmeaInfo->smask;
+       setPositionUpdateVersion(olsrGpsMessage, PUD_WIRE_FORMAT_VERSION);
+       setValidityTime(&olsrGpsMessage->validityTime, validityTime);
+       setPositionUpdateSmask(olsrGpsMessage, nmeaInfo->smask);
+       setPositionUpdateFlags(olsrGpsMessage,
+                       getPositionUpdateFlags(olsrGpsMessage) & ~PUD_FLAGS_GATEWAY);
 
-       /* utc is always present, we make sure of that, so just use it */
-       olsrGpsMessage->gpsInfo.time = getTimeForOlsr(&nmeaInfo->utc);
+       /* utc is always present, we make sure of that elsewhere, so just use it */
+       setPositionUpdateTime(olsrGpsMessage, nmeaInfo->utc.hour, nmeaInfo->utc.min,
+                       nmeaInfo->utc.sec);
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, LAT))) {
-               olsrGpsMessage->gpsInfo.lat = getLatitudeForOlsr(nmeaInfo->lat);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, LAT))) {
+               setPositionUpdateLatitude(olsrGpsMessage, nmeaInfo->lat);
        } else {
-               olsrGpsMessage->gpsInfo.lat = (1 << (PUD_LATITUDE_BITS - 1));
+               setPositionUpdateLatitude(olsrGpsMessage, 0.0);
        }
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, LON))) {
-               olsrGpsMessage->gpsInfo.lon = getLongitudeForOlsr(nmeaInfo->lon);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, LON))) {
+               setPositionUpdateLongitude(olsrGpsMessage, nmeaInfo->lon);
        } else {
-               olsrGpsMessage->gpsInfo.lon = (1 << (PUD_LONGITUDE_BITS - 1));
+               setPositionUpdateLongitude(olsrGpsMessage, 0.0);
        }
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, ELV))) {
-               olsrGpsMessage->gpsInfo.alt = getAltitudeForOlsr(nmeaInfo->elv);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, ELV))) {
+               setPositionUpdateAltitude(olsrGpsMessage, nmeaInfo->elv);
        } else {
-               olsrGpsMessage->gpsInfo.alt = -PUD_ALTITUDE_MIN;
+               setPositionUpdateAltitude(olsrGpsMessage, 0.0);
        }
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, SPEED))) {
-               olsrGpsMessage->gpsInfo.speed = getSpeedForOlsr(nmeaInfo->speed);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, SPEED))) {
+               setPositionUpdateSpeed(olsrGpsMessage, nmeaInfo->speed);
        } else {
-               olsrGpsMessage->gpsInfo.speed = 0;
+               setPositionUpdateSpeed(olsrGpsMessage, 0.0);
        }
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, DIRECTION))) {
-               olsrGpsMessage->gpsInfo.track = getTrackForOlsr(nmeaInfo->direction);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, DIRECTION))) {
+               setPositionUpdateTrack(olsrGpsMessage, nmeaInfo->direction);
        } else {
-               olsrGpsMessage->gpsInfo.track = 0;
+               setPositionUpdateTrack(olsrGpsMessage, 0);
        }
 
-       if (likely(nmeaInfoHasField(nmeaInfo->smask, HDOP))) {
-               olsrGpsMessage->gpsInfo.hdop = getHdopForOlsr(nmeaInfo->HDOP);
+       if (likely(nmea_INFO_has_field(nmeaInfo->smask, HDOP))) {
+               setPositionUpdateHdop(olsrGpsMessage, nmeaInfo->HDOP);
        } else {
-               olsrGpsMessage->gpsInfo.hdop = PUD_HDOP_MAX;
+               setPositionUpdateHdop(olsrGpsMessage, PUD_HDOP_MAX);
        }
 
-       nodeLength = setupNodeInfoForOlsr(olsrGpsMessage, olsrMessageSize);
+       nodeIdBinary = getNodeIdBinary();
+       nodeLength = setPositionUpdateNodeInfo(olsr_cnf->ip_version, olsrGpsMessage,
+                       olsrMessageSize, getNodeIdTypeNumber(),
+                       (unsigned char *) &nodeIdBinary->buffer, nodeIdBinary->length);
 
        /*
         * Messages in OLSR are 4-byte aligned: align
@@ -736,8 +337,7 @@ unsigned int gpsToOlsr(nmeaINFO *nmeaInfo, union olsr_message *olsrMessage,
                olsrMessage->v4.olsr_msgtype = PUD_OLSR_MSG_TYPE;
                olsrMessage->v4.olsr_vtime = reltime_to_me(validityTime * 1000);
                /* message->v4.olsr_msgsize at the end */
-               memcpy(&olsrMessage->v4.originator, &olsr_cnf->main_addr,
-                               olsr_cnf->ipsize);
+               olsrMessage->v4.originator = olsr_cnf->main_addr.v4.s_addr;
                olsrMessage->v4.ttl = getOlsrTtl();
                olsrMessage->v4.hopcnt = 0;
                olsrMessage->v4.seqno = htons(get_msg_seqno());
@@ -752,8 +352,7 @@ unsigned int gpsToOlsr(nmeaINFO *nmeaInfo, union olsr_message *olsrMessage,
                olsrMessage->v6.olsr_msgtype = PUD_OLSR_MSG_TYPE;
                olsrMessage->v6.olsr_vtime = reltime_to_me(validityTime * 1000);
                /* message->v6.olsr_msgsize at the end */
-               memcpy(&olsrMessage->v6.originator, &olsr_cnf->main_addr,
-                               olsr_cnf->ipsize);
+               olsrMessage->v6.originator = olsr_cnf->main_addr.v6;
                olsrMessage->v6.ttl = getOlsrTtl();
                olsrMessage->v6.hopcnt = 0;
                olsrMessage->v6.seqno = htons(get_msg_seqno());