blob: e0b56eaba5c3f5bd32b82477ac450c84b1746c12 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include "Configuration.h"
2
3#include <stdio.h>
4#include <string.h>
5#include <errno.h>
6#include <stdlib.h>
7#include <stdarg.h>
8#include <sys/types.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#ifdef __VXWORKS__
12#include <ifLib.h>
13#include <inetLib.h>
14#else
15#include <ifaddrs.h>
16#endif
17
18#include "aos/aos_core.h"
19#ifndef __VXWORKS__
20#include "aos/common/unique_malloc_ptr.h"
21#endif
22
23namespace aos {
24namespace configuration {
25
26namespace {
27
28#ifdef __VXWORKS__
29const size_t kMaxAddrLength = INET_ADDR_LEN;
30#else
31// Including the terminating '\0'.
32const size_t kMaxAddrLength = 18;
33#endif
34// Returns whether or not the current IP address is in ownIPAddress.
35bool GetOwnIPAddress();
36
37#ifdef __VXWORKS__
38// vxworks doesn't have real asprintf.......
39static inline int aos_asprintf(size_t max_len, char **strp, const char *fmt, ...) {
40 *strp = static_cast<char *>(malloc(max_len));
41 if (*strp == NULL) {
42 return -1;
43 }
44 va_list argp;
45 va_start(argp, fmt);
46 const int r = vsnprintf(*strp, max_len, fmt, argp);
47 va_end(argp);
48 if (static_cast<uintmax_t>(r) >= max_len) {
49 errno = EOVERFLOW;
50 free(*strp);
51 return -1;
52 }
53 return r;
54}
55
56// 4-slot cRIO: motfec0
57// 8-slot cRIO port 1: fec0
58// ifShow will show you all of the ones on a cRIO
59const char *const kCrioNetInterfaces[] = {"fec0", "motfec0"};
60bool GetOwnIPAddress(char *buffer, size_t bufferSize) {
61 if (bufferSize < INET_ADDR_LEN) {
62 LOG(ERROR, "bufferSize(%jd) isn't >= INET_ADDR_LEN(%jd)\n",
63 static_cast<intmax_t>(bufferSize),
64 static_cast<intmax_t>(INET_ADDR_LEN));
65 return false;
66 }
67 for (size_t i = 0;
68 i < sizeof(kCrioNetInterfaces) / sizeof(kCrioNetInterfaces[0]); ++i) {
69 if (ifAddrGet(const_cast<char *>(kCrioNetInterfaces[i]), buffer) != OK) {
70 LOG(DEBUG, "ifAddrGet(\"%s\", %p) failed with %d: %s\n",
71 kCrioNetInterfaces[i], buffer, errno, strerror(errno));
72 } else {
73 return true;
74 }
75 }
76 LOG(ERROR, "couldn't get the cRIO's IP address\n");
77 return false;
78}
79#else
80static inline int aos_asprintf(size_t, char **strp, const char *fmt, ...) {
81 va_list argp;
82 va_start(argp, fmt);
83 const int r = vasprintf(strp, fmt, argp);
84 va_end(argp);
85 return r;
86}
87
88const char *const kAtomNetInterface = "eth0";
89bool GetOwnIPAddress(char *buffer, size_t bufferSize) {
90 ifaddrs *addrs;
91 if (getifaddrs(&addrs) != 0) {
92 LOG(ERROR, "getifaddrs(%p) failed with %d: %s\n", &addrs,
93 errno, strerror(errno));
94 return false;
95 }
96 // Smart pointers don't work very well for iterating through a linked list,
97 // but it does do a very nice job of making sure that addrs gets freed.
98 unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
99
100 for (; addrs != NULL; addrs = addrs->ifa_next) {
101 if (addrs->ifa_addr->sa_family == AF_INET) {
102 if (strcmp(kAtomNetInterface, addrs->ifa_name) == 0) {
103 const char *ipAddress = inet_ntoa(
104 reinterpret_cast<sockaddr_in *>(addrs->ifa_addr)->sin_addr);
105 strncpy(buffer, ipAddress, bufferSize);
106 return true;
107 }
108 }
109 }
110 LOG(ERROR, "couldn't find an AF_INET interface named \"%s\"\n",
111 kAtomNetInterface);
112 return false;
113}
114#endif
115
116const char *RawIPAddress(uint8_t last_part) {
117 char ownIPAddress[kMaxAddrLength];
118 if (!GetOwnIPAddress(ownIPAddress, sizeof(ownIPAddress))) {
119 return NULL;
120 }
121 char *last_dot = strrchr(ownIPAddress, '.');
122 if (last_dot == NULL) {
123 LOG(ERROR, "can't find any '.'s in \"%s\"\n", ownIPAddress);
124 return NULL;
125 }
126 *last_dot = '\0';
127
128 char *r;
129 if (aos_asprintf(kMaxAddrLength, &r, "%s.%hhu",
130 ownIPAddress, last_part) == -1) {
131 return NULL;
132 }
133 return r;
134}
135
136} // namespace
137
138const char *GetIPAddress(NetworkDevice device) {
139 switch (device) {
140 case NetworkDevice::kAtom:
141 return RawIPAddress(179);
142 case NetworkDevice::kCRIO:
143 return RawIPAddress(2);
144 }
145 LOG(FATAL, "Unknown network device.");
146 return NULL;
147}
148
149} // namespace configuration
150} // namespace aos