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