commands-posix.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. /*
  2. * QEMU Guest Agent POSIX-specific command implementations
  3. *
  4. * Copyright IBM Corp. 2011
  5. *
  6. * Authors:
  7. * Michael Roth <mdroth@linux.vnet.ibm.com>
  8. * Michal Privoznik <mprivozn@redhat.com>
  9. *
  10. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  11. * See the COPYING file in the top-level directory.
  12. */
  13. #include <glib.h>
  14. #include <sys/types.h>
  15. #include <sys/ioctl.h>
  16. #include <sys/wait.h>
  17. #include "qga/guest-agent-core.h"
  18. #include "qga-qmp-commands.h"
  19. #include "qerror.h"
  20. #include "qemu-queue.h"
  21. #include "host-utils.h"
  22. #ifndef CONFIG_HAS_ENVIRON
  23. #ifdef __APPLE__
  24. #include <crt_externs.h>
  25. #define environ (*_NSGetEnviron())
  26. #else
  27. extern char **environ;
  28. #endif
  29. #endif
  30. #if defined(__linux__)
  31. #include <mntent.h>
  32. #include <linux/fs.h>
  33. #include <ifaddrs.h>
  34. #include <arpa/inet.h>
  35. #include <sys/socket.h>
  36. #include <net/if.h>
  37. #ifdef FIFREEZE
  38. #define CONFIG_FSFREEZE
  39. #endif
  40. #ifdef FITRIM
  41. #define CONFIG_FSTRIM
  42. #endif
  43. #endif
  44. void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
  45. {
  46. const char *shutdown_flag;
  47. pid_t rpid, pid;
  48. int status;
  49. slog("guest-shutdown called, mode: %s", mode);
  50. if (!has_mode || strcmp(mode, "powerdown") == 0) {
  51. shutdown_flag = "-P";
  52. } else if (strcmp(mode, "halt") == 0) {
  53. shutdown_flag = "-H";
  54. } else if (strcmp(mode, "reboot") == 0) {
  55. shutdown_flag = "-r";
  56. } else {
  57. error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode",
  58. "halt|powerdown|reboot");
  59. return;
  60. }
  61. pid = fork();
  62. if (pid == 0) {
  63. /* child, start the shutdown */
  64. setsid();
  65. reopen_fd_to_null(0);
  66. reopen_fd_to_null(1);
  67. reopen_fd_to_null(2);
  68. execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
  69. "hypervisor initiated shutdown", (char*)NULL, environ);
  70. _exit(EXIT_FAILURE);
  71. } else if (pid < 0) {
  72. goto exit_err;
  73. }
  74. do {
  75. rpid = waitpid(pid, &status, 0);
  76. } while (rpid == -1 && errno == EINTR);
  77. if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
  78. return;
  79. }
  80. exit_err:
  81. error_set(err, QERR_UNDEFINED_ERROR);
  82. }
  83. typedef struct GuestFileHandle {
  84. uint64_t id;
  85. FILE *fh;
  86. QTAILQ_ENTRY(GuestFileHandle) next;
  87. } GuestFileHandle;
  88. static struct {
  89. QTAILQ_HEAD(, GuestFileHandle) filehandles;
  90. } guest_file_state;
  91. static void guest_file_handle_add(FILE *fh)
  92. {
  93. GuestFileHandle *gfh;
  94. gfh = g_malloc0(sizeof(GuestFileHandle));
  95. gfh->id = fileno(fh);
  96. gfh->fh = fh;
  97. QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
  98. }
  99. static GuestFileHandle *guest_file_handle_find(int64_t id)
  100. {
  101. GuestFileHandle *gfh;
  102. QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
  103. {
  104. if (gfh->id == id) {
  105. return gfh;
  106. }
  107. }
  108. return NULL;
  109. }
  110. int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
  111. {
  112. FILE *fh;
  113. int fd;
  114. int64_t ret = -1;
  115. if (!has_mode) {
  116. mode = "r";
  117. }
  118. slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
  119. fh = fopen(path, mode);
  120. if (!fh) {
  121. error_set(err, QERR_OPEN_FILE_FAILED, path);
  122. return -1;
  123. }
  124. /* set fd non-blocking to avoid common use cases (like reading from a
  125. * named pipe) from hanging the agent
  126. */
  127. fd = fileno(fh);
  128. ret = fcntl(fd, F_GETFL);
  129. ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
  130. if (ret == -1) {
  131. error_set(err, QERR_QGA_COMMAND_FAILED, "fcntl() failed");
  132. fclose(fh);
  133. return -1;
  134. }
  135. guest_file_handle_add(fh);
  136. slog("guest-file-open, handle: %d", fd);
  137. return fd;
  138. }
  139. void qmp_guest_file_close(int64_t handle, Error **err)
  140. {
  141. GuestFileHandle *gfh = guest_file_handle_find(handle);
  142. int ret;
  143. slog("guest-file-close called, handle: %ld", handle);
  144. if (!gfh) {
  145. error_set(err, QERR_FD_NOT_FOUND, "handle");
  146. return;
  147. }
  148. ret = fclose(gfh->fh);
  149. if (ret == -1) {
  150. error_set(err, QERR_QGA_COMMAND_FAILED, "fclose() failed");
  151. return;
  152. }
  153. QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
  154. g_free(gfh);
  155. }
  156. struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
  157. int64_t count, Error **err)
  158. {
  159. GuestFileHandle *gfh = guest_file_handle_find(handle);
  160. GuestFileRead *read_data = NULL;
  161. guchar *buf;
  162. FILE *fh;
  163. size_t read_count;
  164. if (!gfh) {
  165. error_set(err, QERR_FD_NOT_FOUND, "handle");
  166. return NULL;
  167. }
  168. if (!has_count) {
  169. count = QGA_READ_COUNT_DEFAULT;
  170. } else if (count < 0) {
  171. error_set(err, QERR_INVALID_PARAMETER, "count");
  172. return NULL;
  173. }
  174. fh = gfh->fh;
  175. buf = g_malloc0(count+1);
  176. read_count = fread(buf, 1, count, fh);
  177. if (ferror(fh)) {
  178. slog("guest-file-read failed, handle: %ld", handle);
  179. error_set(err, QERR_QGA_COMMAND_FAILED, "fread() failed");
  180. } else {
  181. buf[read_count] = 0;
  182. read_data = g_malloc0(sizeof(GuestFileRead));
  183. read_data->count = read_count;
  184. read_data->eof = feof(fh);
  185. if (read_count) {
  186. read_data->buf_b64 = g_base64_encode(buf, read_count);
  187. }
  188. }
  189. g_free(buf);
  190. clearerr(fh);
  191. return read_data;
  192. }
  193. GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
  194. bool has_count, int64_t count, Error **err)
  195. {
  196. GuestFileWrite *write_data = NULL;
  197. guchar *buf;
  198. gsize buf_len;
  199. int write_count;
  200. GuestFileHandle *gfh = guest_file_handle_find(handle);
  201. FILE *fh;
  202. if (!gfh) {
  203. error_set(err, QERR_FD_NOT_FOUND, "handle");
  204. return NULL;
  205. }
  206. fh = gfh->fh;
  207. buf = g_base64_decode(buf_b64, &buf_len);
  208. if (!has_count) {
  209. count = buf_len;
  210. } else if (count < 0 || count > buf_len) {
  211. g_free(buf);
  212. error_set(err, QERR_INVALID_PARAMETER, "count");
  213. return NULL;
  214. }
  215. write_count = fwrite(buf, 1, count, fh);
  216. if (ferror(fh)) {
  217. slog("guest-file-write failed, handle: %ld", handle);
  218. error_set(err, QERR_QGA_COMMAND_FAILED, "fwrite() error");
  219. } else {
  220. write_data = g_malloc0(sizeof(GuestFileWrite));
  221. write_data->count = write_count;
  222. write_data->eof = feof(fh);
  223. }
  224. g_free(buf);
  225. clearerr(fh);
  226. return write_data;
  227. }
  228. struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
  229. int64_t whence, Error **err)
  230. {
  231. GuestFileHandle *gfh = guest_file_handle_find(handle);
  232. GuestFileSeek *seek_data = NULL;
  233. FILE *fh;
  234. int ret;
  235. if (!gfh) {
  236. error_set(err, QERR_FD_NOT_FOUND, "handle");
  237. return NULL;
  238. }
  239. fh = gfh->fh;
  240. ret = fseek(fh, offset, whence);
  241. if (ret == -1) {
  242. error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno));
  243. } else {
  244. seek_data = g_malloc0(sizeof(GuestFileRead));
  245. seek_data->position = ftell(fh);
  246. seek_data->eof = feof(fh);
  247. }
  248. clearerr(fh);
  249. return seek_data;
  250. }
  251. void qmp_guest_file_flush(int64_t handle, Error **err)
  252. {
  253. GuestFileHandle *gfh = guest_file_handle_find(handle);
  254. FILE *fh;
  255. int ret;
  256. if (!gfh) {
  257. error_set(err, QERR_FD_NOT_FOUND, "handle");
  258. return;
  259. }
  260. fh = gfh->fh;
  261. ret = fflush(fh);
  262. if (ret == EOF) {
  263. error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno));
  264. }
  265. }
  266. static void guest_file_init(void)
  267. {
  268. QTAILQ_INIT(&guest_file_state.filehandles);
  269. }
  270. /* linux-specific implementations. avoid this if at all possible. */
  271. #if defined(__linux__)
  272. #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
  273. typedef struct FsMount {
  274. char *dirname;
  275. char *devtype;
  276. QTAILQ_ENTRY(FsMount) next;
  277. } FsMount;
  278. typedef QTAILQ_HEAD(, FsMount) FsMountList;
  279. static void free_fs_mount_list(FsMountList *mounts)
  280. {
  281. FsMount *mount, *temp;
  282. if (!mounts) {
  283. return;
  284. }
  285. QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
  286. QTAILQ_REMOVE(mounts, mount, next);
  287. g_free(mount->dirname);
  288. g_free(mount->devtype);
  289. g_free(mount);
  290. }
  291. }
  292. /*
  293. * Walk the mount table and build a list of local file systems
  294. */
  295. static int build_fs_mount_list(FsMountList *mounts)
  296. {
  297. struct mntent *ment;
  298. FsMount *mount;
  299. char const *mtab = "/proc/self/mounts";
  300. FILE *fp;
  301. fp = setmntent(mtab, "r");
  302. if (!fp) {
  303. g_warning("fsfreeze: unable to read mtab");
  304. return -1;
  305. }
  306. while ((ment = getmntent(fp))) {
  307. /*
  308. * An entry which device name doesn't start with a '/' is
  309. * either a dummy file system or a network file system.
  310. * Add special handling for smbfs and cifs as is done by
  311. * coreutils as well.
  312. */
  313. if ((ment->mnt_fsname[0] != '/') ||
  314. (strcmp(ment->mnt_type, "smbfs") == 0) ||
  315. (strcmp(ment->mnt_type, "cifs") == 0)) {
  316. continue;
  317. }
  318. mount = g_malloc0(sizeof(FsMount));
  319. mount->dirname = g_strdup(ment->mnt_dir);
  320. mount->devtype = g_strdup(ment->mnt_type);
  321. QTAILQ_INSERT_TAIL(mounts, mount, next);
  322. }
  323. endmntent(fp);
  324. return 0;
  325. }
  326. #endif
  327. #if defined(CONFIG_FSFREEZE)
  328. /*
  329. * Return status of freeze/thaw
  330. */
  331. GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
  332. {
  333. if (ga_is_frozen(ga_state)) {
  334. return GUEST_FSFREEZE_STATUS_FROZEN;
  335. }
  336. return GUEST_FSFREEZE_STATUS_THAWED;
  337. }
  338. /*
  339. * Walk list of mounted file systems in the guest, and freeze the ones which
  340. * are real local file systems.
  341. */
  342. int64_t qmp_guest_fsfreeze_freeze(Error **err)
  343. {
  344. int ret = 0, i = 0;
  345. FsMountList mounts;
  346. struct FsMount *mount;
  347. int fd;
  348. char err_msg[512];
  349. slog("guest-fsfreeze called");
  350. QTAILQ_INIT(&mounts);
  351. ret = build_fs_mount_list(&mounts);
  352. if (ret < 0) {
  353. return ret;
  354. }
  355. /* cannot risk guest agent blocking itself on a write in this state */
  356. ga_set_frozen(ga_state);
  357. QTAILQ_FOREACH(mount, &mounts, next) {
  358. fd = qemu_open(mount->dirname, O_RDONLY);
  359. if (fd == -1) {
  360. sprintf(err_msg, "failed to open %s, %s", mount->dirname,
  361. strerror(errno));
  362. error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
  363. goto error;
  364. }
  365. /* we try to cull filesytems we know won't work in advance, but other
  366. * filesytems may not implement fsfreeze for less obvious reasons.
  367. * these will report EOPNOTSUPP. we simply ignore these when tallying
  368. * the number of frozen filesystems.
  369. *
  370. * any other error means a failure to freeze a filesystem we
  371. * expect to be freezable, so return an error in those cases
  372. * and return system to thawed state.
  373. */
  374. ret = ioctl(fd, FIFREEZE);
  375. if (ret == -1) {
  376. if (errno != EOPNOTSUPP) {
  377. sprintf(err_msg, "failed to freeze %s, %s",
  378. mount->dirname, strerror(errno));
  379. error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
  380. close(fd);
  381. goto error;
  382. }
  383. } else {
  384. i++;
  385. }
  386. close(fd);
  387. }
  388. free_fs_mount_list(&mounts);
  389. return i;
  390. error:
  391. free_fs_mount_list(&mounts);
  392. qmp_guest_fsfreeze_thaw(NULL);
  393. return 0;
  394. }
  395. /*
  396. * Walk list of frozen file systems in the guest, and thaw them.
  397. */
  398. int64_t qmp_guest_fsfreeze_thaw(Error **err)
  399. {
  400. int ret;
  401. FsMountList mounts;
  402. FsMount *mount;
  403. int fd, i = 0, logged;
  404. QTAILQ_INIT(&mounts);
  405. ret = build_fs_mount_list(&mounts);
  406. if (ret) {
  407. error_set(err, QERR_QGA_COMMAND_FAILED,
  408. "failed to enumerate filesystems");
  409. return 0;
  410. }
  411. QTAILQ_FOREACH(mount, &mounts, next) {
  412. logged = false;
  413. fd = qemu_open(mount->dirname, O_RDONLY);
  414. if (fd == -1) {
  415. continue;
  416. }
  417. /* we have no way of knowing whether a filesystem was actually unfrozen
  418. * as a result of a successful call to FITHAW, only that if an error
  419. * was returned the filesystem was *not* unfrozen by that particular
  420. * call.
  421. *
  422. * since multiple preceding FIFREEZEs require multiple calls to FITHAW
  423. * to unfreeze, continuing issuing FITHAW until an error is returned,
  424. * in which case either the filesystem is in an unfreezable state, or,
  425. * more likely, it was thawed previously (and remains so afterward).
  426. *
  427. * also, since the most recent successful call is the one that did
  428. * the actual unfreeze, we can use this to provide an accurate count
  429. * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
  430. * may * be useful for determining whether a filesystem was unfrozen
  431. * during the freeze/thaw phase by a process other than qemu-ga.
  432. */
  433. do {
  434. ret = ioctl(fd, FITHAW);
  435. if (ret == 0 && !logged) {
  436. i++;
  437. logged = true;
  438. }
  439. } while (ret == 0);
  440. close(fd);
  441. }
  442. ga_unset_frozen(ga_state);
  443. free_fs_mount_list(&mounts);
  444. return i;
  445. }
  446. static void guest_fsfreeze_cleanup(void)
  447. {
  448. int64_t ret;
  449. Error *err = NULL;
  450. if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
  451. ret = qmp_guest_fsfreeze_thaw(&err);
  452. if (ret < 0 || err) {
  453. slog("failed to clean up frozen filesystems");
  454. }
  455. }
  456. }
  457. #endif /* CONFIG_FSFREEZE */
  458. #if defined(CONFIG_FSTRIM)
  459. /*
  460. * Walk list of mounted file systems in the guest, and trim them.
  461. */
  462. void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
  463. {
  464. int ret = 0;
  465. FsMountList mounts;
  466. struct FsMount *mount;
  467. int fd;
  468. char err_msg[512];
  469. struct fstrim_range r = {
  470. .start = 0,
  471. .len = -1,
  472. .minlen = has_minimum ? minimum : 0,
  473. };
  474. slog("guest-fstrim called");
  475. QTAILQ_INIT(&mounts);
  476. ret = build_fs_mount_list(&mounts);
  477. if (ret < 0) {
  478. return;
  479. }
  480. QTAILQ_FOREACH(mount, &mounts, next) {
  481. fd = qemu_open(mount->dirname, O_RDONLY);
  482. if (fd == -1) {
  483. sprintf(err_msg, "failed to open %s, %s", mount->dirname,
  484. strerror(errno));
  485. error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
  486. goto error;
  487. }
  488. /* We try to cull filesytems we know won't work in advance, but other
  489. * filesytems may not implement fstrim for less obvious reasons. These
  490. * will report EOPNOTSUPP; we simply ignore these errors. Any other
  491. * error means an unexpected error, so return it in those cases. In
  492. * some other cases ENOTTY will be reported (e.g. CD-ROMs).
  493. */
  494. ret = ioctl(fd, FITRIM, &r);
  495. if (ret == -1) {
  496. if (errno != ENOTTY && errno != EOPNOTSUPP) {
  497. sprintf(err_msg, "failed to trim %s, %s",
  498. mount->dirname, strerror(errno));
  499. error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
  500. close(fd);
  501. goto error;
  502. }
  503. }
  504. close(fd);
  505. }
  506. error:
  507. free_fs_mount_list(&mounts);
  508. }
  509. #endif /* CONFIG_FSTRIM */
  510. #define LINUX_SYS_STATE_FILE "/sys/power/state"
  511. #define SUSPEND_SUPPORTED 0
  512. #define SUSPEND_NOT_SUPPORTED 1
  513. static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
  514. const char *sysfile_str, Error **err)
  515. {
  516. char *pmutils_path;
  517. pid_t pid, rpid;
  518. int status;
  519. pmutils_path = g_find_program_in_path(pmutils_bin);
  520. pid = fork();
  521. if (!pid) {
  522. char buf[32]; /* hopefully big enough */
  523. ssize_t ret;
  524. int fd;
  525. setsid();
  526. reopen_fd_to_null(0);
  527. reopen_fd_to_null(1);
  528. reopen_fd_to_null(2);
  529. if (pmutils_path) {
  530. execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
  531. }
  532. /*
  533. * If we get here either pm-utils is not installed or execle() has
  534. * failed. Let's try the manual method if the caller wants it.
  535. */
  536. if (!sysfile_str) {
  537. _exit(SUSPEND_NOT_SUPPORTED);
  538. }
  539. fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
  540. if (fd < 0) {
  541. _exit(SUSPEND_NOT_SUPPORTED);
  542. }
  543. ret = read(fd, buf, sizeof(buf)-1);
  544. if (ret <= 0) {
  545. _exit(SUSPEND_NOT_SUPPORTED);
  546. }
  547. buf[ret] = '\0';
  548. if (strstr(buf, sysfile_str)) {
  549. _exit(SUSPEND_SUPPORTED);
  550. }
  551. _exit(SUSPEND_NOT_SUPPORTED);
  552. }
  553. g_free(pmutils_path);
  554. if (pid < 0) {
  555. goto undef_err;
  556. }
  557. do {
  558. rpid = waitpid(pid, &status, 0);
  559. } while (rpid == -1 && errno == EINTR);
  560. if (rpid == pid && WIFEXITED(status)) {
  561. switch (WEXITSTATUS(status)) {
  562. case SUSPEND_SUPPORTED:
  563. return;
  564. case SUSPEND_NOT_SUPPORTED:
  565. error_set(err, QERR_UNSUPPORTED);
  566. return;
  567. default:
  568. goto undef_err;
  569. }
  570. }
  571. undef_err:
  572. error_set(err, QERR_UNDEFINED_ERROR);
  573. }
  574. static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
  575. Error **err)
  576. {
  577. char *pmutils_path;
  578. pid_t rpid, pid;
  579. int status;
  580. pmutils_path = g_find_program_in_path(pmutils_bin);
  581. pid = fork();
  582. if (pid == 0) {
  583. /* child */
  584. int fd;
  585. setsid();
  586. reopen_fd_to_null(0);
  587. reopen_fd_to_null(1);
  588. reopen_fd_to_null(2);
  589. if (pmutils_path) {
  590. execle(pmutils_path, pmutils_bin, NULL, environ);
  591. }
  592. /*
  593. * If we get here either pm-utils is not installed or execle() has
  594. * failed. Let's try the manual method if the caller wants it.
  595. */
  596. if (!sysfile_str) {
  597. _exit(EXIT_FAILURE);
  598. }
  599. fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
  600. if (fd < 0) {
  601. _exit(EXIT_FAILURE);
  602. }
  603. if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
  604. _exit(EXIT_FAILURE);
  605. }
  606. _exit(EXIT_SUCCESS);
  607. }
  608. g_free(pmutils_path);
  609. if (pid < 0) {
  610. goto exit_err;
  611. }
  612. do {
  613. rpid = waitpid(pid, &status, 0);
  614. } while (rpid == -1 && errno == EINTR);
  615. if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
  616. return;
  617. }
  618. exit_err:
  619. error_set(err, QERR_UNDEFINED_ERROR);
  620. }
  621. void qmp_guest_suspend_disk(Error **err)
  622. {
  623. bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
  624. if (error_is_set(err)) {
  625. return;
  626. }
  627. guest_suspend("pm-hibernate", "disk", err);
  628. }
  629. void qmp_guest_suspend_ram(Error **err)
  630. {
  631. bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
  632. if (error_is_set(err)) {
  633. return;
  634. }
  635. guest_suspend("pm-suspend", "mem", err);
  636. }
  637. void qmp_guest_suspend_hybrid(Error **err)
  638. {
  639. bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
  640. if (error_is_set(err)) {
  641. return;
  642. }
  643. guest_suspend("pm-suspend-hybrid", NULL, err);
  644. }
  645. static GuestNetworkInterfaceList *
  646. guest_find_interface(GuestNetworkInterfaceList *head,
  647. const char *name)
  648. {
  649. for (; head; head = head->next) {
  650. if (strcmp(head->value->name, name) == 0) {
  651. break;
  652. }
  653. }
  654. return head;
  655. }
  656. /*
  657. * Build information about guest interfaces
  658. */
  659. GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
  660. {
  661. GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
  662. struct ifaddrs *ifap, *ifa;
  663. char err_msg[512];
  664. if (getifaddrs(&ifap) < 0) {
  665. snprintf(err_msg, sizeof(err_msg),
  666. "getifaddrs failed: %s", strerror(errno));
  667. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  668. goto error;
  669. }
  670. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  671. GuestNetworkInterfaceList *info;
  672. GuestIpAddressList **address_list = NULL, *address_item = NULL;
  673. char addr4[INET_ADDRSTRLEN];
  674. char addr6[INET6_ADDRSTRLEN];
  675. int sock;
  676. struct ifreq ifr;
  677. unsigned char *mac_addr;
  678. void *p;
  679. g_debug("Processing %s interface", ifa->ifa_name);
  680. info = guest_find_interface(head, ifa->ifa_name);
  681. if (!info) {
  682. info = g_malloc0(sizeof(*info));
  683. info->value = g_malloc0(sizeof(*info->value));
  684. info->value->name = g_strdup(ifa->ifa_name);
  685. if (!cur_item) {
  686. head = cur_item = info;
  687. } else {
  688. cur_item->next = info;
  689. cur_item = info;
  690. }
  691. }
  692. if (!info->value->has_hardware_address &&
  693. ifa->ifa_flags & SIOCGIFHWADDR) {
  694. /* we haven't obtained HW address yet */
  695. sock = socket(PF_INET, SOCK_STREAM, 0);
  696. if (sock == -1) {
  697. snprintf(err_msg, sizeof(err_msg),
  698. "failed to create socket: %s", strerror(errno));
  699. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  700. goto error;
  701. }
  702. memset(&ifr, 0, sizeof(ifr));
  703. strncpy(ifr.ifr_name, info->value->name, IF_NAMESIZE);
  704. if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
  705. snprintf(err_msg, sizeof(err_msg),
  706. "failed to get MAC address of %s: %s",
  707. ifa->ifa_name,
  708. strerror(errno));
  709. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  710. goto error;
  711. }
  712. mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
  713. if (asprintf(&info->value->hardware_address,
  714. "%02x:%02x:%02x:%02x:%02x:%02x",
  715. (int) mac_addr[0], (int) mac_addr[1],
  716. (int) mac_addr[2], (int) mac_addr[3],
  717. (int) mac_addr[4], (int) mac_addr[5]) == -1) {
  718. snprintf(err_msg, sizeof(err_msg),
  719. "failed to format MAC: %s", strerror(errno));
  720. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  721. goto error;
  722. }
  723. info->value->has_hardware_address = true;
  724. close(sock);
  725. }
  726. if (ifa->ifa_addr &&
  727. ifa->ifa_addr->sa_family == AF_INET) {
  728. /* interface with IPv4 address */
  729. address_item = g_malloc0(sizeof(*address_item));
  730. address_item->value = g_malloc0(sizeof(*address_item->value));
  731. p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
  732. if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
  733. snprintf(err_msg, sizeof(err_msg),
  734. "inet_ntop failed : %s", strerror(errno));
  735. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  736. goto error;
  737. }
  738. address_item->value->ip_address = g_strdup(addr4);
  739. address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
  740. if (ifa->ifa_netmask) {
  741. /* Count the number of set bits in netmask.
  742. * This is safe as '1' and '0' cannot be shuffled in netmask. */
  743. p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
  744. address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
  745. }
  746. } else if (ifa->ifa_addr &&
  747. ifa->ifa_addr->sa_family == AF_INET6) {
  748. /* interface with IPv6 address */
  749. address_item = g_malloc0(sizeof(*address_item));
  750. address_item->value = g_malloc0(sizeof(*address_item->value));
  751. p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
  752. if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
  753. snprintf(err_msg, sizeof(err_msg),
  754. "inet_ntop failed : %s", strerror(errno));
  755. error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
  756. goto error;
  757. }
  758. address_item->value->ip_address = g_strdup(addr6);
  759. address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
  760. if (ifa->ifa_netmask) {
  761. /* Count the number of set bits in netmask.
  762. * This is safe as '1' and '0' cannot be shuffled in netmask. */
  763. p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
  764. address_item->value->prefix =
  765. ctpop32(((uint32_t *) p)[0]) +
  766. ctpop32(((uint32_t *) p)[1]) +
  767. ctpop32(((uint32_t *) p)[2]) +
  768. ctpop32(((uint32_t *) p)[3]);
  769. }
  770. }
  771. if (!address_item) {
  772. continue;
  773. }
  774. address_list = &info->value->ip_addresses;
  775. while (*address_list && (*address_list)->next) {
  776. address_list = &(*address_list)->next;
  777. }
  778. if (!*address_list) {
  779. *address_list = address_item;
  780. } else {
  781. (*address_list)->next = address_item;
  782. }
  783. info->value->has_ip_addresses = true;
  784. }
  785. freeifaddrs(ifap);
  786. return head;
  787. error:
  788. freeifaddrs(ifap);
  789. qapi_free_GuestNetworkInterfaceList(head);
  790. return NULL;
  791. }
  792. #else /* defined(__linux__) */
  793. void qmp_guest_suspend_disk(Error **err)
  794. {
  795. error_set(err, QERR_UNSUPPORTED);
  796. }
  797. void qmp_guest_suspend_ram(Error **err)
  798. {
  799. error_set(err, QERR_UNSUPPORTED);
  800. }
  801. void qmp_guest_suspend_hybrid(Error **err)
  802. {
  803. error_set(err, QERR_UNSUPPORTED);
  804. }
  805. GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
  806. {
  807. error_set(errp, QERR_UNSUPPORTED);
  808. return NULL;
  809. }
  810. #endif
  811. #if !defined(CONFIG_FSFREEZE)
  812. GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
  813. {
  814. error_set(err, QERR_UNSUPPORTED);
  815. return 0;
  816. }
  817. int64_t qmp_guest_fsfreeze_freeze(Error **err)
  818. {
  819. error_set(err, QERR_UNSUPPORTED);
  820. return 0;
  821. }
  822. int64_t qmp_guest_fsfreeze_thaw(Error **err)
  823. {
  824. error_set(err, QERR_UNSUPPORTED);
  825. return 0;
  826. }
  827. #endif /* CONFIG_FSFREEZE */
  828. #if !defined(CONFIG_FSTRIM)
  829. void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
  830. {
  831. error_set(err, QERR_UNSUPPORTED);
  832. }
  833. #endif
  834. /* register init/cleanup routines for stateful command groups */
  835. void ga_command_state_init(GAState *s, GACommandState *cs)
  836. {
  837. #if defined(CONFIG_FSFREEZE)
  838. ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
  839. #endif
  840. ga_command_state_add(cs, guest_file_init, NULL);
  841. }