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