1 #include <OlsrdPudWireFormat/wireFormat.h>
9 bool isValidNodeIdType(unsigned long long nodeIdType) {
13 (/* (nodeIdType >= PUD_NODEIDTYPE_GLOBAL_FIRST) && */ (nodeIdType <= PUD_NODEIDTYPE_GLOBAL_LAST)) ||
14 ( (nodeIdType >= PUD_NODEIDTYPE_LOCAL_FIRST ) && (nodeIdType <= PUD_NODEIDTYPE_LOCAL_LAST ))
18 (nodeIdType != PUD_NODEIDTYPE_GAP1)
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)
32 Get the validity time from a message
34 @param validityTimeField
35 A pointer to the validity time field
38 The validity time in seconds
40 unsigned long getValidityTime(uint8_t * validityTimeField) {
41 return PUD_VALIDITY_TIME_FROM_OLSR(*validityTimeField >> 4, *validityTimeField % 16);
45 Set the validity time of the position update message
47 @param validityTimeField
48 A pointer to the validity time field
50 The validity time in seconds
52 void setValidityTime(uint8_t * validityTimeField, unsigned long long validityTime) {
54 unsigned long long lsn = 0;
55 unsigned long long upperBound;
57 upperBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
58 while ((msn < 16) && (validityTime >= upperBound)) {
60 upperBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
64 if (unlikely(validityTime >= upperBound)) {
67 unsigned long lowerBound = PUD_VALIDITY_TIME_FROM_OLSR(msn, 0);
68 unsigned long resolution = (1 << msn);
69 lsn = ((validityTime - lowerBound + (resolution >> 1)) / resolution);
75 *validityTimeField = ((msn << 4) | lsn);
83 Get the type of the uplink message
86 A pointer to the uplink message
88 The type of the uplink message
90 uint8_t getUplinkMessageType(UplinkHeader * uplinkHeader) {
91 return uplinkHeader->type;
95 Set the type of the uplink message
98 A pointer to the uplink message
100 The type of the uplink message
102 void setUplinkMessageType(UplinkHeader * uplinkHeader,
104 uplinkHeader->type = type;
108 Get the length of the uplink message
111 A pointer to the uplink message
113 The length of the uplink message
115 uint16_t getUplinkMessageLength(UplinkHeader * uplinkHeader) {
116 return ntohs(uplinkHeader->length);
120 Set the length of the uplink message
123 A pointer to the uplink message
125 The length of the uplink message
127 void setUplinkMessageLength(UplinkHeader * uplinkHeader,
129 uplinkHeader->length = ntohs(length);
133 Get the IPv6 status of the uplink message
136 A pointer to the uplink message
138 true when the uplink message is sent from an olsrd stack in IPv6 mode, false
141 bool getUplinkMessageIPv6(UplinkHeader * uplinkHeader) {
142 return (uplinkHeader->ipv6 == 1);
146 Set the IPv6 status of the uplink message
149 A pointer to the uplink message
151 The IPv6 status of the uplink message (true when the uplink message is sent
152 from olsrd stack in IPv6 mode, false otherwise)
154 void setUplinkMessageIPv6(UplinkHeader * uplinkHeader,
156 uplinkHeader->ipv6 = ipv6 ? 1 : 0;
160 Set the padding of the uplink message header
163 A pointer to the uplink message
165 The padding of the uplink message header
167 void setUplinkMessagePadding(UplinkHeader * uplinkHeader,
169 uplinkHeader->pad = pad;
177 Determine the size of an OLSR message
182 A pointer to the OLSR message
184 The size of the OLSR message
186 unsigned short getOlsrMessageSize(int ipVersion,
187 union olsr_message * olsrMessage) {
188 if (ipVersion == AF_INET) {
189 return ntohs(olsrMessage->v4.olsr_msgsize);
192 return ntohs(olsrMessage->v6.olsr_msgsize);
196 Get the originator of an OLSR message
199 The IP version (AF_INET or AF_INET6)
201 A pointer to the OLSR message
203 A pointer to the originator address
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;
211 return (union olsr_ip_addr *) &olsrMessage->v6.originator;
215 Get the position update message in an OLSR message
218 The IP version (AF_INET or AF_INET6)
220 A pointer to the OLSR message
222 A pointer to the position update message
224 PudOlsrPositionUpdate * getOlsrMessagePayload(int ipVersion,
225 union olsr_message * olsrMessage) {
226 if (ipVersion == AF_INET) {
227 return (PudOlsrPositionUpdate *) &olsrMessage->v4.message;
230 return (PudOlsrPositionUpdate *) &olsrMessage->v6.message;
234 * PudOlsrPositionUpdate
238 Get the version of the position update message
240 @param olsrGpsMessage
241 A pointer to the position update message
243 The version of the position update message
245 uint8_t getPositionUpdateVersion(
246 PudOlsrPositionUpdate * olsrGpsMessage) {
247 return olsrGpsMessage->version;
251 Set the version of the position update message
253 @param olsrGpsMessage
254 A pointer to the position update message
256 The version of the position update message
258 void setPositionUpdateVersion(
259 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t version) {
260 olsrGpsMessage->version = version;
264 Get the smask of the position update message
266 @param olsrGpsMessage
267 A pointer to the position update message
269 The smask of the position update message
271 uint8_t getPositionUpdateSmask(
272 PudOlsrPositionUpdate * olsrGpsMessage) {
273 return olsrGpsMessage->smask;
277 Set the smask of the position update message
279 @param olsrGpsMessage
280 A pointer to the position update message
282 The smask of the position update message
284 void setPositionUpdateSmask(
285 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t smask) {
286 olsrGpsMessage->smask = smask;
290 Get the flags of the position update message
292 @param olsrGpsMessage
293 A pointer to the position update message
295 The flags of the position update message
297 uint8_t getPositionUpdateFlags(
298 PudOlsrPositionUpdate * olsrGpsMessage) {
299 return olsrGpsMessage->flags;
303 Set the flags of the position update message
305 @param olsrGpsMessage
306 A pointer to the position update message
308 The flags of the position update message
310 void setPositionUpdateFlags(
311 PudOlsrPositionUpdate * olsrGpsMessage, uint8_t flags) {
312 olsrGpsMessage->flags = flags;
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.
323 @param olsrGpsMessage
324 A pointer to the position update message
326 The base date from which to determine the time (number of seconds since Epoch,
329 A pointer to the time structure into which to put the converted time
331 void getPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
332 time_t baseDate, struct tm *nowStruct) {
333 uint32_t olsrTime = olsrGpsMessage->gpsInfo.time;
336 time_t now = baseDate;
337 gmtime_r(&now, nowStruct);
339 secNow = ((nowStruct->tm_hour * 60 * 60) + (nowStruct->tm_min * 60)
340 + nowStruct->tm_sec);
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);
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);
360 nowStruct->tm_hour = ((olsrTime % (24 * 60 * 60)) / 3600);
361 nowStruct->tm_min = ((olsrTime % (60 * 60)) / 60);
362 nowStruct->tm_sec = (olsrTime % 60);
366 Set the time of the position update message (the number of seconds after
369 @param olsrGpsMessage
370 A pointer to the position update message
378 void setPositionUpdateTime(PudOlsrPositionUpdate * olsrGpsMessage,
379 int hour, int min, int sec) {
380 olsrGpsMessage->gpsInfo.time = ((hour * 60 * 60) + (min * 60) + sec);
384 Get the latitude of the position update message
386 @param olsrGpsMessage
387 A pointer to the position update message
390 The latitude converted to degrees: [-90, 90>
392 double getPositionUpdateLatitude(
393 PudOlsrPositionUpdate * olsrGpsMessage) {
394 uint32_t olsrLat = olsrGpsMessage->gpsInfo.lat;
395 double lat = (double) olsrLat;
397 /* lat is in [0, 2^LATITUDE_BITS> */
399 /* take half of the rounding error */
402 lat /= (double) (1 << PUD_LATITUDE_BITS);
403 /* lat is now in [0, 1> */
406 /* lat is now in [-0.5, 0.5> */
409 /* lat is now in [-90, 90> */
415 Set the latitude of the position update message
417 @param olsrGpsMessage
418 A pointer to the position update message
420 The latitude in degrees: [-90, 90]
422 void setPositionUpdateLatitude(
423 PudOlsrPositionUpdate * olsrGpsMessage, double latitude) {
424 double lat = latitude;
426 /* lat is in [-90, 90] */
427 assert(lat >= -90.0);
431 /* lat is now in [-0.5, 0.5] */
434 /* lat is now in [0, 1] */
436 lat *= (double) (1 << PUD_LATITUDE_BITS);
437 /* lat is now in [0, LATITUDE_BITS] */
440 if (unlikely(lat > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
441 lat = (double) ((1 << PUD_LATITUDE_BITS) - 1);
443 /* lat is now in [0, 2^LATITUDE_BITS> */
445 olsrGpsMessage->gpsInfo.lat = lrint(lat);
449 Get the longitude of the position update message
451 @param olsrGpsMessage
452 A pointer to the position update message
455 The longitude converted to degrees: [-180, 180>
457 double getPositionUpdateLongitude(
458 PudOlsrPositionUpdate * olsrGpsMessage) {
459 uint32_t olsrLon = olsrGpsMessage->gpsInfo.lon;
460 double lon = (double) olsrLon;
462 /* lon is in [0, 2^LONGITUDE_BITS> */
464 /* take half of the rounding error */
467 lon /= (1 << PUD_LONGITUDE_BITS);
468 /* lon is now in [0, 1> */
471 /* lon is now in [-0.5, 0.5> */
474 /* lon is now in [-180, 180> */
480 Set the longitude of the position update message
482 @param olsrGpsMessage
483 A pointer to the position update message
485 The longitude in degrees: [-90, 90]
487 void setPositionUpdateLongitude(
488 PudOlsrPositionUpdate * olsrGpsMessage, double longitude) {
489 double lon = longitude;
491 /* lon is in [-180, 180] */
492 assert(lon >= -180.0);
493 assert(lon <= 180.0);
496 /* lon is now in [-0.5, 0.5] */
499 /* lon is now in [0, 1] */
501 lon *= (double) (1 << PUD_LONGITUDE_BITS);
502 /* lon is now in [0, LONGITUDE_BITS] */
505 if (unlikely(lon > (double)((1 << PUD_LATITUDE_BITS) - 1))) {
506 lon = (double) ((1 << PUD_LATITUDE_BITS) - 1);
509 /* lon is now in [0, 2^LONGITUDE_BITS> */
511 olsrGpsMessage->gpsInfo.lon = lrint(lon);
515 Get the altitude of the position update message
517 @param olsrGpsMessage
518 A pointer to the position update message
521 The altitude in meters
523 long getPositionUpdateAltitude(
524 PudOlsrPositionUpdate * olsrGpsMessage) {
525 return ((long) olsrGpsMessage->gpsInfo.alt + PUD_ALTITUDE_MIN);
529 Set the altitude of the position update message
531 @param olsrGpsMessage
532 A pointer to the position update message
534 The altitude in meters
536 void setPositionUpdateAltitude(
537 PudOlsrPositionUpdate * olsrGpsMessage, double altitude) {
538 double alt = altitude;
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;
546 alt -= PUD_ALTITUDE_MIN;
548 olsrGpsMessage->gpsInfo.alt = lrint(alt);
552 Get the speed of the position update message
554 @param olsrGpsMessage
555 A pointer to the position update message
560 unsigned long getPositionUpdateSpeed(
561 PudOlsrPositionUpdate * olsrGpsMessage) {
562 return olsrGpsMessage->gpsInfo.speed;
566 Set the speed of the position update message
568 @param olsrGpsMessage
569 A pointer to the position update message
573 void setPositionUpdateSpeed(
574 PudOlsrPositionUpdate * olsrGpsMessage, double speed) {
577 if (unlikely(speed < 0)) {
579 } else if (unlikely(speed > PUD_SPEED_MAX)) {
583 olsrGpsMessage->gpsInfo.speed = lrint(spd);
587 Get the track angle of the position update message
589 @param olsrGpsMessage
590 A pointer to the position update message
593 The track angle in degrees
595 unsigned long getPositionUpdateTrack(
596 PudOlsrPositionUpdate * olsrGpsMessage) {
597 return olsrGpsMessage->gpsInfo.track;
601 Set the track angle of the position update message
603 @param olsrGpsMessage
604 A pointer to the position update message
606 The track angle in degrees
608 void setPositionUpdateTrack(
609 PudOlsrPositionUpdate * olsrGpsMessage, double track) {
610 olsrGpsMessage->gpsInfo.track = lrint(track);
614 Get the HDOP of the position update message
616 @param olsrGpsMessage
617 A pointer to the position update message
622 double getPositionUpdateHdop(
623 PudOlsrPositionUpdate * olsrGpsMessage) {
624 return (olsrGpsMessage->gpsInfo.hdop * PUD_HDOP_RESOLUTION);
628 Set the HDOP of the position update message
630 @param olsrGpsMessage
631 A pointer to the position update message
635 void setPositionUpdateHdop(PudOlsrPositionUpdate * olsrGpsMessage,
637 double hdopInternal = hdop;
639 if (unlikely(hdopInternal > PUD_HDOP_MAX)) {
640 hdopInternal = PUD_HDOP_MAX;
643 olsrGpsMessage->gpsInfo.hdop = lrint(hdopInternal / PUD_HDOP_RESOLUTION);
651 Get the nodeIdType of the position update message
654 The IP version (AF_INET or AF_INET6)
655 @param olsrGpsMessage
656 A pointer to the position update message
661 NodeIdType getPositionUpdateNodeIdType(int ipVersion,
662 PudOlsrPositionUpdate * olsrGpsMessage) {
663 if (getPositionUpdateFlags(olsrGpsMessage) & PUD_FLAGS_ID) {
664 return olsrGpsMessage->nodeInfo.nodeIdType;
667 return ((ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 : PUD_NODEIDTYPE_IPV6);
671 Set the nodeIdType of the position update message
673 @param olsrGpsMessage
674 A pointer to the position update message
678 void setPositionUpdateNodeIdType(
679 PudOlsrPositionUpdate * olsrGpsMessage, NodeIdType nodeIdType) {
680 olsrGpsMessage->nodeInfo.nodeIdType = nodeIdType;
684 Get the nodeId and its size, accounting for nodeId presence
687 The IP version (AF_INET or AF_INET6)
689 A pointer to the OLSR message
691 A pointer to the location where a pointer to the nodeId (as contained in the
692 olsrMessage) can be stored
694 A pointer to the location where the number of bytes in the nodeId can be
697 void getPositionUpdateNodeId(int ipVersion, union olsr_message * olsrMessage,
698 unsigned char ** nodeId, unsigned int * nodeIdSize) {
699 PudOlsrPositionUpdate * olsrGpsMessage = getOlsrMessagePayload(ipVersion,
702 *nodeId = &olsrGpsMessage->nodeInfo.nodeId;
704 switch (getPositionUpdateNodeIdType(ipVersion, olsrGpsMessage)) {
705 case PUD_NODEIDTYPE_MAC: /* hardware address */
706 *nodeIdSize = PUD_NODEIDTYPE_MAC_BYTES;
709 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
710 *nodeIdSize = PUD_NODEIDTYPE_MSISDN_BYTES;
713 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
714 *nodeIdSize = PUD_NODEIDTYPE_TETRA_BYTES;
717 case PUD_NODEIDTYPE_DNS: /* DNS name */
718 *nodeIdSize = strlen((char *) *nodeId);
719 /* FIXME for no '\0' at the end, need to scan from the end until
720 * encountering a non-zero byte: end of string address and
721 * subtract the string start address */
724 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
725 *nodeIdSize = PUD_NODEIDTYPE_MMSI_BYTES;
728 case PUD_NODEIDTYPE_URN: /* a URN number */
729 *nodeIdSize = PUD_NODEIDTYPE_URN_BYTES;
732 case PUD_NODEIDTYPE_192:
733 *nodeIdSize = PUD_NODEIDTYPE_192_BYTES;
736 case PUD_NODEIDTYPE_193:
737 *nodeIdSize = PUD_NODEIDTYPE_193_BYTES;
740 case PUD_NODEIDTYPE_194:
741 *nodeIdSize = PUD_NODEIDTYPE_194_BYTES;
744 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
745 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
746 default: /* unsupported */
748 *nodeId = (unsigned char *) getOlsrMessageOriginator(ipVersion,
751 (ipVersion == AF_INET) ?
752 PUD_NODEIDTYPE_IPV4_BYTES : PUD_NODEIDTYPE_IPV6_BYTES;
761 Set the nodeId of the position update message
763 @param olsrGpsMessage
764 A pointer to the position update message
768 The number of bytes in nodeId
769 @param padWithNullByte
770 When true then an extra '\0' byte will be added at the end
772 void setPositionUpdateNodeId(
773 PudOlsrPositionUpdate * olsrGpsMessage, unsigned char * nodeId,
774 unsigned int nodeIdSize, bool padWithNullByte) {
775 memcpy(&olsrGpsMessage->nodeInfo.nodeId, nodeId, nodeIdSize);
776 if (unlikely(padWithNullByte)) {
777 (&olsrGpsMessage->nodeInfo.nodeId)[nodeIdSize] = '\0';
782 Convert the node information to the node information for an OLSR message and
783 put it in the PUD message in the OLSR message. Also updates the PUD message
787 The IP version (AF_INET or AF_INET6)
788 @param olsrGpsMessage
789 A pointer to the PUD message in the OLSR message
790 @param olsrMessageSize
791 The maximum number of bytes available for the olsrMessage
795 The (configured) nodeId in binary/wireformat representation
797 The number of bytes in the nodeId
800 The number of bytes written in the PUD message in the OLSR message (for ALL
801 the node information)
803 size_t setPositionUpdateNodeInfo(int ipVersion,
804 PudOlsrPositionUpdate * olsrGpsMessage, unsigned int olsrMessageSize,
805 NodeIdType nodeIdType, unsigned char * nodeId, size_t nodeIdLength) {
806 unsigned int length = 0;
808 setPositionUpdateNodeIdType(olsrGpsMessage, nodeIdType);
809 switch (nodeIdType) {
810 case PUD_NODEIDTYPE_MAC: /* hardware address */
811 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
812 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
813 case PUD_NODEIDTYPE_MMSI: /* an AIS MMSI number */
814 case PUD_NODEIDTYPE_URN: /* a URN number */
815 case PUD_NODEIDTYPE_192:
816 case PUD_NODEIDTYPE_193:
817 case PUD_NODEIDTYPE_194:
818 length = nodeIdLength;
819 setPositionUpdateNodeId(olsrGpsMessage, nodeId, nodeIdLength, false);
822 case PUD_NODEIDTYPE_DNS: /* DNS name */
824 long charsAvailable = olsrMessageSize
825 - (PUD_OLSRWIREFORMATSIZE + sizeof(NodeInfo)
826 - sizeof(olsrGpsMessage->nodeInfo.nodeId)) - 1;
828 length = nodeIdLength + 1;
829 if (unlikely((long) length > charsAvailable)) {
830 length = charsAvailable;
833 setPositionUpdateNodeId(olsrGpsMessage, nodeId, length, true);
837 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
838 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
839 /* explicit return: no nodeId information in message */
842 default: /* unsupported */
843 /* fallback to IP address */
844 setPositionUpdateNodeIdType(olsrGpsMessage,
845 (ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4 :
846 PUD_NODEIDTYPE_IPV6);
848 /* explicit return: no nodeId information in message */
852 setPositionUpdateFlags(olsrGpsMessage,
853 getPositionUpdateFlags(olsrGpsMessage) | PUD_FLAGS_ID);
854 return ((sizeof(NodeInfo)
855 - (sizeof(olsrGpsMessage->nodeInfo.nodeId) /* nodeId placeholder */))
860 * UplinkClusterLeader
864 Get the version of the cluster leader message
866 @param clusterLeaderMessage
867 A pointer to the cluster leader message
869 The version of the cluster leader message
871 uint8_t getClusterLeaderVersion(
872 UplinkClusterLeader * clusterLeaderMessage) {
873 return clusterLeaderMessage->version;
877 Set the version of the cluster leader message
879 @param clusterLeaderMessage
880 A pointer to the cluster leader message
882 The version of the cluster leader message
884 void setClusterLeaderVersion(
885 UplinkClusterLeader * clusterLeaderMessage, uint8_t version) {
886 clusterLeaderMessage->version = version;
890 Get the originator of a cluster leader message
893 The IP version (AF_INET or AF_INET6)
894 @param clusterLeaderMessage
895 A pointer to the cluster leader message
897 A pointer to the originator address
899 union olsr_ip_addr * getClusterLeaderOriginator(int ipVersion,
900 UplinkClusterLeader * clusterLeaderMessage) {
901 if (ipVersion == AF_INET) {
902 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.originator;
905 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.originator;
909 Get the cluster leader of a cluster leader message
912 The IP version (AF_INET or AF_INET6)
913 @param clusterLeaderMessage
914 A pointer to the cluster leader message
916 A pointer to the clust leader address
918 union olsr_ip_addr * getClusterLeaderClusterLeader(int ipVersion,
919 UplinkClusterLeader * clusterLeaderMessage) {
920 if (ipVersion == AF_INET) {
921 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v4.clusterLeader;
924 return (union olsr_ip_addr *) &clusterLeaderMessage->leader.v6.clusterLeader;