PUD: update 2 error reports
[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,"
86                                         " falling back to IP address", PUD_NODE_ID_TYPE_NAME,
87                                         nodeIdTypeNumber);
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         olsrGpsMessage = getOlsrMessagePayload(ipVersion, olsrMessage);
175
176         if (olsrGpsMessage->smask & PUD_FLAGS_ID) {
177                 switch (olsrGpsMessage->nodeInfo.nodeIdType) {
178                         case PUD_NODEIDTYPE_MAC: /* hardware address */
179                         {
180                                 unsigned char * hwAddr = &olsrGpsMessage->nodeInfo.nodeId;
181
182                                 assert (IFHWADDRLEN == 6);
183
184                                 chars = snprintf(nodeIdBuffer, nodeIdBufferSize,
185                                                 "%02x:%02x:%02x:%02x:%02x:%02x", hwAddr[0], hwAddr[1],
186                                                 hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]);
187                                 if (likely(chars < (int) nodeIdBufferSize)) {
188                                         nodeIdBuffer[chars] = '\0';
189                                 } else {
190                                         nodeIdBuffer[nodeIdBufferSize - 1] = '\0';
191                                 }
192                                 *nodeId = &nodeIdBuffer[0];
193                         }
194                                 break;
195
196                         case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
197                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 7,
198                                                 nodeIdBuffer, nodeIdBufferSize);
199                                 break;
200
201                         case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
202                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 8,
203                                                 nodeIdBuffer, nodeIdBufferSize);
204                                 break;
205
206                         case PUD_NODEIDTYPE_DNS: /* DNS name */
207                                 *nodeId = (char *) &olsrGpsMessage->nodeInfo.nodeId;
208                                 break;
209
210                         case PUD_NODEIDTYPE_192:
211                         case PUD_NODEIDTYPE_193:
212                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 3,
213                                                 nodeIdBuffer, nodeIdBufferSize);
214                                 break;
215
216                         case PUD_NODEIDTYPE_194:
217                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 2,
218                                                 nodeIdBuffer, nodeIdBufferSize);
219                                 break;
220
221                         case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
222                         case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
223                                 goto noId;
224
225                         default: /* unsupported */
226                                 pudError(false, "Reception of unsupported %s %u,"
227                                                 " falling back to IP address", PUD_NODE_ID_TYPE_NAME,
228                                                 olsrGpsMessage->nodeInfo.nodeIdType);
229                                 olsrGpsMessage->smask &= ~PUD_FLAGS_ID;
230                                 goto noId;
231                 }
232
233                 return;
234         }
235
236         /* message has NO nodeId information */
237         noId: {
238                 void * addr = getOlsrMessageOriginator(ipVersion, olsrMessage);
239                 *nodeId = inet_ntop(ipVersion, addr, nodeIdBuffer, nodeIdBufferSize);
240         }
241
242         return;
243 }
244
245 /**
246  Convert the nodeIdType of an OLSR message into a string.
247
248  @param ipVersion
249  The ip version, either AF_INET or AF_INET6
250  @param olsrMessage
251  A pointer to the OLSR message. Used to be able to retrieve the IP address of
252  the sender.
253  @param nodeIdTypeBuffer
254  A pointer to the buffer in which the nodeIdType string representation is
255  written (the buffer needs to be at least PUD_TX_NODEIDTYPE_DIGITS + 1 bytes).
256  When NULL then the nodeIdType string is not written.
257  @param nodeIdTypeBufferSize
258  The size of the nodeIdTypeBuffer
259  */
260 void getNodeTypeStringFromOlsr(int ipVersion, union olsr_message * olsrMessage,
261                 char * nodeIdTypeBuffer, int nodeIdTypeBufferSize) {
262         int chars;
263
264         if (unlikely(!nodeIdTypeBuffer || (nodeIdTypeBufferSize == 0))) {
265                 return;
266         }
267
268         assert(nodeIdTypeBufferSize >= (PUD_TX_NODEIDTYPE_DIGITS + 1));
269
270         /* message has NO nodeId information */
271         chars = snprintf(&nodeIdTypeBuffer[0], nodeIdTypeBufferSize, "%u",
272                         getNodeIdType(ipVersion, olsrMessage));
273         if (likely(chars < nodeIdTypeBufferSize)) {
274                 nodeIdTypeBuffer[chars] = '\0';
275         } else {
276                 nodeIdTypeBuffer[nodeIdTypeBufferSize] = '\0';
277         }
278
279         return;
280 }