RDK Documentation (Open Sourced RDK Components)
Device_DHCPv4_Client.cpp
Go to the documentation of this file.
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 2016 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 
20 /**
21  * @file Device_DHCPv4_Client.cpp
22  * @brief This source file contains the APIs of device DHCPv4 client.
23  */
24 #include <net/if.h>
25 #include <string.h>
26 #include "Device_DHCPv4_Client.h"
27 #include "Device_IP_Interface.h"
28 #include "Device_IP.h"
29 #ifdef YOCTO_BUILD
30 #include "secure_wrapper.h"
31 #endif
32 #define MAX_CMD_LEN 128
33 #define MAX_BUF_LEN 256
34 #define MAX_IP_LEN 16
35 
36 DHCPv4Client hostIf_DHCPv4Client::dhcpClient = {{'\0'}, {'\0'}, {'\0'}};
37 GHashTable *hostIf_DHCPv4Client::dhcpv4ClientHash = NULL;
38 GMutex *hostIf_DHCPv4Client::m_mutex = NULL;
39 GHashTable* hostIf_DHCPv4Client::m_notifyHash = NULL;
40 /* Constructor for hostIf_DHCPv4Client*/
41 
42 /**
43  * @brief Class Constructor of the class hostIf_DHCPv4Client.
44  *
45  * It will initialize the device id, interface, dns servers and ipRouters.
46  *
47  * @param[in] devid Device identification Number.
48  */
49 hostIf_DHCPv4Client::hostIf_DHCPv4Client(int dev_id):dev_id(dev_id)
50 {
51  FILE* cmdOP;
52  int len;
53  char buffer[MAX_BUF_LEN]={'\0'};
54  bBackUpFlags.interface=0;
55  bBackUpFlags.dnsservers=0;
56  bBackUpFlags.ipRouters=0;
57  memset(&backupDhcpClient, '\0', sizeof(backupDhcpClient));
58  RDK_LOG(RDK_LOG_DEBUG,LOG_TR69HOSTIF,"Inside constructor for dev_id:%d\n", dev_id);
59 }
60 
61 void hostIf_DHCPv4Client::getLock()
62 {
63  if(!m_mutex)
64  {
65  m_mutex = g_mutex_new();
66  }
67  g_mutex_lock(m_mutex);
68 }
69 
70 void hostIf_DHCPv4Client::releaseLock()
71 {
72  g_mutex_unlock(m_mutex);
73 }
74 
75 GHashTable* hostIf_DHCPv4Client::getNotifyHash()
76 {
77  if(m_notifyHash)
78  {
79  return m_notifyHash;
80  }
81  else
82  {
83  return m_notifyHash = g_hash_table_new(g_str_hash, g_str_equal);
84  }
85 }
86 
87 hostIf_DHCPv4Client* hostIf_DHCPv4Client::getInstance(int dev_id)
88 {
89  RDK_LOG(RDK_LOG_DEBUG,LOG_TR69HOSTIF,"Entering [%s]\n", __FUNCTION__);
90  hostIf_DHCPv4Client* pRet = NULL;
91  if(dhcpv4ClientHash)
92  {
93  pRet = (hostIf_DHCPv4Client *)g_hash_table_lookup(dhcpv4ClientHash, (gpointer) dev_id);
94  }
95  else
96  {
97 
98  dhcpv4ClientHash = g_hash_table_new(NULL, NULL);
99  }
100  if(!pRet)
101  {
102  try {
103  pRet = new hostIf_DHCPv4Client(dev_id);
104  } catch(int e)
105  {
106  RDK_LOG(RDK_LOG_WARN,LOG_TR69HOSTIF,"Caught exception, not able create DHCPv4 client instance..\n");
107  }
108  g_hash_table_insert(dhcpv4ClientHash, (gpointer)dev_id, pRet);
109  }
110  return pRet;
111 }
112 
113 
114 GList* hostIf_DHCPv4Client::getAllInstances()
115 {
116  if(dhcpv4ClientHash)
117  return g_hash_table_get_keys(dhcpv4ClientHash);
118  return NULL;
119 }
120 
121 
122 void hostIf_DHCPv4Client::closeInstance(hostIf_DHCPv4Client *pDev)
123 {
124  if(pDev)
125  {
126  g_hash_table_remove(dhcpv4ClientHash, (gconstpointer)pDev->dev_id);
127  delete pDev;
128  }
129 }
130 
131 hostIf_DHCPv4Client::~hostIf_DHCPv4Client()
132 {
133  if(m_notifyHash)
134  {
135  g_hash_table_destroy(m_notifyHash);
136  }
137 }
138 
139 void hostIf_DHCPv4Client::closeAllInstances()
140 {
141  if(dhcpv4ClientHash)
142  {
143  GList* tmp_list = g_hash_table_get_values (dhcpv4ClientHash);
144 
145  while(tmp_list)
146  {
147  hostIf_DHCPv4Client* pDev = (hostIf_DHCPv4Client *)tmp_list->data;
148  tmp_list = tmp_list->next;
149  closeInstance(pDev);
150  }
151  }
152 }
153 
154 /**
155  * @brief This gets the interface information used by the DHCP(Dynamic Host Configuration Protocol)
156  * v4 client devices.
157  *
158  * @param[out] stMsgData TR-069 Host interface message request.
159  * @param[in] pChanged Status of the operation.
160  *
161  * @return Returns the status of the operation.
162  *
163  * @retval OK if is successfully fetch the data from the device.
164  * @retval ERR_INTERNAL_ERROR if not able to fetch the data.
165  * @ingroup TR69_HOSTIF_DHCPv4_CLIENT_API
166  */
168 {
169  int ret = get_Device_DHCPv4_Client_Fields(eDHCPv4Interface);
170  if(ret== OK)
171  {
172  if(bBackUpFlags.interface && pChanged && (strncmp(backupDhcpClient.interface, dhcpClient.interface, sizeof(backupDhcpClient.interface))))
173  {
174  *pChanged= true;
175  }
176  bBackUpFlags.interface = 1;
177  strncpy(backupDhcpClient.interface, dhcpClient.interface, MAX_IF_LEN -1);
178  backupDhcpClient.interface[MAX_IF_LEN-1]='\0';
179  strncpy(stMsgData->paramValue, dhcpClient.interface, TR69HOSTIFMGR_MAX_PARAM_LEN -1);
180  stMsgData->paramValue[TR69HOSTIFMGR_MAX_PARAM_LEN -1]='\0';
181  stMsgData->paramLen=strlen(dhcpClient.interface);
182  stMsgData->paramtype = hostIf_StringType;
183  }
184  return ret;
185 }
186 
187 /**
188  * @brief This gets the DNS server information used by the DHCP(Dynamic Host Configuration Protocol)
189  * v4 client devices.
190  *
191  * @param[out] stMsgData TR-069 Host interface message request.
192  * @param[in] pChanged Status of the operation.
193  *
194  * @return Returns the status of the operation.
195  *
196  * @retval OK if is successfully fetch the data from the device.
197  * @retval ERR_INTERNAL_ERROR if not able to fetch the data.
198  * @ingroup TR69_HOSTIF_DHCPv4_CLIENT_API
199  */
201 {
202  int ret= get_Device_DHCPv4_Client_Fields(eDHCPv4Dnsservers);
203  if(ret== OK)
204  {
205  if(bBackUpFlags.dnsservers && pChanged && (strncmp(backupDhcpClient.dnsservers, dhcpClient.dnsservers, sizeof(backupDhcpClient.dnsservers))))
206  {
207  *pChanged= true;
208  }
209  bBackUpFlags.dnsservers = 1;
210  strncpy(backupDhcpClient.dnsservers, dhcpClient.dnsservers, MAX_DNS_SERVER_LEN -1);
211  backupDhcpClient.dnsservers[MAX_DNS_SERVER_LEN-1]='\0';
212  strncpy(stMsgData->paramValue, dhcpClient.dnsservers, TR69HOSTIFMGR_MAX_PARAM_LEN -1);
213  stMsgData->paramValue[TR69HOSTIFMGR_MAX_PARAM_LEN -1]='\0';
214  stMsgData->paramLen=strlen(dhcpClient.dnsservers);
215  stMsgData->paramtype = hostIf_StringType;
216  }
217  return ret;
218 }
219 
220 /**
221  * @brief This gets the IP Routers information used by the DHCP(Dynamic Host Configuration Protocol)
222  * v4 client devices.
223  *
224  * @param[out] stMsgData TR-069 Host interface message request.
225  * @param[in] pChanged Status of the operation.
226  *
227  * @return Returns the status of the operation.
228  *
229  * @retval OK if is successfully fetch the data from the device.
230  * @retval ERR_INTERNAL_ERROR if not able to fetch the data.
231  * @ingroup TR69_HOSTIF_DHCPv4_CLIENT_API
232  */
234 {
235  int ret = get_Device_DHCPv4_Client_Fields(eDHCPv4Iprouters);
236 
237  if ( ret == OK)
238  {
239  if(bBackUpFlags.ipRouters && pChanged && (strncmp(backupDhcpClient.ipRouters, dhcpClient.ipRouters, sizeof(backupDhcpClient.ipRouters))))
240  {
241  *pChanged= true;
242  }
243  bBackUpFlags.ipRouters = 1;
244  strncpy(backupDhcpClient.ipRouters, dhcpClient.ipRouters, MAX_IP_ROUTER_LEN - 1);
245  backupDhcpClient.ipRouters[MAX_IP_ROUTER_LEN -1 ] ='\0';
246  strncpy(stMsgData->paramValue, dhcpClient.ipRouters, TR69HOSTIFMGR_MAX_PARAM_LEN -1);
247  stMsgData->paramValue[TR69HOSTIFMGR_MAX_PARAM_LEN -1]='\0';
248  stMsgData->paramLen=strlen(dhcpClient.ipRouters);
249  stMsgData->paramtype = hostIf_StringType;
250  }
251  return ret;
252 }
253 
254 int hostIf_DHCPv4Client::get_Device_DHCPv4_ClientNumberOfEntries(HOSTIF_MsgData_t *stMsgData)
255 {
256  int num=1;
257  char cmd[MAX_CMD_LEN]={'\0'};
258  FILE* cmdOP=NULL;
259  char buffer[MAX_BUF_LEN]={'\0'};
260  int ret=NOK;
261  RDK_LOG(RDK_LOG_DEBUG,LOG_TR69HOSTIF,"Entering [%s]\n", __FUNCTION__);
262  snprintf(cmd,MAX_CMD_LEN -1,"ip r | grep default|wc -l");
263  cmdOP=popen(cmd,"r");
264  if (cmdOP)
265  {
266  fgets(buffer,MAX_BUF_LEN,cmdOP);
267  num = strtol(buffer,NULL,10);
268  put_int(stMsgData->paramValue, num);
269  stMsgData->paramtype = hostIf_UnsignedIntType;
270  stMsgData->paramLen = sizeof(unsigned int);
271  pclose(cmdOP);
272  ret = OK;
273  }
274  return ret;
275 }
276 
277 bool hostIf_DHCPv4Client::isIfnameInroutetoDNSServer(char* dnsServer, char* ifName)
278 {
279  char cmd[MAX_CMD_LEN]={'\0'};
280  char opIfName[8]={'\0'};
281  FILE* cmdOP;
282 
283  snprintf(cmd,MAX_CMD_LEN -1, "ip route get %s | grep %s | awk 'BEGIN {FR=\" \"} {printf $5}'", dnsServer, dnsServer);
284 #ifdef YOCTO_BUILD
285  cmdOP=v_secure_popen("r", "ip route get %s | grep %s | awk 'BEGIN {FR=\" \"} {printf $5}'", dnsServer, dnsServer);
286 #else
287  cmdOP=popen(cmd, "r");
288 #endif
289  if (cmdOP)
290  {
291  fgets(opIfName, 8, cmdOP);
292 #ifdef YOCTO_BUILD
293  v_secure_pclose(cmdOP);
294 #else
295  pclose(cmdOP);
296 #endif
297  }
298  if(strncmp(opIfName, ifName, sizeof(opIfName))==0)
299  {
300  return 1;
301  }
302  return 0;
303 }
304 
305 int hostIf_DHCPv4Client::get_Device_DHCPv4_Client_Fields(DHCPv4ClientMembers dhclientMember)
306 {
307  FILE* cmdOP;
308  int ret=NOK;
309  int len;
310  char ifname[IFNAMSIZ]={'\0'};
311  char buffer[MAX_BUF_LEN]={'\0'};
312  char dupbuf[MAX_BUF_LEN]={'\0'};
313  char cmd[MAX_CMD_LEN]={'\0'};
314  char *token=NULL;
315  char *savePtr=NULL;
316  int ipNumOfEntries=0;
317  int index=0;
318  GList *devList =NULL;
319  GList *elem=NULL;
320  HOSTIF_MsgData_t msgData;
321 
322  memset(&msgData, 0, sizeof(msgData));
323  ret=getInterfaceName(ifname);
324  if(ret!=OK)
325  return ret;
326 
327 
328  RDK_LOG(RDK_LOG_DEBUG,LOG_TR69HOSTIF,"Entering [%s] asking for member %d\n", __FUNCTION__, dhclientMember);
329  switch(dhclientMember)
330  {
331  case eDHCPv4Interface:
332  /* Get the number of IP interfaces, loop through the objects match the dev_id which matches the ifname and name the interface */
334  ipNumOfEntries=get_int(msgData.paramValue);
335  for(index = 1; index<=ipNumOfEntries; index++)
336  {
337  hostIf_IPInterface *pIface = hostIf_IPInterface::getInstance(index);
338  pIface->get_Interface_Name(&msgData);
339  if(strncmp(msgData.paramValue, ifname, strlen(ifname))==0)
340  {
341  snprintf(dhcpClient.interface, MAX_IF_LEN - 1, "Device.IP.Interface.%d", index);
342  ret=OK;
343  break;
344  }
345 
346  }
347  break;
348  case eDHCPv4Dnsservers:
349  memset(dhcpClient.dnsservers, '\0', sizeof dhcpClient.dnsservers);
350  /* Get the name server from resolv.conf and check if they belong to the interface address*/
351  snprintf(cmd, MAX_CMD_LEN - 1, "cat /etc/resolv.conf | grep nameserver | cut -f2 -d' '|awk 'BEGIN { RS=\"\"; FS=\"\\n\"}{ for (i=1; i<=NF; i++) printf $i\",\" }'");
352  cmdOP=popen(cmd, "r");
353  if (cmdOP)
354  {
355  fgets(buffer, MAX_BUF_LEN, cmdOP);
356  strncpy(dupbuf, buffer, MAX_BUF_LEN - 1);
357  dupbuf[MAX_BUF_LEN-1]='\0';
358  memset(dhcpClient.dnsservers, 0, sizeof(dhcpClient.dnsservers));
359  token=(char *)strtok_r(dupbuf, ",", &savePtr);
360  len=0;
361  /*check if we have a valid token and if the token is a valid IP address*/
362  if(token!=NULL && isValidIPAddr(token))
363  {
364  if((isIfnameInroutetoDNSServer(token, ifname)))
365  {
366  snprintf(dhcpClient.dnsservers, sizeof(dhcpClient.dnsservers), "%s,", token);
367  len=strlen(token)+1;
368  }
369  while(token=strtok_r(NULL, ",", &savePtr))
370  {
371  if((isIfnameInroutetoDNSServer(token, ifname)))
372  {
373  snprintf(dhcpClient.dnsservers+len, sizeof(dhcpClient.dnsservers)-len, "%s,", token);
374  len+=strlen(token)+1;
375  }
376  }
377  len=strlen(dhcpClient.dnsservers);
378  if(len > 0)
379  {
380  dhcpClient.dnsservers[len-1]='\0';
381  }
382  ret=OK;
383  }
384  pclose(cmdOP);
385  }
386  break;
387  case eDHCPv4Iprouters:
388  memset(dhcpClient.ipRouters, '\0', sizeof(dhcpClient.ipRouters));
389  memset(cmd, 0, sizeof cmd);
390  /*Get the default interface name and its gateway. If the interface name matches with the class interface, then fill iprouters */
391  snprintf(cmd, MAX_CMD_LEN - 1 ,"ip r|grep default| grep %s |awk '{printf $3}'",ifname);
392 #ifdef YOCTO_BUILD
393  cmdOP=v_secure_popen("r", "ip r|grep default| grep %s |awk '{printf $3}'",ifname);
394 #else
395  cmdOP=popen(cmd, "r");
396 #endif
397  if (cmdOP)
398  {
399  fgets(buffer, MAX_BUF_LEN, cmdOP);
400  if(buffer[0]!='\0')
401  {
402  snprintf(dhcpClient.ipRouters, sizeof(dhcpClient.ipRouters), "%s", buffer);
403  }
404  ret=OK;
405 #ifdef YOCTO_BUILD
406  v_secure_pclose(cmdOP);
407 #else
408  pclose(cmdOP);
409 #endif
410  }
411  break;
412  default:
413  ret=NOT_HANDLED;
414  }
415  return ret;
416 }
417 
418 bool hostIf_DHCPv4Client::isValidIPAddr(char* addr)
419 {
420  int i, count=0;
421  int retVal=1;
422  char temp[MAX_IP_LEN]={0};
423  char *tptr, *tptr1, *savePtr;
424  int val=0;
425  int alpha=0;
426  int valid=1;
427 
428  /*ipv4 address cannot be greater than 15 chars*/
429  if(strlen(addr)>15)
430  return 0;
431  strncpy(temp, addr, MAX_IP_LEN -1);
432  temp[MAX_IP_LEN-1]='\0';
433  /*Check if the address contains only numbers and has 3 dots.*/
434  for (i=0; temp[i]!='\0'; ((temp[i]=='.')?count++:(isdigit(temp[i])?1:alpha++)), i++);
435  do
436  {
437  if(count!=3)
438  {
439  retVal= 0;
440  break;
441  }
442  if(alpha)
443  {
444  retVal= 0;
445  break;
446  }
447  /*each segment in the IP address cannot be greater than 255 */
448  tptr=strtok_r(temp, ".", &savePtr);
449  if(tptr)
450  {
451  val=atoi(tptr);
452  if(val>255 || val < 0)
453  {
454  retVal= 0;
455  break;
456  }
457  while(count)
458  {
459  tptr=strtok_r(NULL, ".", &savePtr);
460  if(tptr)
461  {
462  val=atoi(tptr);
463  if(val>255 || val < 0)
464  {
465  retVal= 0;
466  break;
467  }
468  }
469  else
470  {
471  retVal= 0;
472  break;
473  }
474  count --;
475  }
476  }
477  else
478  {
479  retVal= 0;
480  break;
481  }
482  } while(0);
483  return retVal;
484 }
485 int hostIf_DHCPv4Client::getInterfaceName(char* ifname){
486  char cmd[MAX_CMD_LEN]={'\0'};
487  char opIfName[IFNAMSIZ+1]={'\0'};
488  FILE* cmdOP=NULL;
489  int retVal=NOK;
490 
491  snprintf(cmd,MAX_CMD_LEN - 1, "ip r | grep default | sed -n '%dp' | awk '{printf $5}'",this->dev_id);
492  cmdOP=popen(cmd,"r");
493  if (cmdOP)
494  {
495  fgets(opIfName,IFNAMSIZ,cmdOP);
496  if(opIfName[0]!='\0')
497  {
498  strncpy(ifname,opIfName,IFNAMSIZ);
499  retVal=OK;
500  }
501  else
502  {
503  retVal= NOK;
504  }
505  pclose(cmdOP);
506  }
507  return retVal;
508 }
hostIf_DHCPv4Client::hostIf_DHCPv4Client
hostIf_DHCPv4Client(int dev_id)
Class Constructor of the class hostIf_DHCPv4Client.
Definition: Device_DHCPv4_Client.cpp:49
hostIf_IPInterface::get_Interface_Name
int get_Interface_Name(HOSTIF_MsgData_t *stMsgData, bool *pChanged=NULL)
This function gets the IP Interface Name.It provides the textual name of the interface as assigned by...
Definition: Device_IP_Interface.cpp:638
_HostIf_MsgData_t
Definition: hostIf_tr69ReqHandler.h:170
hostIf_DHCPv4Client
This class provides the interface for getting device DHCPv4 Client information.
Definition: Device_DHCPv4_Client.h:151
Device_IP_Interface.h
The header file provides TR069 device IP interface information APIs.
hostIf_IP::get_Device_IP_InterfaceNumberOfEntries
static int get_Device_IP_InterfaceNumberOfEntries(HOSTIF_MsgData_t *)
Get the number of entries in the Interface table.
Definition: Device_IP.cpp:641
Device_DHCPv4_Client.h
The header file provides TR069 device DHCPv4 Client information APIs.
hostIf_DHCPv4Client::get_Device_DHCPv4_Client_DnsServer
int get_Device_DHCPv4_Client_DnsServer(HOSTIF_MsgData_t *stMsgData, bool *pChanged=NULL)
This gets the DNS server information used by the DHCP(Dynamic Host Configuration Protocol) v4 client ...
Definition: Device_DHCPv4_Client.cpp:200
_HostIf_MsgData_t::paramtype
HostIf_ParamType_t paramtype
Definition: hostIf_tr69ReqHandler.h:177
RDK_LOG
#define RDK_LOG
Definition: rdk_debug.h:258
DHCPv4Client
These values are the members variables of the DHCPv4Client structure.
Definition: Device_DHCPv4_Client.h:120
_HostIf_MsgData_t::paramValue
char paramValue[(4 *1024)]
Definition: hostIf_tr69ReqHandler.h:172
Device_IP.h
The header file provides TR069 device IP information APIs.
DHCPv4ClientMembers
DHCPv4ClientMembers
These values are the members of the DHCPv4ClientMembers.
Definition: Device_DHCPv4_Client.h:139
hostIf_DHCPv4Client::get_Device_DHCPv4_Client_InterfaceReference
int get_Device_DHCPv4_Client_InterfaceReference(HOSTIF_MsgData_t *stMsgData, bool *pChanged=NULL)
This gets the interface information used by the DHCP(Dynamic Host Configuration Protocol) v4 client d...
Definition: Device_DHCPv4_Client.cpp:167
hostIf_IPInterface
This class provides the hostIf IP interface for getting IP interface information.
Definition: Device_IP_Interface.h:224
hostIf_DHCPv4Client::get_Device_DHCPv4_Client_IPRouters
int get_Device_DHCPv4_Client_IPRouters(HOSTIF_MsgData_t *stMsgData, bool *pChanged=NULL)
This gets the IP Routers information used by the DHCP(Dynamic Host Configuration Protocol) v4 client ...
Definition: Device_DHCPv4_Client.cpp:233
put_int
void put_int(char *ptr, int val)
This function converts the input data to integer type.
Definition: hostIf_utils.cpp:152
_HostIf_MsgData_t::paramLen
short paramLen
Definition: hostIf_tr69ReqHandler.h:175