replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingutility.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include "routingutility.h"
24 #include "routingmanager.h"
25 #include "oic_malloc.h"
26 #include "include/logger.h"
27
28 /**
29  * Logging tag for module name.
30  */
31 #define TAG "OIC_RM_UTIL"
32
33 /**
34  * Tag for printing the logs of forwarding the packet.
35  */
36 #define RM_TAG "OIC_RM_RAP"
37
38 /**
39  * Default routing option data length is 1 byte with any of the following values.
40  * 00 - source and destination address is not present.
41  * 01 - source and destination address is present with message type as ACK.
42  * 10 - source and destination address is present with message type as RESET.
43  * 11 - source and destination address is present with message type as NORMAL.
44  */
45 #define DEFAULT_ROUTE_OPTION_LEN 1
46
47 /**
48  * Minimum routing option data length is
49  * Msg Type(1 bytes) + length of src address(1byte) + length of destination address(1byte) +
50  * Seq Num(2bytes)
51  */
52 #define MIN_ROUTE_OPTION_LEN 5
53
54 /**
55  * Acknowledge message type is denoted as 01000000
56  */
57 #define ACK_MESSAGE_TYPE (1 << 6)
58
59 /**
60  * Reset message type is denoted as 10000000
61  */
62 #define RST_MESSAGE_TYPE (1 << 7)
63
64 /**
65  * Normal message type is denoted as 11000000
66  */
67 #define NORMAL_MESSAGE_TYPE (3 << 6)
68
69 /**
70  * Stack mode.
71  */
72 static OCMode g_rmStackMode = OC_CLIENT;
73
74 void RMSetStackMode(OCMode mode)
75 {
76     g_rmStackMode = mode;
77 }
78
79 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
80 OCStackResult RMAddInfo(const char *destination, void *message, bool isRequest,
81                         bool *doPost)
82 {
83     RM_NULL_CHECK_WITH_RET(message, TAG, "options");
84
85     CAHeaderOption_t **options = NULL;
86     uint8_t *numOptions = NULL;
87
88     if (isRequest)
89     {
90         CARequestInfo_t *requestMsg = message;
91         options = &(requestMsg->info.options);
92         RM_NULL_CHECK_WITH_RET(options, TAG, "options");
93         numOptions = &(requestMsg->info.numOptions);
94         RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
95     }
96     else
97     {
98         CAResponseInfo_t *respMsg = message;
99         if ('\0' == destination[0] && (CA_EMPTY == respMsg->result))
100         {
101             OIC_LOG(DEBUG, TAG, "Response is for an Endpoint, No need to add the routing Option");
102             return OC_STACK_OK;
103         }
104         options = &(respMsg->info.options);
105         RM_NULL_CHECK_WITH_RET(options, TAG, "options");
106         numOptions = &(respMsg->info.numOptions);
107         RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
108     }
109
110
111     CAHeaderOption_t *optionPtr = NULL;
112     int8_t index = -1;
113
114     RMGetRouteOptionIndex(*options, *numOptions, &index);
115
116     if (-1 < index)
117     {
118         OIC_LOG(INFO, TAG, "Route option is present");
119         optionPtr = *options;
120     }
121     else
122     {
123         OIC_LOG(INFO, TAG, "Route option is not present");
124         index = *numOptions;
125         optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
126         if (!optionPtr)
127         {
128             OIC_LOG(ERROR, TAG, "OICCalloc failed");
129             return OC_STACK_NO_MEMORY;
130         }
131
132         memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
133     }
134
135     OCStackResult res = OC_STACK_OK;
136     RMRouteOption_t routeOption = {.destGw = 0};
137     if (*numOptions != index)
138     {
139         OIC_LOG(INFO, TAG, "Route option is already present");
140         res = RMParseRouteOption(&optionPtr[index], &routeOption);
141         if (OC_STACK_OK != res)
142         {
143             OIC_LOG(ERROR, TAG, "RMParseRouteOption failed");
144             return OC_STACK_ERROR;
145         }
146     }
147
148     if (!isRequest)
149     {
150         CAResponseInfo_t *respMsg = message;
151         if (CA_EMPTY == respMsg->result && CA_MSG_ACKNOWLEDGE == respMsg->info.type)
152         {
153             OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH ACKNOWLEDGEMENT");
154             routeOption.msgType = ACK;
155             if (OC_SERVER == g_rmStackMode)
156             {
157                 OIC_LOG(DEBUG, TAG, "This is server mode");
158                 // Send the Empty message in the response with adding the MSGType in Route option.
159                 respMsg->info.type = CA_MSG_NONCONFIRM;
160                 respMsg->result = CA_CONTENT;
161             }
162             else
163             {
164                 OIC_LOG(DEBUG, TAG, "Send a POST request");
165                 if (NULL != doPost)
166                 {
167                     *doPost = true;
168                 }
169             }
170         }
171         else if (CA_EMPTY == respMsg->result && CA_MSG_RESET == respMsg->info.type)
172         {
173             OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH RESET");
174             routeOption.msgType = RST;
175             respMsg->info.type = CA_MSG_NONCONFIRM;
176             respMsg->result = CA_CONTENT;
177         }
178     }
179
180     if(destination)
181     {
182         memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
183         memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
184                sizeof(routeOption.destEp));
185     }
186
187 #ifdef ROUTING_GATEWAY
188     // A gateway is supposed to add its ID as source.
189     uint32_t gatewayId = RMGetGatewayId();
190     if (gatewayId)
191     {
192         memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
193     }
194
195     if(!routeOption.destGw)
196     {
197         routeOption.mSeqNum = RMGetMcastSeqNumber();
198     }
199 #endif
200
201     res = RMCreateRouteOption(&routeOption, optionPtr + index);
202     if (OC_STACK_OK != res)
203     {
204         OIC_LOG(ERROR, TAG, "Creation of routing option failed");
205         OICFree(optionPtr);
206         return res;
207     }
208
209     if ((*numOptions) == index )
210     {
211         (*numOptions) = (*numOptions) + 1;
212         OICFree(*options);
213         *options = optionPtr;
214     }
215
216     return OC_STACK_OK;
217 }
218
219 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
220                            CAEndpoint_t *endpoint)
221 {
222     RM_NULL_CHECK_WITH_RET(options, TAG, "options");
223     RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
224     RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
225     RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
226
227     if (0 >= *numOptions)
228     {
229         OIC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
230         return OC_STACK_ERROR;
231     }
232
233     int8_t routeIndex = -1;
234     RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
235
236     if (-1 >= routeIndex)
237     {
238         OIC_LOG(DEBUG, TAG, "Nothing to remove.");
239         return OC_STACK_OK;
240     }
241
242     // Update Endpoint with source address from RM header option.
243     if (DEFAULT_ROUTE_OPTION_LEN < (*options + routeIndex)->optionLength )
244     {
245         uint8_t dLen = 0;
246         uint16_t count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
247         memcpy(&dLen, (*options + routeIndex)->optionData + DEFAULT_ROUTE_OPTION_LEN, sizeof(dLen));
248         count += dLen;
249         uint8_t sLen = 0;
250         memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
251         count += sizeof(sLen);
252         if (0 < sLen)
253         {
254             memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
255                    GATEWAY_ID_LENGTH);
256
257             uint32_t rData1 = 0;
258             memcpy(&rData1, endpoint->routeData, sizeof(rData1));
259             OIC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]", rData1, sLen);
260
261             count += GATEWAY_ID_LENGTH;
262
263             if (GATEWAY_ID_LENGTH < sLen)
264             {
265                 memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
266                        (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
267
268                 uint16_t rData2 = 0;
269                 memcpy(&rData2, endpoint->routeData + GATEWAY_ID_LENGTH, sizeof(rData2));
270                 OIC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint", rData2);
271             }
272         }
273     }
274
275     // Remove route option from header.
276     for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
277     {
278         memcpy((*options) + i, (*options)+i+1, sizeof(**options));
279     }
280     *numOptions = (*numOptions) - 1;
281
282     if (0 == *numOptions)
283     {
284         // Remove route option.
285         OICFree(*options);
286         *options = NULL;
287     }
288     return OC_STACK_OK;
289 }
290
291 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
292 {
293     RM_NULL_CHECK_VOID(index, TAG, "index");
294
295     if (NULL == options)
296     {
297         OIC_LOG(INFO, TAG, "No existing options");
298         return;
299     }
300
301     for (uint32_t i = 0; i < numOptions; i++)
302     {
303         OIC_LOG_V(DEBUG, TAG, "Request- optionID: %u", options[i].optionID);
304         if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
305         {
306             OIC_LOG_V(INFO, TAG, "Found Option at %d", i);
307             *index = i;
308             break;
309         }
310     }
311 }
312
313 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
314 {
315     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
316     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
317
318     uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
319                         (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
320     uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
321                         (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
322
323     OIC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
324
325     unsigned int totalLength = 0;
326     uint8_t *tempData = NULL;
327
328     if (0 == dLen && 0 == sLen)
329     {
330         OIC_LOG(DEBUG, RM_TAG, "Source and destination is not present");
331         totalLength = DEFAULT_ROUTE_OPTION_LEN;
332         tempData = OICCalloc(totalLength, sizeof(char));
333         if (NULL == tempData)
334         {
335             OIC_LOG(ERROR, RM_TAG, "Calloc failed");
336             return OC_STACK_NO_MEMORY;
337         }
338
339         if (ACK == optValue->msgType)
340         {
341             OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
342             memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
343         }
344         else if (RST == optValue->msgType)
345         {
346             OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
347             memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
348         }
349         else
350         {
351             OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
352             memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
353         }
354     }
355     else
356     {
357         totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
358         tempData = OICCalloc(totalLength, sizeof(char));
359         if (NULL == tempData)
360         {
361             OIC_LOG(ERROR, RM_TAG, "Calloc failed");
362             return OC_STACK_NO_MEMORY;
363         }
364
365         if (ACK == optValue->msgType)
366         {
367             OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
368             memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
369         }
370         else if (RST == optValue->msgType)
371         {
372             OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
373             memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
374         }
375         else
376         {
377             OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
378             memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
379         }
380
381         memcpy(tempData + DEFAULT_ROUTE_OPTION_LEN, &dLen, sizeof(dLen));
382         unsigned int count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
383         if (0 < dLen)
384         {
385             if (optValue->destGw)
386             {
387                 memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
388                 count += GATEWAY_ID_LENGTH;
389             }
390
391             if (optValue->destEp)
392             {
393                 memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
394                 count += ENDPOINT_ID_LENGTH;
395             }
396         }
397
398         memcpy(tempData + count, &sLen, sizeof(sLen));
399         count += sizeof(sLen);
400         if (0 < sLen)
401         {
402             if (optValue->srcGw)
403             {
404                 memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
405                 count += GATEWAY_ID_LENGTH;
406             }
407
408             if (optValue->srcEp)
409             {
410                 memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
411                 count += ENDPOINT_ID_LENGTH;
412             }
413         }
414
415         memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
416     }
417
418     memcpy(options->optionData, tempData, totalLength);
419
420     options->optionID = RM_OPTION_MESSAGE_SWITCHING;
421     options->optionLength = totalLength;
422
423     OIC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
424
425     OICFree(tempData);
426     return OC_STACK_OK;
427 }
428
429 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
430 {
431     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
432     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
433     if (0 == options->optionLength)
434     {
435         OIC_LOG(ERROR, RM_TAG, "Option data is not present");
436         return OC_STACK_ERROR;
437     }
438
439     OIC_LOG_V(DEBUG, RM_TAG, "Option Length is %d", options->optionLength);
440     uint8_t mType = 0;
441     memcpy(&mType, options->optionData, sizeof(mType));
442
443     if (ACK_MESSAGE_TYPE == mType)
444     {
445         OIC_LOG(INFO, RM_TAG, "ACK_MESSAGE_TYPE");
446         optValue->msgType = ACK;
447     }
448     else if (RST_MESSAGE_TYPE == mType)
449     {
450         OIC_LOG(INFO, RM_TAG, "RST_MESSAGE_TYPE");
451         optValue->msgType = RST;
452     }
453     else if (NORMAL_MESSAGE_TYPE == mType)
454     {
455         OIC_LOG(INFO, RM_TAG, "NOR_MESSAGE_TYPE");
456         optValue->msgType = NOR;
457     }
458
459     if (DEFAULT_ROUTE_OPTION_LEN == options->optionLength)
460     {
461         OIC_LOG(INFO, RM_TAG, "No source and destination are present");
462     }
463     else
464     {
465         uint8_t dLen = 0 ;
466         uint16_t count = DEFAULT_ROUTE_OPTION_LEN;
467         memcpy(&dLen, options->optionData + count, sizeof(dLen));
468         count += sizeof(dLen);
469         if (0 < dLen)
470         {
471             memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
472             count += GATEWAY_ID_LENGTH;
473
474             if (GATEWAY_ID_LENGTH < dLen)
475             {
476                 memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
477                 count += ENDPOINT_ID_LENGTH;
478             }
479         }
480
481         uint8_t sLen = 0;
482         memcpy(&sLen, options->optionData + count, sizeof(sLen));
483         count += sizeof(sLen);
484         if (0 < sLen)
485         {
486             memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
487             count += GATEWAY_ID_LENGTH;
488
489             if (GATEWAY_ID_LENGTH < sLen)
490             {
491                 memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
492                 count += ENDPOINT_ID_LENGTH;
493             }
494         }
495         memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
496     }
497
498     OIC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
499     OIC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
500     OIC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
501     OIC_LOG_V(INFO, RM_TAG, "Message Type is [%u]", optValue->msgType);
502     return OC_STACK_OK;
503 }