hv_kvp_daemon.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  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/hyperv.h>
  36. #include <linux/netlink.h>
  37. #include <ifaddrs.h>
  38. #include <netdb.h>
  39. #include <syslog.h>
  40. #include <sys/stat.h>
  41. #include <fcntl.h>
  42. /*
  43. * KVP protocol: The user mode component first registers with the
  44. * the kernel component. Subsequently, the kernel component requests, data
  45. * for the specified keys. In response to this message the user mode component
  46. * fills in the value corresponding to the specified key. We overload the
  47. * sequence field in the cn_msg header to define our KVP message types.
  48. *
  49. * We use this infrastructure for also supporting queries from user mode
  50. * application for state that may be maintained in the KVP kernel component.
  51. *
  52. */
  53. enum key_index {
  54. FullyQualifiedDomainName = 0,
  55. IntegrationServicesVersion, /*This key is serviced in the kernel*/
  56. NetworkAddressIPv4,
  57. NetworkAddressIPv6,
  58. OSBuildNumber,
  59. OSName,
  60. OSMajorVersion,
  61. OSMinorVersion,
  62. OSVersion,
  63. ProcessorArchitecture
  64. };
  65. static char kvp_send_buffer[4096];
  66. static char kvp_recv_buffer[4096 * 2];
  67. static struct sockaddr_nl addr;
  68. static int in_hand_shake = 1;
  69. static char *os_name = "";
  70. static char *os_major = "";
  71. static char *os_minor = "";
  72. static char *processor_arch;
  73. static char *os_build;
  74. static char *lic_version = "Unknown version";
  75. static struct utsname uts_buf;
  76. #define MAX_FILE_NAME 100
  77. #define ENTRIES_PER_BLOCK 50
  78. struct kvp_record {
  79. __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
  80. __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
  81. };
  82. struct kvp_file_state {
  83. int fd;
  84. int num_blocks;
  85. struct kvp_record *records;
  86. int num_records;
  87. __u8 fname[MAX_FILE_NAME];
  88. };
  89. static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT];
  90. static void kvp_acquire_lock(int pool)
  91. {
  92. struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
  93. fl.l_pid = getpid();
  94. if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
  95. syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
  96. exit(-1);
  97. }
  98. }
  99. static void kvp_release_lock(int pool)
  100. {
  101. struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
  102. fl.l_pid = getpid();
  103. if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
  104. perror("fcntl");
  105. syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
  106. exit(-1);
  107. }
  108. }
  109. static void kvp_update_file(int pool)
  110. {
  111. FILE *filep;
  112. size_t bytes_written;
  113. /*
  114. * We are going to write our in-memory registry out to
  115. * disk; acquire the lock first.
  116. */
  117. kvp_acquire_lock(pool);
  118. filep = fopen(kvp_file_info[pool].fname, "w");
  119. if (!filep) {
  120. kvp_release_lock(pool);
  121. syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
  122. exit(-1);
  123. }
  124. bytes_written = fwrite(kvp_file_info[pool].records,
  125. sizeof(struct kvp_record),
  126. kvp_file_info[pool].num_records, filep);
  127. fflush(filep);
  128. kvp_release_lock(pool);
  129. }
  130. static void kvp_update_mem_state(int pool)
  131. {
  132. FILE *filep;
  133. size_t records_read = 0;
  134. struct kvp_record *record = kvp_file_info[pool].records;
  135. struct kvp_record *readp;
  136. int num_blocks = kvp_file_info[pool].num_blocks;
  137. int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
  138. kvp_acquire_lock(pool);
  139. filep = fopen(kvp_file_info[pool].fname, "r");
  140. if (!filep) {
  141. kvp_release_lock(pool);
  142. syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
  143. exit(-1);
  144. }
  145. while (!feof(filep)) {
  146. readp = &record[records_read];
  147. records_read += fread(readp, sizeof(struct kvp_record),
  148. ENTRIES_PER_BLOCK * num_blocks,
  149. filep);
  150. if (!feof(filep)) {
  151. /*
  152. * We have more data to read.
  153. */
  154. num_blocks++;
  155. record = realloc(record, alloc_unit * num_blocks);
  156. if (record == NULL) {
  157. syslog(LOG_ERR, "malloc failed");
  158. exit(-1);
  159. }
  160. continue;
  161. }
  162. break;
  163. }
  164. kvp_file_info[pool].num_blocks = num_blocks;
  165. kvp_file_info[pool].records = record;
  166. kvp_file_info[pool].num_records = records_read;
  167. kvp_release_lock(pool);
  168. }
  169. static int kvp_file_init(void)
  170. {
  171. int ret, fd;
  172. FILE *filep;
  173. size_t records_read;
  174. __u8 *fname;
  175. struct kvp_record *record;
  176. struct kvp_record *readp;
  177. int num_blocks;
  178. int i;
  179. int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
  180. if (access("/var/opt/hyperv", F_OK)) {
  181. if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
  182. syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
  183. exit(-1);
  184. }
  185. }
  186. for (i = 0; i < KVP_POOL_COUNT; i++) {
  187. fname = kvp_file_info[i].fname;
  188. records_read = 0;
  189. num_blocks = 1;
  190. sprintf(fname, "/var/opt/hyperv/.kvp_pool_%d", i);
  191. fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
  192. if (fd == -1)
  193. return 1;
  194. filep = fopen(fname, "r");
  195. if (!filep)
  196. return 1;
  197. record = malloc(alloc_unit * num_blocks);
  198. if (record == NULL) {
  199. fclose(filep);
  200. return 1;
  201. }
  202. while (!feof(filep)) {
  203. readp = &record[records_read];
  204. records_read += fread(readp, sizeof(struct kvp_record),
  205. ENTRIES_PER_BLOCK,
  206. filep);
  207. if (!feof(filep)) {
  208. /*
  209. * We have more data to read.
  210. */
  211. num_blocks++;
  212. record = realloc(record, alloc_unit *
  213. num_blocks);
  214. if (record == NULL) {
  215. fclose(filep);
  216. return 1;
  217. }
  218. continue;
  219. }
  220. break;
  221. }
  222. kvp_file_info[i].fd = fd;
  223. kvp_file_info[i].num_blocks = num_blocks;
  224. kvp_file_info[i].records = record;
  225. kvp_file_info[i].num_records = records_read;
  226. fclose(filep);
  227. }
  228. return 0;
  229. }
  230. static int kvp_key_delete(int pool, __u8 *key, int key_size)
  231. {
  232. int i;
  233. int j, k;
  234. int num_records;
  235. struct kvp_record *record;
  236. /*
  237. * First update the in-memory state.
  238. */
  239. kvp_update_mem_state(pool);
  240. num_records = kvp_file_info[pool].num_records;
  241. record = kvp_file_info[pool].records;
  242. for (i = 0; i < num_records; i++) {
  243. if (memcmp(key, record[i].key, key_size))
  244. continue;
  245. /*
  246. * Found a match; just move the remaining
  247. * entries up.
  248. */
  249. if (i == num_records) {
  250. kvp_file_info[pool].num_records--;
  251. kvp_update_file(pool);
  252. return 0;
  253. }
  254. j = i;
  255. k = j + 1;
  256. for (; k < num_records; k++) {
  257. strcpy(record[j].key, record[k].key);
  258. strcpy(record[j].value, record[k].value);
  259. j++;
  260. }
  261. kvp_file_info[pool].num_records--;
  262. kvp_update_file(pool);
  263. return 0;
  264. }
  265. return 1;
  266. }
  267. static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
  268. int value_size)
  269. {
  270. int i;
  271. int j, k;
  272. int num_records;
  273. struct kvp_record *record;
  274. int num_blocks;
  275. if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
  276. (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
  277. return 1;
  278. /*
  279. * First update the in-memory state.
  280. */
  281. kvp_update_mem_state(pool);
  282. num_records = kvp_file_info[pool].num_records;
  283. record = kvp_file_info[pool].records;
  284. num_blocks = kvp_file_info[pool].num_blocks;
  285. for (i = 0; i < num_records; i++) {
  286. if (memcmp(key, record[i].key, key_size))
  287. continue;
  288. /*
  289. * Found a match; just update the value -
  290. * this is the modify case.
  291. */
  292. memcpy(record[i].value, value, value_size);
  293. kvp_update_file(pool);
  294. return 0;
  295. }
  296. /*
  297. * Need to add a new entry;
  298. */
  299. if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
  300. /* Need to allocate a larger array for reg entries. */
  301. record = realloc(record, sizeof(struct kvp_record) *
  302. ENTRIES_PER_BLOCK * (num_blocks + 1));
  303. if (record == NULL)
  304. return 1;
  305. kvp_file_info[pool].num_blocks++;
  306. }
  307. memcpy(record[i].value, value, value_size);
  308. memcpy(record[i].key, key, key_size);
  309. kvp_file_info[pool].records = record;
  310. kvp_file_info[pool].num_records++;
  311. kvp_update_file(pool);
  312. return 0;
  313. }
  314. static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
  315. int value_size)
  316. {
  317. int i;
  318. int num_records;
  319. struct kvp_record *record;
  320. if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
  321. (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
  322. return 1;
  323. /*
  324. * First update the in-memory state.
  325. */
  326. kvp_update_mem_state(pool);
  327. num_records = kvp_file_info[pool].num_records;
  328. record = kvp_file_info[pool].records;
  329. for (i = 0; i < num_records; i++) {
  330. if (memcmp(key, record[i].key, key_size))
  331. continue;
  332. /*
  333. * Found a match; just copy the value out.
  334. */
  335. memcpy(value, record[i].value, value_size);
  336. return 0;
  337. }
  338. return 1;
  339. }
  340. static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
  341. __u8 *value, int value_size)
  342. {
  343. struct kvp_record *record;
  344. /*
  345. * First update our in-memory database.
  346. */
  347. kvp_update_mem_state(pool);
  348. record = kvp_file_info[pool].records;
  349. if (index >= kvp_file_info[pool].num_records) {
  350. return 1;
  351. }
  352. memcpy(key, record[index].key, key_size);
  353. memcpy(value, record[index].value, value_size);
  354. return 0;
  355. }
  356. void kvp_get_os_info(void)
  357. {
  358. FILE *file;
  359. char *p, buf[512];
  360. uname(&uts_buf);
  361. os_build = uts_buf.release;
  362. processor_arch = uts_buf.machine;
  363. /*
  364. * The current windows host (win7) expects the build
  365. * string to be of the form: x.y.z
  366. * Strip additional information we may have.
  367. */
  368. p = strchr(os_build, '-');
  369. if (p)
  370. *p = '\0';
  371. file = fopen("/etc/SuSE-release", "r");
  372. if (file != NULL)
  373. goto kvp_osinfo_found;
  374. file = fopen("/etc/redhat-release", "r");
  375. if (file != NULL)
  376. goto kvp_osinfo_found;
  377. /*
  378. * Add code for other supported platforms.
  379. */
  380. /*
  381. * We don't have information about the os.
  382. */
  383. os_name = uts_buf.sysname;
  384. return;
  385. kvp_osinfo_found:
  386. /* up to three lines */
  387. p = fgets(buf, sizeof(buf), file);
  388. if (p) {
  389. p = strchr(buf, '\n');
  390. if (p)
  391. *p = '\0';
  392. p = strdup(buf);
  393. if (!p)
  394. goto done;
  395. os_name = p;
  396. /* second line */
  397. p = fgets(buf, sizeof(buf), file);
  398. if (p) {
  399. p = strchr(buf, '\n');
  400. if (p)
  401. *p = '\0';
  402. p = strdup(buf);
  403. if (!p)
  404. goto done;
  405. os_major = p;
  406. /* third line */
  407. p = fgets(buf, sizeof(buf), file);
  408. if (p) {
  409. p = strchr(buf, '\n');
  410. if (p)
  411. *p = '\0';
  412. p = strdup(buf);
  413. if (p)
  414. os_minor = p;
  415. }
  416. }
  417. }
  418. done:
  419. fclose(file);
  420. return;
  421. }
  422. static void kvp_process_ipconfig_file(char *cmd,
  423. char *config_buf, int len,
  424. int element_size, int offset)
  425. {
  426. char buf[256];
  427. char *p;
  428. char *x;
  429. FILE *file;
  430. /*
  431. * First execute the command.
  432. */
  433. file = popen(cmd, "r");
  434. if (file == NULL)
  435. return;
  436. if (offset == 0)
  437. memset(config_buf, 0, len);
  438. while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
  439. if ((len - strlen(config_buf)) < (element_size + 1))
  440. break;
  441. x = strchr(p, '\n');
  442. *x = '\0';
  443. strcat(config_buf, p);
  444. strcat(config_buf, ";");
  445. }
  446. pclose(file);
  447. }
  448. static void kvp_get_ipconfig_info(char *if_name,
  449. struct hv_kvp_ipaddr_value *buffer)
  450. {
  451. char cmd[512];
  452. /*
  453. * Get the address of default gateway (ipv4).
  454. */
  455. sprintf(cmd, "%s %s", "ip route show dev", if_name);
  456. strcat(cmd, " | awk '/default/ {print $3 }'");
  457. /*
  458. * Execute the command to gather gateway info.
  459. */
  460. kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
  461. (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
  462. /*
  463. * Get the address of default gateway (ipv6).
  464. */
  465. sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name);
  466. strcat(cmd, " | awk '/default/ {print $3 }'");
  467. /*
  468. * Execute the command to gather gateway info (ipv6).
  469. */
  470. kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
  471. (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
  472. }
  473. static unsigned int hweight32(unsigned int *w)
  474. {
  475. unsigned int res = *w - ((*w >> 1) & 0x55555555);
  476. res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
  477. res = (res + (res >> 4)) & 0x0F0F0F0F;
  478. res = res + (res >> 8);
  479. return (res + (res >> 16)) & 0x000000FF;
  480. }
  481. static int kvp_process_ip_address(void *addrp,
  482. int family, char *buffer,
  483. int length, int *offset)
  484. {
  485. struct sockaddr_in *addr;
  486. struct sockaddr_in6 *addr6;
  487. int addr_length;
  488. char tmp[50];
  489. const char *str;
  490. if (family == AF_INET) {
  491. addr = (struct sockaddr_in *)addrp;
  492. str = inet_ntop(family, &addr->sin_addr, tmp, 50);
  493. addr_length = INET_ADDRSTRLEN;
  494. } else {
  495. addr6 = (struct sockaddr_in6 *)addrp;
  496. str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
  497. addr_length = INET6_ADDRSTRLEN;
  498. }
  499. if ((length - *offset) < addr_length + 1)
  500. return 1;
  501. if (str == NULL) {
  502. strcpy(buffer, "inet_ntop failed\n");
  503. return 1;
  504. }
  505. if (*offset == 0)
  506. strcpy(buffer, tmp);
  507. else
  508. strcat(buffer, tmp);
  509. strcat(buffer, ";");
  510. *offset += strlen(str) + 1;
  511. return 0;
  512. }
  513. static int
  514. kvp_get_ip_address(int family, char *if_name, int op,
  515. void *out_buffer, int length)
  516. {
  517. struct ifaddrs *ifap;
  518. struct ifaddrs *curp;
  519. int offset = 0;
  520. int sn_offset = 0;
  521. int error = 0;
  522. char *buffer;
  523. struct hv_kvp_ipaddr_value *ip_buffer;
  524. char cidr_mask[5]; /* /xyz */
  525. int weight;
  526. int i;
  527. unsigned int *w;
  528. char *sn_str;
  529. struct sockaddr_in6 *addr6;
  530. if (op == KVP_OP_ENUMERATE) {
  531. buffer = out_buffer;
  532. } else {
  533. ip_buffer = out_buffer;
  534. buffer = (char *)ip_buffer->ip_addr;
  535. ip_buffer->addr_family = 0;
  536. }
  537. /*
  538. * On entry into this function, the buffer is capable of holding the
  539. * maximum key value.
  540. */
  541. if (getifaddrs(&ifap)) {
  542. strcpy(buffer, "getifaddrs failed\n");
  543. return 1;
  544. }
  545. curp = ifap;
  546. while (curp != NULL) {
  547. if (curp->ifa_addr == NULL) {
  548. curp = curp->ifa_next;
  549. continue;
  550. }
  551. if ((if_name != NULL) &&
  552. (strncmp(curp->ifa_name, if_name, strlen(if_name)))) {
  553. /*
  554. * We want info about a specific interface;
  555. * just continue.
  556. */
  557. curp = curp->ifa_next;
  558. continue;
  559. }
  560. /*
  561. * We only support two address families: AF_INET and AF_INET6.
  562. * If a family value of 0 is specified, we collect both
  563. * supported address families; if not we gather info on
  564. * the specified address family.
  565. */
  566. if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
  567. curp = curp->ifa_next;
  568. continue;
  569. }
  570. if ((curp->ifa_addr->sa_family != AF_INET) &&
  571. (curp->ifa_addr->sa_family != AF_INET6)) {
  572. curp = curp->ifa_next;
  573. continue;
  574. }
  575. if (op == KVP_OP_GET_IP_INFO) {
  576. /*
  577. * Gather info other than the IP address.
  578. * IP address info will be gathered later.
  579. */
  580. if (curp->ifa_addr->sa_family == AF_INET) {
  581. ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
  582. /*
  583. * Get subnet info.
  584. */
  585. error = kvp_process_ip_address(
  586. curp->ifa_netmask,
  587. AF_INET,
  588. (char *)
  589. ip_buffer->sub_net,
  590. length,
  591. &sn_offset);
  592. if (error)
  593. goto gather_ipaddr;
  594. } else {
  595. ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
  596. /*
  597. * Get subnet info in CIDR format.
  598. */
  599. weight = 0;
  600. sn_str = (char *)ip_buffer->sub_net;
  601. addr6 = (struct sockaddr_in6 *)
  602. curp->ifa_netmask;
  603. w = addr6->sin6_addr.s6_addr32;
  604. for (i = 0; i < 4; i++)
  605. weight += hweight32(&w[i]);
  606. sprintf(cidr_mask, "/%d", weight);
  607. if ((length - sn_offset) <
  608. (strlen(cidr_mask) + 1))
  609. goto gather_ipaddr;
  610. if (sn_offset == 0)
  611. strcpy(sn_str, cidr_mask);
  612. else
  613. strcat(sn_str, cidr_mask);
  614. strcat((char *)ip_buffer->sub_net, ";");
  615. sn_offset += strlen(sn_str) + 1;
  616. }
  617. /*
  618. * Collect other ip related configuration info.
  619. */
  620. kvp_get_ipconfig_info(if_name, ip_buffer);
  621. }
  622. gather_ipaddr:
  623. error = kvp_process_ip_address(curp->ifa_addr,
  624. curp->ifa_addr->sa_family,
  625. buffer,
  626. length, &offset);
  627. if (error)
  628. goto getaddr_done;
  629. curp = curp->ifa_next;
  630. }
  631. getaddr_done:
  632. freeifaddrs(ifap);
  633. return error;
  634. }
  635. static int
  636. kvp_get_domain_name(char *buffer, int length)
  637. {
  638. struct addrinfo hints, *info ;
  639. int error = 0;
  640. gethostname(buffer, length);
  641. memset(&hints, 0, sizeof(hints));
  642. hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
  643. hints.ai_socktype = SOCK_STREAM;
  644. hints.ai_flags = AI_CANONNAME;
  645. error = getaddrinfo(buffer, NULL, &hints, &info);
  646. if (error != 0) {
  647. strcpy(buffer, "getaddrinfo failed\n");
  648. return error;
  649. }
  650. strcpy(buffer, info->ai_canonname);
  651. freeaddrinfo(info);
  652. return error;
  653. }
  654. static int
  655. netlink_send(int fd, struct cn_msg *msg)
  656. {
  657. struct nlmsghdr *nlh;
  658. unsigned int size;
  659. struct msghdr message;
  660. char buffer[64];
  661. struct iovec iov[2];
  662. size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
  663. nlh = (struct nlmsghdr *)buffer;
  664. nlh->nlmsg_seq = 0;
  665. nlh->nlmsg_pid = getpid();
  666. nlh->nlmsg_type = NLMSG_DONE;
  667. nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
  668. nlh->nlmsg_flags = 0;
  669. iov[0].iov_base = nlh;
  670. iov[0].iov_len = sizeof(*nlh);
  671. iov[1].iov_base = msg;
  672. iov[1].iov_len = size;
  673. memset(&message, 0, sizeof(message));
  674. message.msg_name = &addr;
  675. message.msg_namelen = sizeof(addr);
  676. message.msg_iov = iov;
  677. message.msg_iovlen = 2;
  678. return sendmsg(fd, &message, 0);
  679. }
  680. int main(void)
  681. {
  682. int fd, len, sock_opt;
  683. int error;
  684. struct cn_msg *message;
  685. struct pollfd pfd;
  686. struct nlmsghdr *incoming_msg;
  687. struct cn_msg *incoming_cn_msg;
  688. struct hv_kvp_msg *hv_msg;
  689. char *p;
  690. char *key_value;
  691. char *key_name;
  692. int op;
  693. int pool;
  694. daemon(1, 0);
  695. openlog("KVP", 0, LOG_USER);
  696. syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
  697. /*
  698. * Retrieve OS release information.
  699. */
  700. kvp_get_os_info();
  701. if (kvp_file_init()) {
  702. syslog(LOG_ERR, "Failed to initialize the pools");
  703. exit(-1);
  704. }
  705. fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
  706. if (fd < 0) {
  707. syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
  708. exit(-1);
  709. }
  710. addr.nl_family = AF_NETLINK;
  711. addr.nl_pad = 0;
  712. addr.nl_pid = 0;
  713. addr.nl_groups = CN_KVP_IDX;
  714. error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
  715. if (error < 0) {
  716. syslog(LOG_ERR, "bind failed; error:%d", error);
  717. close(fd);
  718. exit(-1);
  719. }
  720. sock_opt = addr.nl_groups;
  721. setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
  722. /*
  723. * Register ourselves with the kernel.
  724. */
  725. message = (struct cn_msg *)kvp_send_buffer;
  726. message->id.idx = CN_KVP_IDX;
  727. message->id.val = CN_KVP_VAL;
  728. hv_msg = (struct hv_kvp_msg *)message->data;
  729. hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
  730. message->ack = 0;
  731. message->len = sizeof(struct hv_kvp_msg);
  732. len = netlink_send(fd, message);
  733. if (len < 0) {
  734. syslog(LOG_ERR, "netlink_send failed; error:%d", len);
  735. close(fd);
  736. exit(-1);
  737. }
  738. pfd.fd = fd;
  739. while (1) {
  740. struct sockaddr *addr_p = (struct sockaddr *) &addr;
  741. socklen_t addr_l = sizeof(addr);
  742. pfd.events = POLLIN;
  743. pfd.revents = 0;
  744. poll(&pfd, 1, -1);
  745. len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0,
  746. addr_p, &addr_l);
  747. if (len < 0 || addr.nl_pid) {
  748. syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
  749. addr.nl_pid, errno, strerror(errno));
  750. close(fd);
  751. return -1;
  752. }
  753. incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
  754. incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
  755. hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
  756. /*
  757. * We will use the KVP header information to pass back
  758. * the error from this daemon. So, first copy the state
  759. * and set the error code to success.
  760. */
  761. op = hv_msg->kvp_hdr.operation;
  762. pool = hv_msg->kvp_hdr.pool;
  763. hv_msg->error = HV_S_OK;
  764. if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
  765. /*
  766. * Driver is registering with us; stash away the version
  767. * information.
  768. */
  769. in_hand_shake = 0;
  770. p = (char *)hv_msg->body.kvp_register.version;
  771. lic_version = malloc(strlen(p) + 1);
  772. if (lic_version) {
  773. strcpy(lic_version, p);
  774. syslog(LOG_INFO, "KVP LIC Version: %s",
  775. lic_version);
  776. } else {
  777. syslog(LOG_ERR, "malloc failed");
  778. }
  779. continue;
  780. }
  781. switch (op) {
  782. case KVP_OP_SET:
  783. if (kvp_key_add_or_modify(pool,
  784. hv_msg->body.kvp_set.data.key,
  785. hv_msg->body.kvp_set.data.key_size,
  786. hv_msg->body.kvp_set.data.value,
  787. hv_msg->body.kvp_set.data.value_size))
  788. hv_msg->error = HV_S_CONT;
  789. break;
  790. case KVP_OP_GET:
  791. if (kvp_get_value(pool,
  792. hv_msg->body.kvp_set.data.key,
  793. hv_msg->body.kvp_set.data.key_size,
  794. hv_msg->body.kvp_set.data.value,
  795. hv_msg->body.kvp_set.data.value_size))
  796. hv_msg->error = HV_S_CONT;
  797. break;
  798. case KVP_OP_DELETE:
  799. if (kvp_key_delete(pool,
  800. hv_msg->body.kvp_delete.key,
  801. hv_msg->body.kvp_delete.key_size))
  802. hv_msg->error = HV_S_CONT;
  803. break;
  804. default:
  805. break;
  806. }
  807. if (op != KVP_OP_ENUMERATE)
  808. goto kvp_done;
  809. /*
  810. * If the pool is KVP_POOL_AUTO, dynamically generate
  811. * both the key and the value; if not read from the
  812. * appropriate pool.
  813. */
  814. if (pool != KVP_POOL_AUTO) {
  815. if (kvp_pool_enumerate(pool,
  816. hv_msg->body.kvp_enum_data.index,
  817. hv_msg->body.kvp_enum_data.data.key,
  818. HV_KVP_EXCHANGE_MAX_KEY_SIZE,
  819. hv_msg->body.kvp_enum_data.data.value,
  820. HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
  821. hv_msg->error = HV_S_CONT;
  822. goto kvp_done;
  823. }
  824. hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
  825. key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
  826. key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
  827. switch (hv_msg->body.kvp_enum_data.index) {
  828. case FullyQualifiedDomainName:
  829. kvp_get_domain_name(key_value,
  830. HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  831. strcpy(key_name, "FullyQualifiedDomainName");
  832. break;
  833. case IntegrationServicesVersion:
  834. strcpy(key_name, "IntegrationServicesVersion");
  835. strcpy(key_value, lic_version);
  836. break;
  837. case NetworkAddressIPv4:
  838. kvp_get_ip_address(AF_INET, NULL, KVP_OP_ENUMERATE,
  839. key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  840. strcpy(key_name, "NetworkAddressIPv4");
  841. break;
  842. case NetworkAddressIPv6:
  843. kvp_get_ip_address(AF_INET6, NULL, KVP_OP_ENUMERATE,
  844. key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  845. strcpy(key_name, "NetworkAddressIPv6");
  846. break;
  847. case OSBuildNumber:
  848. strcpy(key_value, os_build);
  849. strcpy(key_name, "OSBuildNumber");
  850. break;
  851. case OSName:
  852. strcpy(key_value, os_name);
  853. strcpy(key_name, "OSName");
  854. break;
  855. case OSMajorVersion:
  856. strcpy(key_value, os_major);
  857. strcpy(key_name, "OSMajorVersion");
  858. break;
  859. case OSMinorVersion:
  860. strcpy(key_value, os_minor);
  861. strcpy(key_name, "OSMinorVersion");
  862. break;
  863. case OSVersion:
  864. strcpy(key_value, os_build);
  865. strcpy(key_name, "OSVersion");
  866. break;
  867. case ProcessorArchitecture:
  868. strcpy(key_value, processor_arch);
  869. strcpy(key_name, "ProcessorArchitecture");
  870. break;
  871. default:
  872. hv_msg->error = HV_S_CONT;
  873. break;
  874. }
  875. /*
  876. * Send the value back to the kernel. The response is
  877. * already in the receive buffer. Update the cn_msg header to
  878. * reflect the key value that has been added to the message
  879. */
  880. kvp_done:
  881. incoming_cn_msg->id.idx = CN_KVP_IDX;
  882. incoming_cn_msg->id.val = CN_KVP_VAL;
  883. incoming_cn_msg->ack = 0;
  884. incoming_cn_msg->len = sizeof(struct hv_kvp_msg);
  885. len = netlink_send(fd, incoming_cn_msg);
  886. if (len < 0) {
  887. syslog(LOG_ERR, "net_link send failed; error:%d", len);
  888. exit(-1);
  889. }
  890. }
  891. }