96cc534db7f0c1269f388c76bb97b29d2bf9d039
[olsrd.git] / lib / pud / wireformat / src / wireFormat.c
1 #include <OlsrdPudWireFormat/wireFormat.h>
2
3 #include <time.h>
4
5 /*
6  * NodeIdType
7  */
8
9 bool isValidNodeIdType(unsigned long long nodeIdType) {
10         return
11         (
12                 (
13                         (/* (nodeIdType >= PUD_NODEIDTYPE_GLOBAL_FIRST) && */ (nodeIdType <= PUD_NODEIDTYPE_GLOBAL_LAST)) ||
14                         (   (nodeIdType >= PUD_NODEIDTYPE_LOCAL_FIRST ) &&    (nodeIdType <= PUD_NODEIDTYPE_LOCAL_LAST ))
15                 )
16                 &&
17                 (
18                         (nodeIdType != PUD_NODEIDTYPE_GAP1)
19                 )
20         );
21 }
22
23
24 /*
25  * Validity Time
26  */
27
28 /** Determine the validity time in seconds from the OLSR wire format value */
29 #define PUD_VALIDITY_TIME_FROM_OLSR(msn, lsn) ((((lsn) + 16) * (1 << (msn))) - 16)
30
31 /**
32  Get the validity time from a message
33
34  @param validityTimeField
35  A pointer to the validity time field
36
37  @return
38  The validity time in seconds
39  */
40 unsigned long getValidityTime(uint8_t * validityTimeField) {
41         return PUD_VALIDITY_TIME_FROM_OLSR(*validityTimeField >> 4, *validityTimeField % 16);
42 }
43
44 /**
45  Set the validity time of the position update message
46
47  @param validityTimeField
48  A pointer to the validity time field
49  @param validityTime
50  The validity time in seconds
51  */
52 void setValidityTime(uint8_t * validityTimeField, unsigned long long validityTime) {
53         unsigned int msn = 1;
54         unsigned long long lsn = 0;
55         unsigned long long upperBound;
56
57         upperBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
58         while ((msn < 16) && (validityTime >= upperBound)) {
59                 msn++;
60                 upperBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
61         }
62         msn--;
63
64         if (unlikely(validityTime >= upperBound)) {
65                 lsn = 15;
66         } else {
67                 unsigned long lowerBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
68                 unsigned long resolution = (1 << msn);
69                 lsn = ((validityTime - lowerBound + (resolution >> 1)) / resolution);
70         }
71
72         assert(msn <= 15);
73         assert(lsn <= 15);
74
75         *validityTimeField = ((msn << 4) | lsn);
76 }
77
78 /*
79  * UplinkHeader
80  */
81
82 /**
83  Get the type of the uplink message
84
85  @param uplinkHeader
86  A pointer to the uplink message
87  @return
88  The type of the uplink message
89  */
90 uint8_t getUplinkMessageType(UplinkHeader * uplinkHeader) {
91         return uplinkHeader->type;
92 }
93
94 /**
95  Set the type of the uplink message
96
97  @param uplinkHeader
98  A pointer to the uplink message
99  @param type
100  The type of the uplink message
101  */
102 void setUplinkMessageType(UplinkHeader * uplinkHeader,
103                 uint8_t type) {
104         uplinkHeader->type = type;
105 }
106
107 /**
108  Get the length of the uplink message
109
110  @param uplinkHeader
111  A pointer to the uplink message
112  @return
113  The length of the uplink message
114  */
115 uint16_t getUplinkMessageLength(UplinkHeader * uplinkHeader) {
116         return ntohs(uplinkHeader->length);
117 }
118
119 /**
120  Set the length of the uplink message
121
122  @param uplinkHeader
123  A pointer to the uplink message
124  @param length
125  The length of the uplink message
126  */
127 void setUplinkMessageLength(UplinkHeader * uplinkHeader,
128                 uint16_t length) {
129         uplinkHeader->length = ntohs(length);
130 }
131
132 /**
133  Get the IPv6 status of the uplink message
134
135  @param uplinkHeader
136  A pointer to the uplink message
137  @return
138  true when the uplink message is sent from an olsrd stack in IPv6 mode, false
139  otherwise
140  */
141 bool getUplinkMessageIPv6(UplinkHeader * uplinkHeader) {
142         return (uplinkHeader->ipv6 == 1);
143 }
144
145 /**
146  Set the IPv6 status of the uplink message
147
148  @param uplinkHeader
149  A pointer to the uplink message
150  @param ipv6
151  The IPv6 status of the uplink message (true when the uplink message is sent
152  from olsrd stack in IPv6 mode, false otherwise)
153  */
154 void setUplinkMessageIPv6(UplinkHeader * uplinkHeader,
155                 bool ipv6) {
156         uplinkHeader->ipv6 = ipv6 ? 1 : 0;
157 }
158
159 /**
160  Set the padding of the uplink message header
161
162  @param uplinkHeader
163  A pointer to the uplink message
164  @param pad
165  The padding of the uplink message header
166  */
167 void setUplinkMessagePadding(UplinkHeader * uplinkHeader,
168                 uint8_t pad) {
169         uplinkHeader->pad = pad;
170 }
171
172 /*
173  * OLSR header
174  */
175
176 /**
177  Determine the size of an OLSR message
178
179  @param ipVersion
180  The IP version
181  @param olsrMessage
182  A pointer to the OLSR message
183  @return
184  The size of the OLSR message
185  */
186 unsigned short getOlsrMessageSize(int ipVersion,
187                 union olsr_message * olsrMessage) {
188         if (ipVersion == AF_INET) {
189                 return ntohs(olsrMessage->v4.olsr_msgsize);
190         }
191
192         return ntohs(olsrMessage->v6.olsr_msgsize);
193 }
194
195 /**
196  Get the originator of an OLSR message
197
198  @param ipVersion
199  The IP version (AF_INET or AF_INET6)
200  @param olsrMessage
201  A pointer to the OLSR message
202  @return
203  A pointer to the originator address
204  */
205 union olsr_ip_addr * getOlsrMessageOriginator(int ipVersion,
206                 union olsr_message * olsrMessage) {
207         if (ipVersion == AF_INET) {
208                 return (union olsr_ip_addr *) &olsrMessage->v4.originator;
209         }
210
211         return (union olsr_ip_addr *) &olsrMessage->v6.originator;
212 }
213
214 /**
215  Get the position update message in an OLSR message
216
217  @param ipVersion
218  The IP version (AF_INET or AF_INET6)
219  @param olsrMessage
220  A pointer to the OLSR message
221  @return
222  A pointer to the position update message
223  */
224 PudOlsrPositionUpdate * getOlsrMessagePayload(int ipVersion,
225                 union olsr_message * olsrMessage) {
226         if (ipVersion == AF_INET) {
227                 return (PudOlsrPositionUpdate *) &olsrMessage->v4.message;
228         }
229
230         return (PudOlsrPositionUpdate *) &olsrMessage->v6.message;
231 }
232
233 /*
234  * PudOlsrPositionUpdate
235  */
236
237 /**
238  Get the version of the position update message
239
240  @param olsrGpsMessage
241  A pointer to the position update message
242  @return
243  The version of the position update message
244  */
245 uint8_t getPositionUpdateVersion(
246                 PudOlsrPositionUpdate * olsrGpsMessage) {
247         return olsrGpsMessage->version;
248 }
249
250 /**
251  Set the version of the position update message
252
253  @param olsrGpsMessage
254  A pointer to the position update message
255  @param version
256  The version of the position update message
257  */
258 void setPositionUpdateVersion(
259                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t version) {
260         olsrGpsMessage->version = version;
261 }
262
263 /**
264  Get the smask of the position update message
265
266  @param olsrGpsMessage
267  A pointer to the position update message
268  @return
269  The smask of the position update message
270  */
271 uint8_t getPositionUpdateSmask(
272                 PudOlsrPositionUpdate * olsrGpsMessage) {
273         return olsrGpsMessage->smask;
274 }
275
276 /**
277  Set the smask of the position update message
278
279  @param olsrGpsMessage
280  A pointer to the position update message
281  @param smask
282  The smask of the position update message
283  */
284 void setPositionUpdateSmask(
285                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t smask) {
286         olsrGpsMessage->smask = smask;
287 }
288
289 /**
290  Get the flags of the position update message
291
292  @param olsrGpsMessage
293  A pointer to the position update message
294  @return
295  The flags of the position update message
296  */
297 uint8_t getPositionUpdateFlags(
298                 PudOlsrPositionUpdate * olsrGpsMessage) {
299         return olsrGpsMessage->flags;
300 }
301
302 /**
303  Set the flags of the position update message
304
305  @param olsrGpsMessage
306  A pointer to the position update message
307  @param flags
308  The flags of the position update message
309  */
310 void setPositionUpdateFlags(
311                 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t flags) {
312         olsrGpsMessage->flags = flags;
313 }
314
315 /*
316  * GpsInfo
317  */
318
319 /**
320  Convert the time of an OLSR message (the number of seconds after midnight) to
321  a time structure, based on midnight of the current day.
322
323  @param olsrGpsMessage
324  A pointer to the position update message
325  @param baseDate
326  The base date from which to determine the time (number of seconds since Epoch,
327  UTC)
328  @param nowStruct
329  A pointer to the time structure into which to put the converted time
330  */
331 void getPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
332                 time_t baseDate, struct tm *nowStruct) {
333         uint32_t olsrTime = olsrGpsMessage->gpsInfo.time;
334         unsigned int secNow;
335
336         time_t now = baseDate;
337         gmtime_r(&now, nowStruct);
338
339         secNow = ((nowStruct->tm_hour * 60 * 60) + (nowStruct->tm_min * 60)
340                         + nowStruct->tm_sec);
341
342         if (secNow <= (12 * 60 * 60)) {
343                 /* we are now in the first 12h of the day */
344                 if (unlikely(olsrTime > (secNow + (12 * 60 * 60)))) {
345                         /* the message was sent more than 12h later in time:
346                          the message was sent yesterday: adjust the date by -1 day */
347                         now -= (24 * 60 * 60);
348                         gmtime_r(&now, nowStruct);
349                 }
350         } else {
351                 /* we are now in the last 12h of the day */
352                 if (unlikely(olsrTime < (secNow - (12 * 60 * 60)))) {
353                         /* the message was sent more than 12h earlier in time:
354                          the message was sent tomorrow: adjust the date by +1 day */
355                         now += (24 * 60 * 60);
356                         gmtime_r(&now, nowStruct);
357                 }
358         }
359
360         nowStruct->tm_hour = ((olsrTime % (24 * 60 * 60)) / 3600);
361         nowStruct->tm_min = ((olsrTime % (60 * 60)) / 60);
362         nowStruct->tm_sec = (olsrTime % 60);
363 }
364
365 /**
366  Set the time of the position update message (the number of seconds after
367  midnight)
368
369  @param olsrGpsMessage
370  A pointer to the position update message
371  @param hour
372  The hours
373  @param min
374  The minutes
375  @param sec
376  The seconds
377  */
378 void setPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
379                 int hour, int min, int sec) {
380         olsrGpsMessage->gpsInfo.time = ((hour * 60 * 60) + (min * 60) + sec);
381 }
382
383 /**
384  Get the latitude of the position update message
385
386  @param olsrGpsMessage
387  A pointer to the position update message
388
389  @return
390  The latitude converted to degrees: [-90, 90>
391  */
392 double getPositionUpdateLatitude(
393                 PudOlsrPositionUpdate * olsrGpsMessage) {
394         uint32_t olsrLat = olsrGpsMessage->gpsInfo.lat;
395         double lat = (double) olsrLat;
396
397         /* lat is in [0, 2^LATITUDE_BITS> */
398
399         /* take half of the rounding error */
400         lat += 0.5;
401
402         lat /= (double) (1 << PUD_LATITUDE_BITS);
403         /* lat is now in [0, 1> */
404
405         lat -= 0.5;
406         /* lat is now in [-0.5, 0.5> */
407
408         lat *= 180.0;
409         /* lat is now in [-90, 90> */
410
411         return lat;
412 }
413
414 /**
415  Set the latitude of the position update message
416
417  @param olsrGpsMessage
418  A pointer to the position update message
419  @param latitude
420  The latitude in degrees: [-90, 90]
421  */
422 void setPositionUpdateLatitude(
423                 PudOlsrPositionUpdate * olsrGpsMessage, double latitude) {
424         double lat = latitude;
425
426         /* lat is in [-90, 90] */
427         assert(lat >= -90.0);
428         assert(lat <= 90.0);
429
430         lat /= 180.0;
431         /* lat is now in [-0.5, 0.5] */
432
433         lat += 0.5;
434         /* lat is now in [0, 1] */
435
436         lat *= (double) (1 << PUD_LATITUDE_BITS);
437         /* lat is now in [0, LATITUDE_BITS] */
438
439         /* clip max */
440         if (unlikely(lat > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
441                 lat = (double) ((1 << PUD_LATITUDE_BITS) - 1);
442         }
443         /* lat is now in [0, 2^LATITUDE_BITS> */
444
445         olsrGpsMessage->gpsInfo.lat = lrint(lat);
446 }
447
448 /**
449  Get the longitude of the position update message
450
451  @param olsrGpsMessage
452  A pointer to the position update message
453
454  @return
455  The longitude converted to degrees: [-180, 180>
456  */
457 double getPositionUpdateLongitude(
458                 PudOlsrPositionUpdate * olsrGpsMessage) {
459         uint32_t olsrLon = olsrGpsMessage->gpsInfo.lon;
460         double lon = (double) olsrLon;
461
462         /* lon is in [0, 2^LONGITUDE_BITS> */
463
464         /* take half of the rounding error */
465         lon += 0.5;
466
467         lon /= (1 << PUD_LONGITUDE_BITS);
468         /* lon is now in [0, 1> */
469
470         lon -= 0.5;
471         /* lon is now in [-0.5, 0.5> */
472
473         lon *= 360.0;
474         /* lon is now in [-180, 180> */
475
476         return lon;
477 }
478
479 /**
480  Set the longitude of the position update message
481
482  @param olsrGpsMessage
483  A pointer to the position update message
484  @param longitude
485  The longitude in degrees: [-90, 90]
486  */
487 void setPositionUpdateLongitude(
488                 PudOlsrPositionUpdate * olsrGpsMessage, double longitude) {
489         double lon = longitude;
490
491         /* lon is in [-180, 180] */
492         assert(lon >= -180.0);
493         assert(lon <= 180.0);
494
495         lon /= 360.0;
496         /* lon is now in [-0.5, 0.5] */
497
498         lon += 0.5;
499         /* lon is now in [0, 1] */
500
501         lon *= (double) (1 << PUD_LONGITUDE_BITS);
502         /* lon is now in [0, LONGITUDE_BITS] */
503
504         /* clip max */
505         if (unlikely(lon > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
506                 lon = (double) ((1 << PUD_LATITUDE_BITS) - 1);
507         }
508
509         /* lon is now in [0, 2^LONGITUDE_BITS> */
510
511         olsrGpsMessage->gpsInfo.lon = lrint(lon);
512 }
513
514 /**
515  Get the altitude of the position update message
516
517  @param olsrGpsMessage
518  A pointer to the position update message
519
520  @return
521  The altitude in meters
522  */
523 long getPositionUpdateAltitude(
524                 PudOlsrPositionUpdate * olsrGpsMessage) {
525         return ((long) olsrGpsMessage->gpsInfo.alt + PUD_ALTITUDE_MIN);
526 }
527
528 /**
529  Set the altitude of the position update message
530
531  @param olsrGpsMessage
532  A pointer to the position update message
533  @param altitude
534  The altitude in meters
535  */
536 void setPositionUpdateAltitude(
537                 PudOlsrPositionUpdate * olsrGpsMessage, double altitude) {
538         double alt = altitude;
539
540         if (unlikely(alt > PUD_ALTITUDE_MAX)) {
541                 alt = PUD_ALTITUDE_MAX;
542         } else if (unlikely(alt < PUD_ALTITUDE_MIN)) {
543                 alt = PUD_ALTITUDE_MIN;
544         }
545
546         alt -= PUD_ALTITUDE_MIN;
547
548         olsrGpsMessage->gpsInfo.alt = lrint(alt);
549 }
550
551 /**
552  Get the speed of the position update message
553
554  @param olsrGpsMessage
555  A pointer to the position update message
556
557  @return
558  The speed in kph
559  */
560 unsigned long getPositionUpdateSpeed(
561                 PudOlsrPositionUpdate * olsrGpsMessage) {
562         return olsrGpsMessage->gpsInfo.speed;
563 }
564
565 /**
566  Set the speed of the position update message
567
568  @param olsrGpsMessage
569  A pointer to the position update message
570  @param speed
571  The speed in kph
572  */
573 void setPositionUpdateSpeed(
574                 PudOlsrPositionUpdate * olsrGpsMessage, double speed) {
575         double spd = speed;
576
577         if (unlikely(speed < 0)) {
578                 spd = 0;
579         } else if (unlikely(speed > PUD_SPEED_MAX)) {
580                 spd = PUD_SPEED_MAX;
581         }
582
583         olsrGpsMessage->gpsInfo.speed = lrint(spd);
584 }
585
586 /**
587  Get the track angle of the position update message
588
589  @param olsrGpsMessage
590  A pointer to the position update message
591
592  @return
593  The track angle in degrees
594  */
595 unsigned long getPositionUpdateTrack(
596                 PudOlsrPositionUpdate * olsrGpsMessage) {
597         return olsrGpsMessage->gpsInfo.track;
598 }
599
600 /**
601  Set the track angle of the position update message
602
603  @param olsrGpsMessage
604  A pointer to the position update message
605  @param track
606  The track angle in degrees
607  */
608 void setPositionUpdateTrack(
609                 PudOlsrPositionUpdate * olsrGpsMessage, double track) {
610         olsrGpsMessage->gpsInfo.track = lrint(track);
611 }
612
613 /**
614  Get the HDOP of the position update message
615
616  @param olsrGpsMessage
617  A pointer to the position update message
618
619  @return
620  The HDOP
621  */
622 double getPositionUpdateHdop(
623                 PudOlsrPositionUpdate * olsrGpsMessage) {
624         return (olsrGpsMessage->gpsInfo.hdop * PUD_HDOP_RESOLUTION);
625 }
626
627 /**
628  Set the HDOP of the position update message
629
630  @param olsrGpsMessage
631  A pointer to the position update message
632  @param hdop
633  The HDOP
634  */
635 void setPositionUpdateHdop(PudOlsrPositionUpdate * olsrGpsMessage,
636                 double hdop) {
637         double hdopInternal = hdop;
638
639         if (unlikely(hdopInternal > PUD_HDOP_MAX)) {
640                 hdopInternal = PUD_HDOP_MAX;
641         }
642
643         olsrGpsMessage->gpsInfo.hdop = lrint(hdopInternal / PUD_HDOP_RESOLUTION);
644 }
645
646 /*
647  * NodeInfo
648  */
649
650 /**
651  Get the nodeIdType of the position update message
652
653  @param ipVersion
654  The IP version (AF_INET or AF_INET6)
655  @param olsrGpsMessage
656  A pointer to the position update message
657
658  @return
659  The nodeIdType
660  */
661 NodeIdType getPositionUpdateNodeIdType(int ipVersion,
662                 PudOlsrPositionUpdate * olsrGpsMessage) {
663         if (getPositionUpdateFlags(olsrGpsMessage) & PUD_FLAGS_ID) {
664                 return olsrGpsMessage->nodeInfo.nodeIdType;
665         }
666
667         return ((ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 : PUD_NODEIDTYPE_IPV6);
668 }
669
670 /**
671  Set the nodeIdType of the position update message
672
673  @param olsrGpsMessage
674  A pointer to the position update message
675  @param nodeIdType
676  The nodeIdType
677  */
678 void setPositionUpdateNodeIdType(
679                 PudOlsrPositionUpdate * olsrGpsMessage, NodeIdType nodeIdType) {
680         olsrGpsMessage->nodeInfo.nodeIdType = nodeIdType;
681 }
682
683 /**
684  Get the nodeId and its size, accounting for nodeId presence
685
686  @param ipVersion
687  The IP version (AF_INET or AF_INET6)
688  @param olsrMessage
689  A pointer to the OLSR message
690  @param nodeId
691  A pointer to the location where a pointer to the nodeId (as contained in the
692  olsrMessage) can be stored
693  @param nodeIdSize
694  A pointer to the location where the number of bytes in the nodeId can be
695  stored
696  */
697 void getPositionUpdateNodeId(int ipVersion, union olsr_message * olsrMessage,
698                 unsigned char ** nodeId, unsigned int * nodeIdSize) {
699         PudOlsrPositionUpdate * olsrGpsMessage = getOlsrMessagePayload(ipVersion,
700                         olsrMessage);
701
702         *nodeId = &olsrGpsMessage->nodeInfo.nodeId;
703
704         switch (getPositionUpdateNodeIdType(ipVersion, olsrGpsMessage)) {
705         case PUD_NODEIDTYPE_MAC: /* hardware address */
706                 *nodeIdSize = PUD_NODEIDTYPE_MAC_BYTES;
707                 break;
708
709         case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
710                 *nodeIdSize = PUD_NODEIDTYPE_MSISDN_BYTES;
711                 break;
712
713         case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
714                 *nodeIdSize = PUD_NODEIDTYPE_TETRA_BYTES;
715                 break;
716
717         case PUD_NODEIDTYPE_DNS: /* DNS name */
718           {
719             unsigned int len = 0;
720             unsigned char * idx = *nodeId;
721             unsigned char * lastPayloadByte = &((unsigned char *)olsrMessage)[getOlsrMessageSize(ipVersion, olsrMessage) - 1];
722             while ((*idx != '\0') && (idx <= lastPayloadByte)) {
723               idx++;
724               len++;
725             }
726             *nodeIdSize = len;
727           }
728                 break;
729
730         case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
731                 *nodeIdSize = PUD_NODEIDTYPE_MMSI_BYTES;
732                 break;
733
734         case PUD_NODEIDTYPE_URN: /* a URN number */
735                 *nodeIdSize = PUD_NODEIDTYPE_URN_BYTES;
736                 break;
737
738         case PUD_NODEIDTYPE_MIP: /* a MIP OID number */
739                 *nodeIdSize = PUD_NODEIDTYPE_MIP_BYTES;
740                 break;
741
742         case PUD_NODEIDTYPE_192:
743                 *nodeIdSize = PUD_NODEIDTYPE_192_BYTES;
744                 break;
745
746         case PUD_NODEIDTYPE_193:
747                 *nodeIdSize = PUD_NODEIDTYPE_193_BYTES;
748                 break;
749
750         case PUD_NODEIDTYPE_194:
751                 *nodeIdSize = PUD_NODEIDTYPE_194_BYTES;
752                 break;
753
754         case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
755         case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
756         default: /* unsupported */
757         {
758                 *nodeId = (unsigned char *) getOlsrMessageOriginator(ipVersion,
759                                 olsrMessage);
760                 *nodeIdSize =
761                                 (ipVersion == AF_INET) ?
762                                                 PUD_NODEIDTYPE_IPV4_BYTES : PUD_NODEIDTYPE_IPV6_BYTES;
763         }
764                 break;
765         }
766
767         return;
768 }
769
770 /**
771  Set the nodeId of the position update message
772
773  @param olsrGpsMessage
774  A pointer to the position update message
775  @param nodeId
776  The nodeId
777  @param nodeIdSize
778  The number of bytes in nodeId
779  @param padWithNullByte
780  When true then an extra '\0' byte will be added at the end
781  */
782 void setPositionUpdateNodeId(
783                 PudOlsrPositionUpdate * olsrGpsMessage, unsigned char * nodeId,
784                 unsigned int nodeIdSize, bool padWithNullByte) {
785         memcpy(&olsrGpsMessage->nodeInfo.nodeId, nodeId, nodeIdSize);
786         if (unlikely(padWithNullByte)) {
787                 (&olsrGpsMessage->nodeInfo.nodeId)[nodeIdSize] = '\0';
788         }
789 }
790
791 /**
792  Convert the node information to the node information for an OLSR message and
793  put it in the PUD message in the OLSR message. Also updates the PUD message
794  smask to signal whether or not an ID is in the message.
795
796  @param ipVersion
797  The IP version (AF_INET or AF_INET6)
798  @param olsrGpsMessage
799  A pointer to the PUD message in the OLSR message
800  @param olsrMessageSize
801  The maximum number of bytes available for the olsrMessage
802  @param nodeIdType
803  The nodeIdType
804  @param nodeId
805  The (configured) nodeId in binary/wireformat representation
806  @param nodeIdLength
807  The number of bytes in the nodeId
808
809  @return
810  The number of bytes written in the PUD message in the OLSR message (for ALL
811  the node information)
812  */
813 size_t setPositionUpdateNodeInfo(int ipVersion,
814                 PudOlsrPositionUpdate * olsrGpsMessage, unsigned int olsrMessageSize,
815                 NodeIdType nodeIdType, unsigned char * nodeId, size_t nodeIdLength) {
816         unsigned int length = 0;
817
818         setPositionUpdateNodeIdType(olsrGpsMessage, nodeIdType);
819         switch (nodeIdType) {
820         case PUD_NODEIDTYPE_MAC: /* hardware address */
821         case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
822         case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
823         case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
824         case PUD_NODEIDTYPE_URN: /* a URN number */
825         case PUD_NODEIDTYPE_MIP: /* a MIP OID number */
826         case PUD_NODEIDTYPE_192:
827         case PUD_NODEIDTYPE_193:
828         case PUD_NODEIDTYPE_194:
829                 length = nodeIdLength;
830                 setPositionUpdateNodeId(olsrGpsMessage, nodeId, nodeIdLength, false);
831                 break;
832
833         case PUD_NODEIDTYPE_DNS: /* DNS name */
834         {
835                 long charsAvailable = olsrMessageSize
836                                 - (PUD_OLSRWIREFORMATSIZE + sizeof(NodeInfo)
837                                                 - sizeof(olsrGpsMessage->nodeInfo.nodeId)) - 1;
838
839                 length = nodeIdLength + 1;
840                 if (unlikely((long) length > charsAvailable)) {
841                         length = charsAvailable;
842                 }
843
844                 // FIXME do not pad with a null byte (compatibility breaking change!)
845                 setPositionUpdateNodeId(olsrGpsMessage, nodeId, length, true);
846         }
847                 break;
848
849         case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
850         case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
851                 /* explicit return: no nodeId information in message */
852                 return 0;
853
854         default: /* unsupported */
855                 /* fallback to IP address */
856                 setPositionUpdateNodeIdType(olsrGpsMessage,
857                                 (ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 :
858                                 PUD_NODEIDTYPE_IPV6);
859
860                 /* explicit return: no nodeId information in message */
861                 return 0;
862         }
863
864         setPositionUpdateFlags(olsrGpsMessage,
865                         getPositionUpdateFlags(olsrGpsMessage) | PUD_FLAGS_ID);
866         return ((sizeof(NodeInfo)
867                         - (sizeof(olsrGpsMessage->nodeInfo.nodeId) /* nodeId placeholder */))
868                         + length);
869 }
870
871 /*
872  * UplinkClusterLeader
873  */
874
875 /**
876  Get the version of the cluster leader message
877
878  @param clusterLeaderMessage
879  A pointer to the cluster leader message
880  @return
881  The version of the cluster leader message
882  */
883 uint8_t getClusterLeaderVersion(
884                 UplinkClusterLeader * clusterLeaderMessage) {
885         return clusterLeaderMessage->version;
886 }
887
888 /**
889  Set the version of the cluster leader message
890
891  @param clusterLeaderMessage
892  A pointer to the cluster leader message
893  @param version
894  The version of the cluster leader message
895  */
896 void setClusterLeaderVersion(
897                 UplinkClusterLeader * clusterLeaderMessage, uint8_t version) {
898         clusterLeaderMessage->version = version;
899 }
900
901 /**
902  Get the originator of a cluster leader message
903
904  @param ipVersion
905  The IP version (AF_INET or AF_INET6)
906  @param clusterLeaderMessage
907  A pointer to the cluster leader message
908  @return
909  A pointer to the originator address
910  */
911 union olsr_ip_addr * getClusterLeaderOriginator(int ipVersion,
912                 UplinkClusterLeader * clusterLeaderMessage) {
913         if (ipVersion == AF_INET) {
914                 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.originator;
915         }
916
917         return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.originator;
918 }
919
920 /**
921  Get the cluster leader of a cluster leader message
922
923  @param ipVersion
924  The IP version (AF_INET or AF_INET6)
925  @param clusterLeaderMessage
926  A pointer to the cluster leader message
927  @return
928  A pointer to the clust leader address
929  */
930 union olsr_ip_addr * getClusterLeaderClusterLeader(int ipVersion,
931                 UplinkClusterLeader * clusterLeaderMessage) {
932         if (ipVersion == AF_INET) {
933                 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.clusterLeader;
934         }
935
936         return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.clusterLeader;
937 }