OpENer - Open Source EtherNet/IP(TM) I/O Target Stack  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
networkconfig.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2018, Rockwell Automation, Inc.
3  * All rights reserved.
4  *
5  ******************************************************************************/
6 #include <string.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #include "ciptcpipinterface.h"
11 #include "networkconfig.h"
12 #include "cipcommon.h"
13 #include "ciperror.h"
14 #include "trace.h"
15 #include "opener_api.h"
16 
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <linux/if.h>
20 #include <net/if.h>
21 #include <netinet/in.h>
22 
23 #include <errno.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <arpa/inet.h>
27 #include <unistd.h>
28 
29 #define LOOPBACK_BINARY 0x7f000001
30 
31 void ConfigureMacAddress(const char *interface) {
32  struct ifreq ifr;
33  size_t if_name_len = strlen(interface);
34  if(if_name_len < sizeof(ifr.ifr_name) ) {
35  memcpy(ifr.ifr_name, interface, if_name_len);
36  ifr.ifr_name[if_name_len] = 0;
37  }
38  else{
39  OPENER_TRACE_INFO("interface name is too long");
40  }
41 
42  int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
43 
44  if(ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
45  memcpy(&(g_ethernet_link.physical_address), &ifr.ifr_hwaddr.sa_data,
47  }
48  CloseSocket(fd);
49 }
50 
51 EipStatus ConfigureNetworkInterface(const char *const network_interface) {
52 
53  struct ifreq ifr;
54  size_t if_name_len = strlen(network_interface);
55  if(if_name_len < sizeof(ifr.ifr_name) ) {
56  memcpy(ifr.ifr_name, network_interface, if_name_len);
57  ifr.ifr_name[if_name_len] = 0;
58  }
59  else{
60  OPENER_TRACE_INFO("interface name is too long\n");
61  }
62 
63  int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
64  int ipaddr = 0;
65  int netaddr = 0;
66  if(ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
67  ipaddr = ( (struct sockaddr_in *) &ifr.ifr_addr )->sin_addr.s_addr;
68  }
69  else{
70  return kEipStatusError;
71  }
72 
73  if(ioctl(fd, SIOCGIFNETMASK, &ifr) == 0) {
74  netaddr = ( (struct sockaddr_in *) &ifr.ifr_netmask )->sin_addr.s_addr;
75  }
76  else{
77  return kEipStatusError;
78  }
79 
82 
83  char route_location[] = "/proc/net/route";
84 
85  FILE *file_handle = fopen(route_location, "r");
86  char file_buffer[100] = { 0 };
87  char *gateway_string = NULL;
88  CipUdint gateway = 0;
89 
90  if(file_handle) {
91  char *needle_start = NULL;
92  while(NULL ==
93  (needle_start =
94  strstr(file_buffer,
95  network_interface) ) &&
96  fgets(file_buffer, sizeof(file_buffer), file_handle) ) {
97  }
98 
99  if(NULL != needle_start) {
100  char *strtok_save = NULL;
101  strtok_r(needle_start, " \t", &strtok_save);
102  strtok_r(needle_start, " \t", &strtok_save);
103  gateway_string = strtok_r(needle_start, "\t", &strtok_save);
104  }
105  else{
106  OPENER_TRACE_ERR("network interface: %s not found", network_interface);
107  fclose(file_handle);
108  exit(1);
109  }
110  }
111 
112  if(inet_pton(AF_INET, gateway_string, &gateway) == 1) {
113  if(LOOPBACK_BINARY != gateway) {
115  }
116  else{
118  }
119  }
120  else{
122  }
123 
124  /* calculate the CIP multicast address. The multicast address is calculated, not input*/
125  EipUint32 host_id = ntohl(interface_configuration_.ip_address) & ~ntohl(
126  interface_configuration_.network_mask); /* see CIP spec 3-5.3 for multicast address algorithm*/
127  host_id -= 1;
128  host_id &= 0x3ff;
129 
131  htonl(ntohl(inet_addr("239.192.1.0") ) + (host_id << 5) );
132 
133  CloseSocket(fd);
134  fclose(file_handle);
135 
136  return kEipStatusOk;
137 }
138 
140  char resolv_conf_file[] = "/etc/resolv.conf";
141  FILE *file_handle = fopen(resolv_conf_file, "r");
142  char *file_buffer = NULL;
143  size_t file_length;
144  char *domain_name_string = NULL;
145  char *dns1_string = NULL;
146  char *dns2_string = NULL;
147 
148  if(file_handle) {
149  fseek(file_handle, 0, SEEK_END);
150  file_length = ftell(file_handle);
151  fseek(file_handle, 0, SEEK_SET);
152  file_buffer = malloc(file_length);
153  if(file_buffer) {
154  fread(file_buffer, 1, file_length, file_handle);
155  fclose(file_handle);
156  }
157  else{
158  OPENER_TRACE_ERR("Could not allocate memory for reading file %s\n",
159  resolv_conf_file);
160  fclose(file_handle);
161  exit(1);
162  }
163  } else {
164  OPENER_TRACE_ERR("Could not open file %s\n", resolv_conf_file);
165  exit(1);
166  }
167 
168  if(strstr(file_buffer, "domain") ) {
169  char *strtok_save = NULL;
170  strtok_r(file_buffer, " ", &strtok_save);
171  domain_name_string = strtok_r(file_buffer, "\n", &strtok_save);
172 
174  /* if the string is already set to a value we have to free the resources
175  * before we can set the new value in order to avoid memory leaks.
176  */
178  }
179  interface_configuration_.domain_name.length = strlen(domain_name_string);
180 
184  sizeof(EipByte) );
187  sizeof(EipByte),
188  "%s",
189  domain_name_string);
190  }
191  else{
193  }
194  }
195 
196  if(strstr(file_buffer, "nameserver") ) {
197  char *strtok_save = NULL;
198  strtok_r(file_buffer, " ", &strtok_save);
199  dns1_string = strtok_r(NULL, "\n", &strtok_save);
200 
201  inet_pton(AF_INET, dns1_string, &interface_configuration_.name_server);
202  }
203 
204  if(strstr(file_buffer, "nameserver ") ) {
205  char *strtok_save = NULL;
206  strtok_r(file_buffer, " ", &strtok_save);
207  dns2_string = strtok_r(file_buffer, "\n", &strtok_save);
208 
209  inet_pton(AF_INET, dns2_string, &interface_configuration_.name_server_2);
210  }
211 
212  free(file_buffer);
213 }
214 
216  char name[1024] = { 0 };
217  gethostname(name, sizeof(name) );
218 
219  if(NULL != hostname_.string) {
220  /* if the string is already set to a value we have to free the resources
221  * before we can set the new value in order to avoid memory leaks.
222  */
224  }
225  hostname_.length = strlen(name);
226  if(hostname_.length) {
227  hostname_.string =
228  (EipByte *) CipCalloc(hostname_.length + 1, sizeof(EipByte) );
229  snprintf( (char *)hostname_.string,
230  (hostname_.length + 1) * sizeof(EipByte), "%s", name );
231  }
232  else{
233  hostname_.string = NULL;
234  }
235 }
Tracing infrastructure for OpENer.
EipUint8 physical_address[6]
#define OPENER_TRACE_ERR(...)
Definition: trace.h:86
MulticastAddressConfiguration g_multicast_configuration
#9 The multicast configuration for this device
void * CipCalloc(size_t number_of_elements, size_t size_of_element)
Allocate memory for the CIP stack.
#define LOOPBACK_BINARY
Definition: networkconfig.c:29
EipUint16 length
Definition: ciptypes.h:139
EipStatus
EIP stack status enum.
Definition: typedefs.h:93
uint32_t EipUint32
Definition: typedefs.h:34
void ConfigureMacAddress(const char *interface)
Configure the MAC address of the device.
Definition: networkconfig.c:31
#define OPENER_TRACE_INFO(...)
Definition: trace.h:89
void CipFree(void *data)
Free memory allocated by the OpENer.
EipByte * string
Definition: ciptypes.h:140
Public interface of the TCP/IP Interface Object.
CipTcpIpNetworkInterfaceConfiguration interface_configuration_
uint8_t EipByte
EIP Data type definitions.
Definition: typedefs.h:28
EipStatus ConfigureNetworkInterface(const char *const network_interface)
Configure the data of the network interface of the device.
Definition: networkconfig.c:27
CipString hostname_
uint32_t CipUdint
Definition: typedefs.h:48
void ConfigureDomainName()
Configure the domain name of the device.
Definition: networkconfig.c:87
void CloseSocket(const int socket_handle)
Close the given socket and clean up the stack.
void ConfigureHostName(void)
Configure the host name of the device.