PageRenderTime 110ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/hv/tools/hv_kvp_daemon.c

https://bitbucket.org/bagyusz/android_kernel_alcatel_cocktail
C | 498 lines | 359 code | 60 blank | 79 comment | 45 complexity | 4b2789356b65d648493592957270b16b MD5 | raw file
  1. /*
  2. * An implementation of key value pair (KVP) functionality for Linux.
  3. *
  4. *
  5. * Copyright (C) 2010, Novell, Inc.
  6. * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License version 2 as published
  10. * by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  15. * NON INFRINGEMENT. See the GNU General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. */
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <sys/poll.h>
  26. #include <sys/utsname.h>
  27. #include <linux/types.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <arpa/inet.h>
  34. #include <linux/connector.h>
  35. #include <linux/netlink.h>
  36. #include <sys/socket.h>
  37. #include <ifaddrs.h>
  38. #include <netdb.h>
  39. #include <syslog.h>
  40. /*
  41. * KYS: TODO. Need to register these in the kernel.
  42. *
  43. * The following definitions are shared with the in-kernel component; do not
  44. * change any of this without making the corresponding changes in
  45. * the KVP kernel component.
  46. */
  47. #define CN_KVP_IDX 0x9 /* MSFT KVP functionality */
  48. #define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
  49. #define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
  50. /*
  51. * KVP protocol: The user mode component first registers with the
  52. * the kernel component. Subsequently, the kernel component requests, data
  53. * for the specified keys. In response to this message the user mode component
  54. * fills in the value corresponding to the specified key. We overload the
  55. * sequence field in the cn_msg header to define our KVP message types.
  56. *
  57. * We use this infrastructure for also supporting queries from user mode
  58. * application for state that may be maintained in the KVP kernel component.
  59. *
  60. * XXXKYS: Have a shared header file between the user and kernel (TODO)
  61. */
  62. enum kvp_op {
  63. KVP_REGISTER = 0, /* Register the user mode component*/
  64. KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
  65. KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
  66. KVP_USER_GET, /*User is requesting the value for the specified key*/
  67. KVP_USER_SET /*User is providing the value for the specified key*/
  68. };
  69. #define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512
  70. #define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048
  71. struct hv_ku_msg {
  72. __u32 kvp_index;
  73. __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
  74. __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
  75. };
  76. enum key_index {
  77. FullyQualifiedDomainName = 0,
  78. IntegrationServicesVersion, /*This key is serviced in the kernel*/
  79. NetworkAddressIPv4,
  80. NetworkAddressIPv6,
  81. OSBuildNumber,
  82. OSName,
  83. OSMajorVersion,
  84. OSMinorVersion,
  85. OSVersion,
  86. ProcessorArchitecture
  87. };
  88. /*
  89. * End of shared definitions.
  90. */
  91. static char kvp_send_buffer[4096];
  92. static char kvp_recv_buffer[4096];
  93. static struct sockaddr_nl addr;
  94. static char *os_name = "";
  95. static char *os_major = "";
  96. static char *os_minor = "";
  97. static char *processor_arch;
  98. static char *os_build;
  99. static char *lic_version;
  100. static struct utsname uts_buf;
  101. void kvp_get_os_info(void)
  102. {
  103. FILE *file;
  104. char *p, buf[512];
  105. uname(&uts_buf);
  106. os_build = uts_buf.release;
  107. processor_arch= uts_buf.machine;
  108. file = fopen("/etc/SuSE-release", "r");
  109. if (file != NULL)
  110. goto kvp_osinfo_found;
  111. file = fopen("/etc/redhat-release", "r");
  112. if (file != NULL)
  113. goto kvp_osinfo_found;
  114. /*
  115. * Add code for other supported platforms.
  116. */
  117. /*
  118. * We don't have information about the os.
  119. */
  120. os_name = uts_buf.sysname;
  121. return;
  122. kvp_osinfo_found:
  123. /* up to three lines */
  124. p = fgets(buf, sizeof(buf), file);
  125. if (p) {
  126. p = strchr(buf, '\n');
  127. if (p)
  128. *p = '\0';
  129. p = strdup(buf);
  130. if (!p)
  131. goto done;
  132. os_name = p;
  133. /* second line */
  134. p = fgets(buf, sizeof(buf), file);
  135. if (p) {
  136. p = strchr(buf, '\n');
  137. if (p)
  138. *p = '\0';
  139. p = strdup(buf);
  140. if (!p)
  141. goto done;
  142. os_major = p;
  143. /* third line */
  144. p = fgets(buf, sizeof(buf), file);
  145. if (p) {
  146. p = strchr(buf, '\n');
  147. if (p)
  148. *p = '\0';
  149. p = strdup(buf);
  150. if (p)
  151. os_minor = p;
  152. }
  153. }
  154. }
  155. done:
  156. fclose(file);
  157. return;
  158. }
  159. static int
  160. kvp_get_ip_address(int family, char *buffer, int length)
  161. {
  162. struct ifaddrs *ifap;
  163. struct ifaddrs *curp;
  164. int ipv4_len = strlen("255.255.255.255") + 1;
  165. int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
  166. int offset = 0;
  167. const char *str;
  168. char tmp[50];
  169. int error = 0;
  170. /*
  171. * On entry into this function, the buffer is capable of holding the
  172. * maximum key value (2048 bytes).
  173. */
  174. if (getifaddrs(&ifap)) {
  175. strcpy(buffer, "getifaddrs failed\n");
  176. return 1;
  177. }
  178. curp = ifap;
  179. while (curp != NULL) {
  180. if ((curp->ifa_addr != NULL) &&
  181. (curp->ifa_addr->sa_family == family)) {
  182. if (family == AF_INET) {
  183. struct sockaddr_in *addr =
  184. (struct sockaddr_in *) curp->ifa_addr;
  185. str = inet_ntop(family, &addr->sin_addr,
  186. tmp, 50);
  187. if (str == NULL) {
  188. strcpy(buffer, "inet_ntop failed\n");
  189. error = 1;
  190. goto getaddr_done;
  191. }
  192. if (offset == 0)
  193. strcpy(buffer, tmp);
  194. else
  195. strcat(buffer, tmp);
  196. strcat(buffer, ";");
  197. offset += strlen(str) + 1;
  198. if ((length - offset) < (ipv4_len + 1))
  199. goto getaddr_done;
  200. } else {
  201. /*
  202. * We only support AF_INET and AF_INET6
  203. * and the list of addresses is separated by a ";".
  204. */
  205. struct sockaddr_in6 *addr =
  206. (struct sockaddr_in6 *) curp->ifa_addr;
  207. str = inet_ntop(family,
  208. &addr->sin6_addr.s6_addr,
  209. tmp, 50);
  210. if (str == NULL) {
  211. strcpy(buffer, "inet_ntop failed\n");
  212. error = 1;
  213. goto getaddr_done;
  214. }
  215. if (offset == 0)
  216. strcpy(buffer, tmp);
  217. else
  218. strcat(buffer, tmp);
  219. strcat(buffer, ";");
  220. offset += strlen(str) + 1;
  221. if ((length - offset) < (ipv6_len + 1))
  222. goto getaddr_done;
  223. }
  224. }
  225. curp = curp->ifa_next;
  226. }
  227. getaddr_done:
  228. freeifaddrs(ifap);
  229. return error;
  230. }
  231. static int
  232. kvp_get_domain_name(char *buffer, int length)
  233. {
  234. struct addrinfo hints, *info ;
  235. gethostname(buffer, length);
  236. int error = 0;
  237. memset(&hints, 0, sizeof(hints));
  238. hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
  239. hints.ai_socktype = SOCK_STREAM;
  240. hints.ai_flags = AI_CANONNAME;
  241. error = getaddrinfo(buffer, "http", &hints, &info);
  242. if (error != 0) {
  243. strcpy(buffer, "getaddrinfo failed\n");
  244. error = 1;
  245. goto get_domain_done;
  246. }
  247. strcpy(buffer, info->ai_canonname);
  248. get_domain_done:
  249. freeaddrinfo(info);
  250. return error;
  251. }
  252. static int
  253. netlink_send(int fd, struct cn_msg *msg)
  254. {
  255. struct nlmsghdr *nlh;
  256. unsigned int size;
  257. struct msghdr message;
  258. char buffer[64];
  259. struct iovec iov[2];
  260. size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
  261. nlh = (struct nlmsghdr *)buffer;
  262. nlh->nlmsg_seq = 0;
  263. nlh->nlmsg_pid = getpid();
  264. nlh->nlmsg_type = NLMSG_DONE;
  265. nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
  266. nlh->nlmsg_flags = 0;
  267. iov[0].iov_base = nlh;
  268. iov[0].iov_len = sizeof(*nlh);
  269. iov[1].iov_base = msg;
  270. iov[1].iov_len = size;
  271. memset(&message, 0, sizeof(message));
  272. message.msg_name = &addr;
  273. message.msg_namelen = sizeof(addr);
  274. message.msg_iov = iov;
  275. message.msg_iovlen = 2;
  276. return sendmsg(fd, &message, 0);
  277. }
  278. int main(void)
  279. {
  280. int fd, len, sock_opt;
  281. int error;
  282. struct cn_msg *message;
  283. struct pollfd pfd;
  284. struct nlmsghdr *incoming_msg;
  285. struct cn_msg *incoming_cn_msg;
  286. struct hv_ku_msg *hv_msg;
  287. char *p;
  288. char *key_value;
  289. char *key_name;
  290. daemon(1, 0);
  291. openlog("KVP", 0, LOG_USER);
  292. syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
  293. /*
  294. * Retrieve OS release information.
  295. */
  296. kvp_get_os_info();
  297. fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
  298. if (fd < 0) {
  299. syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
  300. exit(-1);
  301. }
  302. addr.nl_family = AF_NETLINK;
  303. addr.nl_pad = 0;
  304. addr.nl_pid = 0;
  305. addr.nl_groups = CN_KVP_IDX;
  306. error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
  307. if (error < 0) {
  308. syslog(LOG_ERR, "bind failed; error:%d", error);
  309. close(fd);
  310. exit(-1);
  311. }
  312. sock_opt = addr.nl_groups;
  313. setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
  314. /*
  315. * Register ourselves with the kernel.
  316. */
  317. message = (struct cn_msg *)kvp_send_buffer;
  318. message->id.idx = CN_KVP_IDX;
  319. message->id.val = CN_KVP_VAL;
  320. message->seq = KVP_REGISTER;
  321. message->ack = 0;
  322. message->len = 0;
  323. len = netlink_send(fd, message);
  324. if (len < 0) {
  325. syslog(LOG_ERR, "netlink_send failed; error:%d", len);
  326. close(fd);
  327. exit(-1);
  328. }
  329. pfd.fd = fd;
  330. while (1) {
  331. struct sockaddr *addr_p = (struct sockaddr *) &addr;
  332. socklen_t addr_l = sizeof(addr);
  333. pfd.events = POLLIN;
  334. pfd.revents = 0;
  335. poll(&pfd, 1, -1);
  336. len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0,
  337. addr_p, &addr_l);
  338. if (len < 0 || addr.nl_pid) {
  339. syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
  340. addr.nl_pid, errno, strerror(errno));
  341. close(fd);
  342. return -1;
  343. }
  344. incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
  345. incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
  346. switch (incoming_cn_msg->seq) {
  347. case KVP_REGISTER:
  348. /*
  349. * Driver is registering with us; stash away the version
  350. * information.
  351. */
  352. p = (char *)incoming_cn_msg->data;
  353. lic_version = malloc(strlen(p) + 1);
  354. if (lic_version) {
  355. strcpy(lic_version, p);
  356. syslog(LOG_INFO, "KVP LIC Version: %s",
  357. lic_version);
  358. } else {
  359. syslog(LOG_ERR, "malloc failed");
  360. }
  361. continue;
  362. case KVP_KERNEL_GET:
  363. break;
  364. default:
  365. continue;
  366. }
  367. hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data;
  368. key_name = (char *)hv_msg->kvp_key;
  369. key_value = (char *)hv_msg->kvp_value;
  370. switch (hv_msg->kvp_index) {
  371. case FullyQualifiedDomainName:
  372. kvp_get_domain_name(key_value,
  373. HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  374. strcpy(key_name, "FullyQualifiedDomainName");
  375. break;
  376. case IntegrationServicesVersion:
  377. strcpy(key_name, "IntegrationServicesVersion");
  378. strcpy(key_value, lic_version);
  379. break;
  380. case NetworkAddressIPv4:
  381. kvp_get_ip_address(AF_INET, key_value,
  382. HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  383. strcpy(key_name, "NetworkAddressIPv4");
  384. break;
  385. case NetworkAddressIPv6:
  386. kvp_get_ip_address(AF_INET6, key_value,
  387. HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  388. strcpy(key_name, "NetworkAddressIPv6");
  389. break;
  390. case OSBuildNumber:
  391. strcpy(key_value, os_build);
  392. strcpy(key_name, "OSBuildNumber");
  393. break;
  394. case OSName:
  395. strcpy(key_value, os_name);
  396. strcpy(key_name, "OSName");
  397. break;
  398. case OSMajorVersion:
  399. strcpy(key_value, os_major);
  400. strcpy(key_name, "OSMajorVersion");
  401. break;
  402. case OSMinorVersion:
  403. strcpy(key_value, os_minor);
  404. strcpy(key_name, "OSMinorVersion");
  405. break;
  406. case OSVersion:
  407. strcpy(key_value, os_build);
  408. strcpy(key_name, "OSVersion");
  409. break;
  410. case ProcessorArchitecture:
  411. strcpy(key_value, processor_arch);
  412. strcpy(key_name, "ProcessorArchitecture");
  413. break;
  414. default:
  415. strcpy(key_value, "Unknown Key");
  416. /*
  417. * We use a null key name to terminate enumeration.
  418. */
  419. strcpy(key_name, "");
  420. break;
  421. }
  422. /*
  423. * Send the value back to the kernel. The response is
  424. * already in the receive buffer. Update the cn_msg header to
  425. * reflect the key value that has been added to the message
  426. */
  427. incoming_cn_msg->id.idx = CN_KVP_IDX;
  428. incoming_cn_msg->id.val = CN_KVP_VAL;
  429. incoming_cn_msg->seq = KVP_USER_SET;
  430. incoming_cn_msg->ack = 0;
  431. incoming_cn_msg->len = sizeof(struct hv_ku_msg);
  432. len = netlink_send(fd, incoming_cn_msg);
  433. if (len < 0) {
  434. syslog(LOG_ERR, "net_link send failed; error:%d", len);
  435. exit(-1);
  436. }
  437. }
  438. }