RDK Documentation (Open Sourced RDK Components)
idm_server.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
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 #include <libgupnp/gupnp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <gmodule.h>
23 #include <stdbool.h>
24 #include <memory.h>
25 #include <libxml/tree.h>
26 #include <libxml/parser.h>
27 #include <string.h>
28 #include "secure_wrapper.h"
29 #include "xdevice.h"
30 #include <net/if.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <ifaddrs.h>
35 #include <libgupnp/gupnp-control-point.h>
36 #ifdef ENABLE_SD_NOTIFY
37 #include <systemd/sd-daemon.h>
38 #endif
39 #include "rdk_safeclib.h"
40 #define SERVER_CONTEXT_PORT 50769
41 #define DEVICE_PROTECTION_CONTEXT_PORT 50761
42 #define IDM_SERVICE "urn:schemas-upnp-org:service:X1IDM:1"
43 #define IDM_DP_SERVICE "urn:schemas-upnp-org:service:X1IDM_DP:1"
44 #define IDM_CERT_FILE "/tmp/idm_xpki_cert"
45 #define IDM_KEY_FILE "/tmp/idm_xpki_key"
46 #define IDM_CA_FILE "/tmp/idm_UPnP_CA"
47 #ifndef _GNU_SOURCE
48  #define _GNU_SOURCE
49 #endif
50 #define MAC_ADDR_SIZE 18
51 #define IPv4_ADDR_SIZE 16
52 #define IPv6_ADDR_SIZE 128
53 #define ACCOUNTID_SIZE 30
54 char clientIp[IPv4_ADDR_SIZE],bcastMacaddress[MAC_ADDR_SIZE],gwyIpv6[IPv6_ADDR_SIZE],interface[IPv4_ADDR_SIZE],accountId[ACCOUNTID_SIZE],uUid[256];
55 GString *bcastmacaddress,*serial_num,*recv_id;
56 GUPnPContext *server_upnpContext,*server_upnpContextDeviceProtect;
57 void free_server_memory();
58 int check_file_presence();
59 BOOL check_empty_idm(char *str)
60 {
61  if (str[0]) {
62  return TRUE;
63  }
64  return FALSE;
65 }
66 bool check_null_idm(char *str)
67 {
68  if (str) {
69  return true;
70  }
71  return false;
72 }
73 
74 G_MODULE_EXPORT void
75 get_bcastmacaddress_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
76 {
77  gupnp_service_action_set (action, "BcastMacAddress", G_TYPE_STRING, bcastMacaddress, NULL);
78  gupnp_service_action_return (action);
79 }
80 
81 G_MODULE_EXPORT void
82 query_bcastmacaddress_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
83 {
84  g_value_init (value, G_TYPE_STRING);
85  g_value_set_string (value, bcastMacaddress);
86 }
87 
88 G_MODULE_EXPORT void
89 get_client_ip_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
90 {
91  gupnp_service_action_set (action, "ClientIP", G_TYPE_STRING, clientIp, NULL);
92  gupnp_service_action_return (action);
93 }
94 
95 G_MODULE_EXPORT void
96 query_client_ip_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
97 {
98  g_value_init (value, G_TYPE_STRING);
99  g_value_set_string (value, clientIp);
100 }
101 G_MODULE_EXPORT void
102 get_gwyipv6_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
103 {
104  gupnp_service_action_set (action, "GatewayIPv6", G_TYPE_STRING, gwyIpv6, NULL);
105  gupnp_service_action_return (action);
106 }
107 G_MODULE_EXPORT void
108 query_gwyipv6_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
109 {
110  g_value_init (value, G_TYPE_STRING);
111  g_value_set_string (value, gwyIpv6);
112 }
113 
114 G_MODULE_EXPORT void
115 get_account_id_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
116 {
117  memset(accountId,0,ACCOUNTID_SIZE);
118  getAccountId(accountId);
119  g_message("accountId=%s",accountId);
120  gupnp_service_action_set (action, "AccountId", G_TYPE_STRING, accountId,NULL);
121  gupnp_service_action_return (action);
122 }
123 
124 G_MODULE_EXPORT void
125 query_account_id_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
126 {
127  g_value_init (value, G_TYPE_STRING);
128  g_value_set_string (value, accountId);
129 }
130 
131 xmlDoc * open_document(const char * file_name)
132 {
133  xmlDoc * ret;
134  ret = xmlReadFile(file_name, NULL, 0);
135  if (ret == NULL)
136  {
137  //g_printerr("Failed to parse %s\n", file_name);
138  return NULL;
139  }
140  return ret;
141 }
142 
143 static xmlNode * get_node_by_name(xmlNode * node, const char *node_name)
144 {
145  errno_t rc = -1;
146  int ind = -1;
147  xmlNode * cur_node = NULL;
148  xmlNode * ret = NULL;
149  for (cur_node = node ; cur_node ; cur_node = cur_node->next)
150  {
151  rc = strcmp_s(cur_node->name, strlen(cur_node->name), node_name, &ind);
152  ERR_CHK(rc);
153  if ((ind ==0) && (rc == EOK))
154  {
155  return cur_node;
156  }
157  ret = get_node_by_name(cur_node->children, node_name);
158  if ( ret != NULL )
159  break;
160  }
161  return ret;
162 }
163 
164 int set_content(xmlDoc* doc, const char * node_name, const char * new_value)
165 {
166  xmlNode * root_element = NULL;
167  xmlNode * target_node = NULL;
168  root_element = xmlDocGetRootElement(doc);
169  target_node = get_node_by_name(root_element, node_name);
170  if (target_node==NULL)
171  {
172  g_printerr("Couldn't locate the Target node\n");
173  return 1;
174  }
175  xmlNodeSetContent(target_node,new_value);
176  return 0;
177 }
178 
179 BOOL updatexmldata(const char* xmlfilename, const char* struuid,const char* serialno)
180 {
181  xmlDoc * doc = open_document(xmlfilename);
182  if (doc == NULL)
183  {
184  g_printerr ("Error reading the Device XML file\n");
185  return FALSE;
186  }
187  if (set_content(doc, "UDN", struuid)!=0)
188  {
189  g_printerr ("Error setting the unique device id in conf xml\n");
190  return FALSE;
191  }
192  if (set_content(doc, "serialNumber", serialno)!=0)
193  {
194  g_printerr ("Error setting the serial number in conf xml\n");
195  return FALSE;
196  }
197  FILE *fp = fopen(xmlfilename, "w");
198  if (fp==NULL)
199  {
200  g_printerr ("Error opening the conf xml file for writing\n");
201  return FALSE;
202  }
203  else if (xmlDocFormatDump(fp, doc, 1) == -1)
204  {
205  g_printerr ("Could not write the conf to xml file\n");
206  /*Coverity Fix CID 125137,28460 RESOURCE_LEAK */
207  fclose(fp);
208  xmlFreeDoc(doc);
209 
210  return FALSE;
211  }
212  fclose(fp);
213  xmlFreeDoc(doc);
214  xmlCleanupParser();
215  return TRUE;
216 }
217 
218 void free_server_memory()
219 {
220  g_message("Inside %s",__FUNCTION__);
221 #ifdef IDM_DEBUG
222  gupnp_root_device_set_available (baseDev, FALSE);
223  g_object_unref (upnpService);
224  g_object_unref (baseDev);
225  g_object_unref (server_upnpContext);
226 #else
227  gupnp_root_device_set_available (dev, FALSE);
228  g_object_unref (upnpIdService);
229  g_object_unref (dev);
230  g_object_unref (server_upnpContextDeviceProtect);
231 #endif
232 }
233 BOOL getUidfromRecvId()
234 {
235  BOOL result = FALSE;
236  guint loopvar = 0;
237  gchar **tokens = g_strsplit_set(bcastMacaddress, "':''\n'", -1);
238  guint toklength = g_strv_length(tokens);
239  while (loopvar < toklength)
240  {
241  g_string_printf(recv_id, "ebf5a0a0-1dd1-11b2-a90f-%s%s%s%s%s%s", g_strstrip(tokens[loopvar]), g_strstrip(tokens[loopvar + 1]),g_strstrip(tokens[loopvar + 2]),g_strstrip(tokens[loopvar + 3]),g_strstrip(tokens[loopvar + 4]),g_strstrip(tokens[loopvar + 5]));
242  g_message("getUidfromRecvId: recvId: %s", recv_id->str);
243  result = TRUE;
244  break;
245  }
246  g_strfreev(tokens);
247  return result;
248 }
249 BOOL getUUID(char *outValue)
250 {
251  BOOL result = FALSE;
252  if (!check_null_idm(outValue)) {
253  g_message("getUUID : NULL string !");
254  return result;
255  }
256  if (getUidfromRecvId()){
257  if( (check_empty_idm(recv_id->str))) {
258  sprintf(outValue, "uuid:%s", recv_id->str);
259  result = TRUE;
260  }
261  else
262  {
263  g_message("getUUID : empty recvId");
264  }
265  }
266  else
267  {
268  g_message("getUUID : could not get UUID");
269  }
270  return result;
271 }
272 
273 int idm_server_start(char* Interface, char * base_mac)
274 {
275  g_thread_init (NULL);
276  g_type_init();
277  GError* error = 0;
278  strcpy(interface,Interface);
279  g_message("%s %d interface=%s",__FUNCTION__,__LINE__,interface);
280  getipaddress((const char *)interface,clientIp,FALSE);
281  serial_num = g_string_new(NULL);
282  getserialnum(serial_num);
283  getipaddress((const char *)interface,gwyIpv6,TRUE);
284  strcpy_s(bcastMacaddress, MAC_ADDR_SIZE, base_mac);
285 #ifndef IDM_DEBUG
286  char certFile[24],keyFile[24],caFile[24]=IDM_CA_FILE;
287  strcpy(certFile,IDM_CERT_FILE);
288  strcpy(keyFile,IDM_KEY_FILE);
289  g_message("cert file=%s key file = %s",certFile,keyFile);
290  if((access(certFile,F_OK ) == 0) && (access(keyFile,F_OK ) == 0) && (access(caFile,F_OK ) == 0))
291  {
292  const char* struuid_dp=g_strconcat("uuid:", g_strstrip(bcastMacaddress),NULL);
293  int result = updatexmldata("/etc/xupnp/IDM_DP.xml",struuid_dp,serial_num->str);
294  if (!result)
295  {
296  fprintf(stderr,"Failed to open the device xml file /etc/xupnp/IDM_DP.xml\n");
297  }
298 #ifndef GUPNP_1_2
299  server_upnpContextDeviceProtect = gupnp_context_new_s ( NULL,interface,DEVICE_PROTECTION_CONTEXT_PORT,certFile,keyFile, &error);
300 #else
301  server_upnpContextDeviceProtect = gupnp_context_new_s ( interface,DEVICE_PROTECTION_CONTEXT_PORT,certFile,keyFile, &error);
302 #endif
303  g_message("created new upnpContext");
304  if (error)
305  {
306  g_message("%s:Error creating the Device Protection Broadcast context: %s",
307  __FUNCTION__,error->message);
308  /* g_clear_error() frees the GError *error memory and reset pointer if set in above operation */
309  g_clear_error(&error);
310  }
311  else
312  {
313  gupnp_context_set_subscription_timeout(server_upnpContextDeviceProtect, 0);
314  // Set TLS config params here.
315  gupnp_context_set_tls_params(server_upnpContextDeviceProtect,caFile,keyFile, NULL);
316 #ifndef GUPNP_1_2
317  dev = gupnp_root_device_new (server_upnpContextDeviceProtect, "/etc/xupnp/IDM_DP.xml", "/etc/xupnp/");
318 #else
319  dev = gupnp_root_device_new (server_upnpContextDeviceProtect, "/etc/xupnp/IDM_DP.xml", "/etc/xupnp/", &error);
320 #endif
321  gupnp_root_device_set_available (dev, TRUE);
322  upnpIdService = gupnp_device_info_get_service(GUPNP_DEVICE_INFO (dev), IDM_DP_SERVICE);
323  if (!upnpIdService)
324  {
325  g_message("Cannot get X1Identity service\n");
326  }
327  else
328  {
329  g_message("XUPNP Identity service successfully created");
330  }
331  g_signal_connect (upnpIdService, "action-invoked::GetBcastMacAddress", G_CALLBACK (get_bcastmacaddress_cb), NULL);
332  g_signal_connect (upnpIdService, "query-variable::BcastMacAddress", G_CALLBACK (query_bcastmacaddress_cb), NULL);
333  g_signal_connect (upnpIdService, "action-invoked::GetClientIP", G_CALLBACK (get_client_ip_cb), NULL);
334  g_signal_connect (upnpIdService, "query-variable::ClientIP", G_CALLBACK (query_client_ip_cb), NULL);
335  g_signal_connect (upnpIdService, "action-invoked::GetAccountId", G_CALLBACK (get_account_id_cb), NULL);
336  g_signal_connect (upnpIdService, "query-variable::AccountId", G_CALLBACK (query_account_id_cb), NULL);
337  g_signal_connect (upnpIdService, "action-invoked::GetGatewayIPv6", G_CALLBACK (get_gwyipv6_cb), NULL);
338  g_signal_connect (upnpIdService, "query-variable::GatewayIPv6", G_CALLBACK (query_gwyipv6_cb), NULL);
339  }
340  }
341  else
342  {
343  g_message("%s:mandatory files doesn't present",__FUNCTION__);
344  }
345 #else
346  recv_id=g_string_new(NULL);
347  getUUID(uUid);
348  const char* struuid = uUid;
349  g_message("recv_id=%s",struuid);
350  int result = updatexmldata("/etc/xupnp/IDM.xml",struuid,serial_num->str);
351  if (!result)
352  {
353  fprintf(stderr,"Failed to open the device xml file /etc/xupnp/IDM.xml\n");
354  }
355  else
356  {
357  g_message("Updated the device xml file:IDM.XML uuid: %s",struuid);
358  }
359 #ifndef GUPNP_1_2
360  server_upnpContext = gupnp_context_new (NULL, interface, SERVER_CONTEXT_PORT, &error);
361 #else
362  server_upnpContext = gupnp_context_new (interface, SERVER_CONTEXT_PORT, &error);
363 #endif
364  if (error) {
365  g_message("Error creating the Broadcast context: %s",
366  error->message);
367  /* g_clear_error() frees the GError *error memory and reset pointer if set in above operation */
368  g_clear_error(&error);
369  return 1;
370  }
371  gupnp_context_set_subscription_timeout(server_upnpContext, 0);
372 #ifndef GUPNP_1_2
373  baseDev = gupnp_root_device_new (server_upnpContext, "/etc/xupnp/IDM.xml", "/etc/xupnp/");
374 #else
375  baseDev = gupnp_root_device_new (server_upnpContext, "/etc/xupnp/IDM.xml", "/etc/xupnp/", &error);
376 #endif
377  gupnp_root_device_set_available (baseDev, TRUE);
378  upnpService = gupnp_device_info_get_service(GUPNP_DEVICE_INFO (baseDev), IDM_SERVICE);
379  if (!upnpService)
380  {
381  g_printerr ("Cannot get DiscoverFriendlies service\n");
382  return 1;
383  }
384  g_signal_connect (upnpService, "action-invoked::GetBcastMacAddress", G_CALLBACK (get_bcastmacaddress_cb), NULL);
385  g_signal_connect (upnpService, "query-variable::BcastMacAddress", G_CALLBACK (query_bcastmacaddress_cb), NULL);
386  g_signal_connect (upnpService, "action-invoked::GetClientIP", G_CALLBACK (get_client_ip_cb), NULL);
387  g_signal_connect (upnpService, "query-variable::ClientIP", G_CALLBACK (query_client_ip_cb), NULL);
388  g_signal_connect (upnpService, "action-invoked::GetGatewayIPv6", G_CALLBACK (get_gwyipv6_cb), NULL);
389  g_signal_connect (upnpService, "query-variable::GatewayIPv6", G_CALLBACK (query_gwyipv6_cb), NULL);
390 #endif
391  g_message("completed %s\n",__FUNCTION__);
392  return 0;
393 }
get_gwyipv6_cb
G_MODULE_EXPORT void get_gwyipv6_cb(GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
Callback function which is invoked when getGatewayIPv6 action is invoked and this sets the state vari...
Definition: xcal-device.c:774
query_bcastmacaddress_cb
G_MODULE_EXPORT void query_bcastmacaddress_cb(GUPnPService *service, char *variable, GValue *value, gpointer user_data)
Callback function which is invoked when BcastMacAddress action is invoked and this sets the state var...
Definition: xcal-device.c:1347
getserialnum
gboolean getserialnum(GString *serial_num)
This function is used to get the serial number of the device from the vendor specific file.
Definition: xcal-device-library.c:227
xdevice.h
The header file provides xcal devices APIs.
query_client_ip_cb
G_MODULE_EXPORT void query_client_ip_cb(GUPnPService *service, char *variable, GValue *value, gpointer user_data)
Callback function which is invoked when ClientIP action is invoked and this sets the state variable w...
Definition: xcal-device-main.c:1359
open_document
xmlDoc * open_document(const char *file_name)
Supporting function for reading the XML file.
Definition: xcal-device-main.c:257
updatexmldata
gboolean updatexmldata(const char *xmlfilename, const char *struuid, const char *serialno, const char *friendlyName)
This function is used to update the xml node values UDN, serialNumber and friendlyName.
Definition: xcal-device.c:3260
query_gwyipv6_cb
G_MODULE_EXPORT void query_gwyipv6_cb(GUPnPService *service, char *variable, GValue *value, gpointer user_data)
Callback function which is invoked when Ipv6Prefix action is invoked and this sets the state variable...
Definition: xcal-device.c:1275
getipaddress
int getipaddress(const char *ifname, char *ipAddressBuffer, gboolean ipv6Enabled)
This function is used to get the IP address based on IPv6 or IPv4 is enabled.
Definition: xcal-device.c:2188
set_content
int set_content(xmlDoc *doc, const char *node_name, const char *new_value)
This function is used to set new value to the given node from the xml file.
Definition: xcal-device-main.c:113
get_bcastmacaddress_cb
G_MODULE_EXPORT void get_bcastmacaddress_cb(GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
Callback function which is invoked when getBcastMacAddress action is invoked and this sets the state ...
Definition: xcal-device.c:848
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
get_client_ip_cb
G_MODULE_EXPORT void get_client_ip_cb(GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
Callback function which is invoked when getClientIP action is invoked and this sets the state variabl...
Definition: xcal-device-main.c:901