PUD: move nodeId validation into configuration
[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 node information of an OLSR message to the node information for
143  internal use and set it up in the given buffers.
144
145  @param olsrMessage
146  A pointer to the OLSR message. Used to be able to retrieve the IP address of
147  the sender.
148  @param olsrGpsMessage
149  A pointer to the GPS message in the OLSR message
150  @param nodeId
151  A pointer a variable in which to store the pointer to the buffer in which the
152  nodeId string representation can be found
153  @param nodeIdBuffer
154  A pointer to the buffer in which the nodeId string representation can be
155  written
156  @param nodeIdBufferSize
157  The size of the nodeIdBuffer
158  @param nodeIdTypeString
159  A pointer to the buffer in which the nodeIdType string representation can be
160  written
161  */
162 void getNodeInfoFromOlsr(const union olsr_message *olsrMessage,
163                 PudOlsrWireFormat *olsrGpsMessage, char *nodeIdBuffer,
164                 unsigned int nodeIdBufferSize, const char **nodeId,
165                 char *nodeIdTypeString) {
166         int chars;
167
168         if (olsrGpsMessage->smask & PUD_FLAGS_ID) {
169                 switch (olsrGpsMessage->nodeInfo.nodeIdType) {
170                         case PUD_NODEIDTYPE_MAC: /* hardware address */
171                         {
172                                 unsigned char * hwAddr = &olsrGpsMessage->nodeInfo.nodeId;
173
174                                 assert (IFHWADDRLEN == 6);
175
176                                 chars = snprintf(nodeIdBuffer, nodeIdBufferSize,
177                                                 "%02x:%02x:%02x:%02x:%02x:%02x", hwAddr[0], hwAddr[1],
178                                                 hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]);
179                                 if (likely(chars < (int) nodeIdBufferSize)) {
180                                         nodeIdBuffer[chars] = '\0';
181                                 } else {
182                                         nodeIdBuffer[nodeIdBufferSize - 1] = '\0';
183                                 }
184                                 *nodeId = &nodeIdBuffer[0];
185                         }
186                                 break;
187
188                         case PUD_NODEIDTYPE_MSISDN: /* an MSISDN number */
189                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 7,
190                                                 nodeIdBuffer, nodeIdBufferSize);
191                                 break;
192
193                         case PUD_NODEIDTYPE_TETRA: /* a Tetra number */
194                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 8,
195                                                 nodeIdBuffer, nodeIdBufferSize);
196                                 break;
197
198                         case PUD_NODEIDTYPE_DNS: /* DNS name */
199                                 *nodeId = (char *) &olsrGpsMessage->nodeInfo.nodeId;
200                                 break;
201
202                         case PUD_NODEIDTYPE_192:
203                         case PUD_NODEIDTYPE_193:
204                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 3,
205                                                 nodeIdBuffer, nodeIdBufferSize);
206                                 break;
207
208                         case PUD_NODEIDTYPE_194:
209                                 *nodeId = getNodeIdNumberFromOlsr(olsrGpsMessage, 2,
210                                                 nodeIdBuffer, nodeIdBufferSize);
211                                 break;
212
213                         case PUD_NODEIDTYPE_IPV4: /* IPv4 address */
214                         case PUD_NODEIDTYPE_IPV6: /* IPv6 address */
215                                 goto noId;
216
217                         default: /* unsupported */
218                                 pudError(false,
219                                                 "Reception of unsupported %s %u, using %u",
220                                                 PUD_NODE_ID_TYPE_NAME,
221                                                 olsrGpsMessage->nodeInfo.nodeIdType,
222                                                 ((olsr_cnf->ip_version == AF_INET) ? PUD_NODEIDTYPE_IPV4
223                                                                 : PUD_NODEIDTYPE_IPV6));
224                                 olsrGpsMessage->smask &= ~PUD_FLAGS_ID;
225                                 goto noId;
226                 }
227
228                 /* nodeIdType */
229                 chars = snprintf(nodeIdTypeString, PUD_TX_NODEIDTYPE_DIGITS + 1, "%u",
230                                 olsrGpsMessage->nodeInfo.nodeIdType);
231                 if (likely(chars < PUD_TX_NODEIDTYPE_DIGITS)) {
232                         nodeIdTypeString[chars] = '\0';
233                 } else {
234                         nodeIdTypeString[PUD_TX_NODEIDTYPE_DIGITS] = '\0';
235                 }
236
237                 return;
238         }
239
240         /* message has NO nodeId information */
241         noId: {
242                 const void * addr;
243
244                 /* nodeIdType */
245                 chars = snprintf(&nodeIdTypeString[0], PUD_TX_NODEIDTYPE_DIGITS + 1,
246                                 "%u", ((olsr_cnf->ip_version == AF_INET) ? PUD_NODEIDTYPE_IPV4
247                                 : PUD_NODEIDTYPE_IPV6));
248                 if (likely(chars < PUD_TX_NODEIDTYPE_DIGITS)) {
249                         nodeIdTypeString[chars] = '\0';
250                 } else {
251                         nodeIdTypeString[PUD_TX_NODEIDTYPE_DIGITS] = '\0';
252                 }
253
254                 if (olsr_cnf->ip_version == AF_INET) {
255                         addr = (const void *) &olsrMessage->v4.originator;
256                 } else {
257                         addr = (const void *) &olsrMessage->v6.originator;
258                 }
259
260                 *nodeId = inet_ntop(olsr_cnf->ip_version, addr, nodeIdBuffer,
261                                 nodeIdBufferSize);
262         }
263
264         return;
265 }