1 /* ****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
23 #include "routingutility.h"
24 #include "routingmanager.h"
25 #include "oic_malloc.h"
26 #include "include/logger.h"
29 * Logging tag for module name.
34 * Tag for printing the logs of forwarding the packet.
39 * Minimum routing option data length is
40 * length of src address(1byte) + length of destination address(1byte) + hop count(2bytes)
42 #define MIN_ROUTE_OPTION_LEN 4
44 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
45 OCStackResult RMAddInfo(const char *destination, CAHeaderOption_t **options,
48 OC_LOG(DEBUG, TAG, "IN");
49 RM_NULL_CHECK_WITH_RET(options, TAG, "options");
50 RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
52 CAHeaderOption_t *optionPtr = NULL;
55 RMGetRouteOptionIndex(*options, *numOptions, &index);
59 OC_LOG(INFO, TAG, "Route option is present");
64 OC_LOG(INFO, TAG, "Route option is not present");
66 optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
69 OC_LOG(ERROR, TAG, "OICCalloc failed");
70 return OC_STACK_NO_MEMORY;
73 memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
76 OCStackResult res = OC_STACK_OK;
77 RMRouteOption_t routeOption = {.destGw = 0};
78 if (*numOptions != index)
80 OC_LOG(INFO, TAG, "Route option is already present");
81 res = RMParseRouteOption(&optionPtr[index], &routeOption);
82 if (OC_STACK_OK != res)
84 OC_LOG(ERROR, TAG, "RMParseRouteOption failed");
85 return OC_STACK_ERROR;
91 memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
92 memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
93 sizeof(routeOption.destEp));
96 #ifdef ROUTING_GATEWAY
97 // A gateway is supposed to add its ID as source.
98 uint32_t gatewayId = RMGetGatewayId();
101 memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
104 if(!routeOption.destGw)
106 routeOption.mSeqNum = RMGetMcastSeqNumber();
110 res = RMCreateRouteOption(&routeOption, optionPtr + index);
111 if (OC_STACK_OK != res)
113 OC_LOG(ERROR, TAG, "Creation of routing option failed");
118 if ((*numOptions) == index )
120 (*numOptions) = (*numOptions) + 1;
122 *options = optionPtr;
125 OC_LOG(DEBUG, TAG, "OUT");
129 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
130 CAEndpoint_t *endpoint)
132 OC_LOG(DEBUG, TAG, "IN");
133 RM_NULL_CHECK_WITH_RET(options, TAG, "options");
134 RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
135 RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
136 RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
138 if (0 >= *numOptions)
140 OC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
141 return OC_STACK_ERROR;
144 int8_t routeIndex = -1;
145 RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
147 if (-1 >= routeIndex)
149 OC_LOG(DEBUG, TAG, "Nothing to remove.");
153 // Update Endpoint with source address from RM header option.
154 if (0 != (*options + routeIndex)->optionLength)
157 uint16_t count = sizeof(dLen);
158 memcpy(&dLen, (*options + routeIndex)->optionData, sizeof(dLen));
161 memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
162 count += sizeof(sLen);
165 memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
167 OC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
168 *((uint32_t *)endpoint->routeData), sLen);
170 count += GATEWAY_ID_LENGTH;
172 if (GATEWAY_ID_LENGTH < sLen)
174 memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
175 (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
176 OC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint",
177 *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH)));
182 // Remove route option from header.
183 for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
185 memcpy((*options) + i, (*options)+i+1, sizeof(**options));
187 *numOptions = (*numOptions) - 1;
189 if (0 == *numOptions)
191 // Remove route option.
195 OC_LOG(DEBUG, TAG, "OUT");
199 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
201 OC_LOG(DEBUG, TAG, "IN");
202 RM_NULL_CHECK_VOID(options, TAG, "options");
203 RM_NULL_CHECK_VOID(index, TAG, "index");
204 for (uint32_t i = 0; i < numOptions; i++)
206 OC_LOG_V(DEBUG, TAG, "Request- optionID: %d", options[i].optionID);
207 if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
209 OC_LOG_V(INFO, TAG, "Found Option at %d", i);
214 OC_LOG(DEBUG, TAG, "OUT");
217 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
219 OC_LOG(DEBUG, RM_TAG, "IN");
220 RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
221 RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
223 uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
224 (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
225 uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
226 (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
228 OC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
229 unsigned int totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
230 void *tempData = OICCalloc(totalLength, sizeof(char));
231 if (NULL == tempData)
233 OC_LOG(ERROR, RM_TAG, "Calloc failed");
234 return OC_STACK_NO_MEMORY;
236 memcpy(tempData, &dLen, sizeof(dLen));
237 unsigned int count = sizeof(dLen);
240 if (optValue->destGw)
242 memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
243 count += GATEWAY_ID_LENGTH;
246 if (optValue->destEp)
248 memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
249 count += ENDPOINT_ID_LENGTH;
253 memcpy(tempData + count, &sLen, sizeof(sLen));
254 count += sizeof(sLen);
259 memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
260 count += GATEWAY_ID_LENGTH;
265 memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
266 count += ENDPOINT_ID_LENGTH;
270 memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
271 memcpy(options->optionData, tempData, totalLength);
273 options->optionID = RM_OPTION_MESSAGE_SWITCHING;
274 options->optionLength = totalLength;
276 OC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
279 OC_LOG(DEBUG, RM_TAG, "OUT");
283 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
285 OC_LOG(DEBUG, RM_TAG, "IN");
286 RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
287 RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
288 if (0 == options->optionLength)
290 OC_LOG(ERROR, RM_TAG, "Option data is not present");
291 return OC_STACK_ERROR;
295 uint16_t count = sizeof(dLen);
296 memcpy(&dLen, options->optionData, sizeof(dLen));
299 memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
300 count += GATEWAY_ID_LENGTH;
302 if (GATEWAY_ID_LENGTH < dLen)
304 memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
305 count += ENDPOINT_ID_LENGTH;
310 memcpy(&sLen, options->optionData + count, sizeof(sLen));
311 count += sizeof(sLen);
314 memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
315 count += GATEWAY_ID_LENGTH;
317 if (GATEWAY_ID_LENGTH < sLen)
319 memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
320 count += ENDPOINT_ID_LENGTH;
323 memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
325 OC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
326 OC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
327 OC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
328 OC_LOG(DEBUG, RM_TAG, "OUT");