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