256c6a5214ccea0e6cc63cb72cedd588f86e43b3
[olsrd.git] / lib / pud / src / nodeIdConversion.c
1 #include "nodeIdConversion.h"
2
3 /* Plugin includes */
4 #include "pud.h"
5 #include "configuration.h"
6 #include "networkInterfaces.h"
7 #include "compiler.h"
8
9 /* OLSR includes */
10
11 /* System includes */
12 #include <assert.h>
13 #include <arpa/inet.h>
14 #include <nmea/util.h>
15 #include <net/if.h>
16
17 /* ************************************************************************
18  * Node Information
19  * ************************************************************************ */
20
21 /**
22  Convert the node information to the node information for an OLSR message and
23  put it in the PUD message in the OLSR message. Also updates the PUD message
24  smask.
25
26  @param olsrGpsMessage
27  A pointer to the PUD message in the OLSR message
28  @param olsrMessageSize
29  The maximum number of bytes available for the olsrMessage
30
31  @return
32  The number of bytes written in the PUD message in the OLSR message (for ALL
33  the node information)
34  */
35 size_t setupNodeInfoForOlsr(PudOlsrWireFormat * olsrGpsMessage,
36                 unsigned int olsrMessageSize) {
37         NodeIdType nodeIdTypeNumber = getNodeIdTypeNumber();
38         unsigned char * buffer;
39         unsigned int length = 0;
40
41         olsrGpsMessage->nodeInfo.nodeIdType = nodeIdTypeNumber;
42         switch (nodeIdTypeNumber) {
43                 case PUD_NODEIDTYPE_MAC: /* hardware address */
44                         /* handled when the message is actually sent into OLSR, in the
45                          * pre-transmit hook */
46                         length = IFHWADDRLEN;
47                         break;
48
49                 case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
50                 case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
51                 case PUD_NODEIDTYPE_192:
52                 case PUD_NODEIDTYPE_193:
53                 case PUD_NODEIDTYPE_194:
54                         getNodeIdNumberForOlsrCache(&buffer, &length);
55                         memcpy(&olsrGpsMessage->nodeInfo.nodeId, buffer, length);
56                         break;
57
58                 case PUD_NODEIDTYPE_DNS: /* DNS name */
59                 {
60                         size_t nodeIdLength;
61                         unsigned char * nodeId = getNodeIdWithLength(&nodeIdLength);
62                         long charsAvailable = olsrMessageSize - (PUD_OLSRWIREFORMATSIZE
63                                         + sizeof(NodeInfo)
64                                         - sizeof(olsrGpsMessage->nodeInfo.nodeId)) - 1;
65
66                         length = nodeIdLength + 1;
67                         if (unlikely((long) length > charsAvailable)) {
68                                 length = charsAvailable;
69                                 pudError(false,
70                                                 "nodeId too long, truncated after %ld characters",
71                                                 charsAvailable);
72                         }
73
74                         memcpy(&olsrGpsMessage->nodeInfo.nodeId, nodeId, length);
75                         (&olsrGpsMessage->nodeInfo.nodeId)[length] = '\0';
76                 }
77                         break;
78
79                 case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
80                 case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
81                         /* explicit return: no nodeId information in message */
82                         return 0;
83
84                 default: /* unsupported */
85                         pudError(false, "Configuration of unsupported %s %u, using %u",
86                                         PUD_NODE_ID_TYPE_NAME, nodeIdTypeNumber,
87                                         ((olsr_cnf->ip_version == AF_INET) ? PUD_NODEIDTYPE_IPV4
88                                                         : PUD_NODEIDTYPE_IPV6));
89
90                         /* fallback to IP address */
91                         olsrGpsMessage->nodeInfo.nodeIdType = (olsr_cnf->ip_version
92                                         == AF_INET) ? PUD_NODEIDTYPE_IPV4 : PUD_NODEIDTYPE_IPV6;
93
94                         /* explicit return: no nodeId information in message */
95                         return 0;
96         }
97
98         olsrGpsMessage->smask |= PUD_FLAGS_ID;
99         return ((sizeof(NodeInfo)
100                         - (sizeof(olsrGpsMessage->nodeInfo.nodeId) /* nodeId placeholder */))
101                         + length);
102 }
103
104 /**
105  Get a nodeId number (in string representation), using a certain number of
106  bytes, from the message of an OLSR message.
107
108  @param olsrGpsMessage
109  A pointer to the OLSR message
110  @param bytes
111  The number of bytes used by the number
112  @param nodeIdBuffer
113  The buffer in which to place the nodeId number in string representation
114  @param nodeIdBufferSize
115  The size of the buffer
116
117  @return
118  A pointer to the nodeId string representation (&nodeIdBuffer[0])
119  */
120 static char *getNodeIdNumberFromOlsr(PudOlsrWireFormat * olsrGpsMessage,
121                 unsigned int bytes, char *nodeIdBuffer, socklen_t nodeIdBufferSize) {
122         unsigned char * nodeId = &(olsrGpsMessage->nodeInfo.nodeId);
123         unsigned long long val = 0;
124         unsigned int i = 0;
125         int chars;
126
127         while (i < bytes) {
128                 val <<= 8;
129                 val += nodeId[i];
130                 i++;
131         }
132
133         chars = snprintf(nodeIdBuffer, nodeIdBufferSize, "%llu", val);
134         if (likely(chars < (int) nodeIdBufferSize)) {
135                 nodeIdBuffer[chars] = '\0';
136         } else {
137                 nodeIdBuffer[nodeIdBufferSize] = '\0';
138         }
139         return &nodeIdBuffer[0];
140 }
141
142 /**
143  Convert the nodeId of an OLSR message into a string.
144
145  @param ipVersion
146  The ip version, either AF_INET or AF_INET6
147  @param olsrMessage
148  A pointer to the OLSR message. Used to be able to retrieve the IP address of
149  the sender.
150  @param nodeId
151  A pointer to a variable in which to store the pointer to the buffer in which
152  the nodeId string representation is written (the buffer needs to be at least
153  PUD_TX_NODEIDTYPE_DIGITS + 1 bytes). Not written to when nodeIdBuffer or
154  nodeId is NULL or when nodeIdBufferSize is zero. Can point to nodeIdBuffer
155  or straight into the olsrMessage
156  @param nodeIdBuffer
157  A pointer to the buffer in which the nodeId string representation can be
158  written. Not written to when nodeIdBuffer or nodeId is NULL or when
159  nodeIdBufferSize is zero.
160  @param nodeIdBufferSize
161  The size of the nodeIdBuffer. When zero then nodeIdBuffer and nodeId are not
162  written to.
163  */
164 void getNodeIdStringFromOlsr(int ipVersion, union olsr_message *olsrMessage,
165                 const char **nodeId, char *nodeIdBuffer, unsigned int nodeIdBufferSize) {
166         PudOlsrWireFormat * olsrGpsMessage;
167         int chars;
168
169         if (unlikely(!nodeIdBuffer || (nodeIdBufferSize == 0) || !nodeId)) {
170                 return;
171         }
172
173         assert (nodeIdBufferSize >= (PUD_TX_NODEID_BUFFERSIZE + 1));
174
175         olsrGpsMessage = getOlsrMessagePayload(ipVersion, olsrMessage);
176
177         if (olsrGpsMessage->smask & PUD_FLAGS_ID) {
178                 switch (olsrGpsMessage->nodeInfo.nodeIdType) {
179                         case PUD_NODEIDTYPE_MAC: /* hardware address */
180                         {
181                                 unsigned char * hwAddr = &olsrGpsMessage->nodeInfo.nodeId;
182
183                                 assert (IFHWADDRLEN == 6);
184
185                                 chars = snprintf(nodeIdBuffer, nodeIdBufferSize,
186                                                 "%02x:%02x:%02x:%02x:%02x:%02x", hwAddr[0], hwAddr[1],
187                                                 hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]);
188                                 if (likely(chars < (int) nodeIdBufferSize)) {
189                                         nodeIdBuffer[chars] = '\0';
190                                 } else {
191                                         nodeIdBuffer[nodeIdBufferSize - 1] = '\0';
192                                 }
193                                 *nodeId = &nodeIdBuffer[0];
194                         }
195                                 break;
196
197                         case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
198                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 7,
199                                                 nodeIdBuffer, nodeIdBufferSize);
200                                 break;
201
202                         case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
203                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 8,
204                                                 nodeIdBuffer, nodeIdBufferSize);
205                                 break;
206
207                         case PUD_NODEIDTYPE_DNS: /* DNS name */
208                                 *nodeId = (char *) &olsrGpsMessage->nodeInfo.nodeId;
209                                 break;
210
211                         case PUD_NODEIDTYPE_192:
212                         case PUD_NODEIDTYPE_193:
213                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 3,
214                                                 nodeIdBuffer, nodeIdBufferSize);
215                                 break;
216
217                         case PUD_NODEIDTYPE_194:
218                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 2,
219                                                 nodeIdBuffer, nodeIdBufferSize);
220                                 break;
221
222                         case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
223                         case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
224                                 goto noId;
225
226                         default: /* unsupported */
227                                 pudError(false,
228                                                 "Reception of unsupported %s %u, using %u",
229                                                 PUD_NODE_ID_TYPE_NAME,
230                                                 olsrGpsMessage->nodeInfo.nodeIdType,
231                                                 ((ipVersion == AF_INET) ? PUD_NODEIDTYPE_IPV4
232                                                                 : PUD_NODEIDTYPE_IPV6));
233                                 olsrGpsMessage->smask &= ~PUD_FLAGS_ID;
234                                 goto noId;
235                 }
236
237                 return;
238         }
239
240         /* message has NO nodeId information */
241         noId: {
242                 void * addr = getOlsrMessageOriginator(ipVersion, olsrMessage);
243                 *nodeId = inet_ntop(ipVersion, addr, nodeIdBuffer, nodeIdBufferSize);
244         }
245
246         return;
247 }
248
249 /**
250  Convert the nodeIdType of an OLSR message into a string.
251
252  @param ipVersion
253  The ip version, either AF_INET or AF_INET6
254  @param olsrMessage
255  A pointer to the OLSR message. Used to be able to retrieve the IP address of
256  the sender.
257  @param nodeIdTypeBuffer
258  A pointer to the buffer in which the nodeIdType string representation is
259  written (the buffer needs to be at least PUD_TX_NODEIDTYPE_DIGITS + 1 bytes).
260  When NULL then the nodeIdType string is not written.
261  @param nodeIdTypeBufferSize
262  The size of the nodeIdTypeBuffer
263  */
264 void getNodeTypeStringFromOlsr(int ipVersion, union olsr_message * olsrMessage,
265                 char * nodeIdTypeBuffer, int nodeIdTypeBufferSize) {
266         int chars;
267
268         if (unlikely(!nodeIdTypeBuffer || (nodeIdTypeBufferSize == 0))) {
269                 return;
270         }
271
272         assert(nodeIdTypeBufferSize >= (PUD_TX_NODEIDTYPE_DIGITS + 1));
273
274         /* message has NO nodeId information */
275         chars = snprintf(&nodeIdTypeBuffer[0], nodeIdTypeBufferSize, "%u",
276                         getNodeIdType(ipVersion, olsrMessage));
277         if (likely(chars < nodeIdTypeBufferSize)) {
278                 nodeIdTypeBuffer[chars] = '\0';
279         } else {
280                 nodeIdTypeBuffer[nodeIdTypeBufferSize] = '\0';
281         }
282
283         return;
284 }