/** * virNodeDeviceLookupByName: * @conn: pointer to the hypervisor connection * @name: unique device name * * Lookup a node device by its name. * * virNodeDeviceFree should be used to free the resources after the * node device object is no longer needed. * * Returns a virNodeDevicePtr if found, NULL otherwise. */ virNodeDevicePtr virNodeDeviceLookupByName(virConnectPtr conn, const char *name) { VIR_DEBUG("conn=%p, name=%p", conn, name); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(name, error); if (conn->nodeDeviceDriver && conn->nodeDeviceDriver->nodeDeviceLookupByName) { virNodeDevicePtr ret; ret = conn->nodeDeviceDriver->nodeDeviceLookupByName(conn, name); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; }
/** * virAdmConnectOpen: * @name: uri of the daemon to connect to, NULL for default * @flags: unused, must be 0 * * Opens connection to admin interface of the daemon. * * Returns @virAdmConnectPtr object or NULL on error */ virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags) { char *sock_path = NULL; virAdmConnectPtr conn = NULL; if (virAdmInitialize() < 0) goto error; VIR_DEBUG("flags=%x", flags); virResetLastError(); if (!(conn = virAdmConnectNew())) goto error; if (!(sock_path = getSocketPath(name))) goto error; if (!(conn->privateData = remoteAdminPrivNew(sock_path))) goto error; conn->privateDataFreeFunc = remoteAdminPrivFree; if (remoteAdminConnectOpen(conn, flags) < 0) goto error; cleanup: VIR_FREE(sock_path); return conn; error: virDispatchError(NULL); virObjectUnref(conn); conn = NULL; goto cleanup; }
/** * virAdmServerSetThreadPoolParameters: * @srv: a valid server object reference * @params: pointer to threadpool typed parameter objects * @nparams: number of parameters in @params * @flags: extra flags; not used yet, so callers should always pass 0 * * Change server threadpool parameters according to @params. Note that some * tunables are read-only, thus any attempt to set them will result in a * failure. * * Returns 0 on success, -1 in case of an error. */ int virAdmServerSetThreadPoolParameters(virAdmServerPtr srv, virTypedParameterPtr params, int nparams, unsigned int flags) { VIR_DEBUG("srv=%p, params=%p, nparams=%x, flags=%x", srv, params, nparams, flags); virResetLastError(); virCheckAdmServerReturn(srv, -1); virCheckNonNullArgGoto(params, error); virCheckNonNegativeArgGoto(nparams, error); if (remoteAdminServerSetThreadPoolParameters(srv, params, nparams, flags) < 0) goto error; return 0; error: virDispatchError(NULL); return -1; }
/** * virNetworkLookupByUUIDString: * @conn: pointer to the hypervisor connection * @uuidstr: the string UUID for the network * * Try to lookup a network on the given hypervisor based on its UUID. * * Returns a new network object or NULL in case of failure. If the * network cannot be found, then VIR_ERR_NO_NETWORK error is raised. */ virNetworkPtr virNetworkLookupByUUIDString(virConnectPtr conn, const char *uuidstr) { unsigned char uuid[VIR_UUID_BUFLEN]; VIR_DEBUG("conn=%p, uuidstr=%s", conn, NULLSTR(uuidstr)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(uuidstr, error); if (virUUIDParse(uuidstr, uuid) < 0) { virReportInvalidArg(uuidstr, _("uuidstr in %s must be a valid UUID"), __FUNCTION__); goto error; } return virNetworkLookupByUUID(conn, &uuid[0]); error: virDispatchError(conn); return NULL; }
/** * virNetworkLookupByUUID: * @conn: pointer to the hypervisor connection * @uuid: the raw UUID for the network * * Try to lookup a network on the given hypervisor based on its UUID. * * virNetworkFree should be used to free the resources after the * network object is no longer needed. * * Returns a new network object or NULL in case of failure. If the * network cannot be found, then VIR_ERR_NO_NETWORK error is raised. */ virNetworkPtr virNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { VIR_UUID_DEBUG(conn, uuid); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(uuid, error); if (conn->networkDriver && conn->networkDriver->networkLookupByUUID) { virNetworkPtr ret; ret = conn->networkDriver->networkLookupByUUID(conn, uuid); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; }
/** * virNWFilterBindingLookupByPortDev: * @conn: pointer to the hypervisor connection * @portdev: name for the network port device * * Try to lookup a network filter binding on the given hypervisor based * on network port device name. * * virNWFilterBindingFree should be used to free the resources after the * binding object is no longer needed. * * Returns a new binding object or NULL in case of failure. If the * network filter cannot be found, then VIR_ERR_NO_NWFILTER_BINDING * error is raised. */ virNWFilterBindingPtr virNWFilterBindingLookupByPortDev(virConnectPtr conn, const char *portdev) { VIR_DEBUG("conn=%p, name=%s", conn, NULLSTR(portdev)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(portdev, error); if (conn->nwfilterDriver && conn->nwfilterDriver->nwfilterBindingLookupByPortDev) { virNWFilterBindingPtr ret; ret = conn->nwfilterDriver->nwfilterBindingLookupByPortDev(conn, portdev); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; }
/** * virAdmConnectListServers: * @conn: daemon connection reference * @servers: Pointer to a list to store an array containing objects or NULL * if the list is not required (number of servers only) * @flags: extra flags; not used yet, so callers should always pass 0 * * Collect list of all servers provided by daemon the client is connected to. * * Returns the number of servers available on daemon side or -1 in case of a * failure, setting @servers to NULL. There is a guaranteed extra element set * to NULL in the @servers list returned to make the iteration easier, excluding * this extra element from the final count. * Caller is responsible to call virAdmServerFree() on each list element, * followed by freeing @servers. */ int virAdmConnectListServers(virAdmConnectPtr conn, virAdmServerPtr **servers, unsigned int flags) { int ret = -1; VIR_DEBUG("conn=%p, servers=%p, flags=%x", conn, servers, flags); virResetLastError(); virCheckFlagsGoto(0, error); if (servers) *servers = NULL; virCheckAdmConnectReturn(conn, -1); if ((ret = remoteAdminConnectListServers(conn, servers, flags)) < 0) goto error; return ret; error: virDispatchError(NULL); return -1; }
/** * virDomainLxcEnterSecurityLabel: * @model: the security model to set * @label: the security label to apply * @oldlabel: filled with old security label * @flags: currently unused, pass 0 * * This API is LXC specific, so it will only work with hypervisor * connections to the LXC driver. * * Attaches the process to the security label specified * by @label. @label is interpreted relative to @model * Depending on the security driver, this may * not take effect until the next call to exec(). * * If @oldlabel is not NULL, it will be filled with info * about the current security label. This may let the * process be moved back to the previous label if no * exec() has yet been performed. * * Returns 0 on success, -1 on error */ int virDomainLxcEnterSecurityLabel(virSecurityModelPtr model, virSecurityLabelPtr label, virSecurityLabelPtr oldlabel, unsigned int flags) { VIR_DEBUG("model=%p, label=%p, oldlabel=%p, flags=%x", model, label, oldlabel, flags); virResetLastError(); virCheckFlagsGoto(0, error); virCheckNonNullArgGoto(model, error); virCheckNonNullArgGoto(label, error); if (oldlabel) memset(oldlabel, 0, sizeof(*oldlabel)); if (STREQ(model->model, "selinux")) { #ifdef WITH_SELINUX if (oldlabel) { security_context_t ctx; if (getcon(&ctx) < 0) { virReportSystemError(errno, _("unable to get PID %d security context"), getpid()); goto error; } if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) { virReportError(VIR_ERR_INTERNAL_ERROR, _("security label exceeds " "maximum length: %d"), VIR_SECURITY_LABEL_BUFLEN - 1); freecon(ctx); goto error; } strcpy(oldlabel->label, (char *) ctx); freecon(ctx); if ((oldlabel->enforcing = security_getenforce()) < 0) { virReportSystemError(errno, "%s", _("error calling security_getenforce()")); goto error; } } if (setexeccon(label->label) < 0) { virReportSystemError(errno, _("Cannot set context %s"), label->label); goto error; } #else virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Support for SELinux is not enabled")); goto error; #endif } else if (STREQ(model->model, "apparmor")) { #ifdef WITH_APPARMOR if (aa_change_profile(label->label) < 0) { virReportSystemError(errno, _("error changing profile to %s"), label->label); goto error; } #else virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Support for AppArmor is not enabled")); goto error; #endif } else if (STREQ(model->model, "none")) { /* nothing todo */ } else { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Security model %s cannot be entered"), model->model); goto error; } return 0; error: virDispatchError(NULL); return -1; }
/** * virAdmConnectOpen: * @name: uri of the daemon to connect to, NULL for default * @flags: bitwise-OR of virConnectFlags; so far the only supported flag is * VIR_CONNECT_NO_ALIASES * * Opens connection to admin interface of the daemon. * * Returns @virAdmConnectPtr object or NULL on error */ virAdmConnectPtr virAdmConnectOpen(const char *name, unsigned int flags) { char *sock_path = NULL; char *alias = NULL; virAdmConnectPtr conn = NULL; virConfPtr conf = NULL; char *uristr = NULL; if (virAdmInitialize() < 0) goto error; VIR_DEBUG("flags=%x", flags); virResetLastError(); if (!(conn = virAdmConnectNew())) goto error; if (virConfLoadConfig(&conf, "libvirt-admin.conf") < 0) goto error; if (name) { if (VIR_STRDUP(uristr, name) < 0) goto error; } else { if (virAdmGetDefaultURI(conf, &uristr) < 0) goto error; } if ((!(flags & VIR_CONNECT_NO_ALIASES) && virURIResolveAlias(conf, uristr, &alias) < 0)) goto error; if (alias) { VIR_FREE(uristr); uristr = alias; } if (!(conn->uri = virURIParse(uristr))) goto error; if (!(sock_path = getSocketPath(conn->uri))) goto error; if (!(conn->privateData = remoteAdminPrivNew(sock_path))) goto error; conn->privateDataFreeFunc = remoteAdminPrivFree; if (remoteAdminConnectOpen(conn, flags) < 0) goto error; cleanup: VIR_FREE(sock_path); VIR_FREE(uristr); virConfFree(conf); return conn; error: virDispatchError(NULL); virObjectUnref(conn); conn = NULL; goto cleanup; }
/* * Runs test and count average time (if the nloops is grater than 1) * * returns: -1 = error, 0 = success */ int virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data) { int i, ret = 0; double *ts = NULL; if (testCounter == 0 && !virTestGetVerbose()) fprintf(stderr, " "); testCounter++; if (testOOM < 2) { if (virTestGetVerbose()) fprintf(stderr, "%2d) %-65s ... ", testCounter, title); } if (nloops > 1 && (VIR_ALLOC_N(ts, nloops) < 0)) return -1; for (i=0; i < nloops; i++) { struct timeval before, after; if (ts) GETTIMEOFDAY(&before); virResetLastError(); ret = body(data); virErrorPtr err = virGetLastError(); if (err) { if (virTestGetVerbose() || virTestGetDebug()) virDispatchError(NULL); } if (ret != 0) { break; } if (ts) { GETTIMEOFDAY(&after); ts[i] = DIFF_MSEC(&after, &before); } } if (testOOM < 2) { if (virTestGetVerbose()) { if (ret == 0 && ts) fprintf(stderr, "OK [%.5f ms]\n", virtTestCountAverage(ts, nloops)); else if (ret == 0) fprintf(stderr, "OK\n"); else if (ret == EXIT_AM_SKIP) fprintf(stderr, "SKIP\n"); else fprintf(stderr, "FAILED\n"); } else { if (testCounter != 1 && !((testCounter-1) % 40)) { fprintf(stderr, " %-3d\n", (testCounter-1)); fprintf(stderr, " "); } if (ret == 0) fprintf(stderr, "."); else if (ret == EXIT_AM_SKIP) fprintf(stderr, "_"); else fprintf(stderr, "!"); } } VIR_FREE(ts); return ret; }
int main(int argc, char **argv) { virConfPtr conf = NULL; const char *login_shell_path = conf_file; pid_t cpid = -1; int ret = EXIT_CANCELED; int status; uid_t uid = getuid(); gid_t gid = getgid(); char *name = NULL; char **shargv = NULL; virSecurityModelPtr secmodel = NULL; virSecurityLabelPtr seclabel = NULL; virDomainPtr dom = NULL; virConnectPtr conn = NULL; char *homedir = NULL; int arg; int longindex = -1; int ngroups; gid_t *groups = NULL; ssize_t nfdlist = 0; int *fdlist = NULL; int openmax; size_t i; struct option opt[] = { {"help", no_argument, NULL, 'h'}, {"version", optional_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; if (virInitialize() < 0) { fprintf(stderr, _("Failed to initialize libvirt error handling")); return EXIT_CANCELED; } setenv("PATH", "/bin:/usr/bin", 1); virSetErrorFunc(NULL, NULL); virSetErrorLogPriorityFunc(NULL); progname = argv[0]; if (!setlocale(LC_ALL, "")) { perror("setlocale"); /* failure to setup locale is not fatal */ } if (!bindtextdomain(PACKAGE, LOCALEDIR)) { perror("bindtextdomain"); return ret; } if (!textdomain(PACKAGE)) { perror("textdomain"); return ret; } while ((arg = getopt_long(argc, argv, "hV", opt, &longindex)) != -1) { switch (arg) { case 'h': usage(); exit(EXIT_SUCCESS); case 'V': show_version(); exit(EXIT_SUCCESS); case '?': default: usage(); exit(EXIT_CANCELED); } } if (argc > optind) { virReportSystemError(EINVAL, _("%s takes no options"), progname); goto cleanup; } if (uid == 0) { virReportSystemError(EPERM, _("%s must be run by non root users"), progname); goto cleanup; } name = virGetUserName(uid); if (!name) goto cleanup; homedir = virGetUserDirectoryByUID(uid); if (!homedir) goto cleanup; if (!(conf = virConfReadFile(login_shell_path, 0))) goto cleanup; if ((ngroups = virGetGroupList(uid, gid, &groups)) < 0) goto cleanup; if (virLoginShellAllowedUser(conf, name, groups) < 0) goto cleanup; if (!(shargv = virLoginShellGetShellArgv(conf))) goto cleanup; conn = virConnectOpen("lxc:///"); if (!conn) goto cleanup; dom = virDomainLookupByName(conn, name); if (!dom) goto cleanup; if (!virDomainIsActive(dom) && virDomainCreate(dom)) { virErrorPtr last_error; last_error = virGetLastError(); if (last_error->code != VIR_ERR_OPERATION_INVALID) { virReportSystemError(last_error->code, _("Can't create %s container: %s"), name, last_error->message); goto cleanup; } } openmax = sysconf(_SC_OPEN_MAX); if (openmax < 0) { virReportSystemError(errno, "%s", _("sysconf(_SC_OPEN_MAX) failed")); goto cleanup; } if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) goto cleanup; if (VIR_ALLOC(secmodel) < 0) goto cleanup; if (VIR_ALLOC(seclabel) < 0) goto cleanup; if (virNodeGetSecurityModel(conn, secmodel) < 0) goto cleanup; if (virDomainGetSecurityLabel(dom, seclabel) < 0) goto cleanup; if (virSetUIDGID(0, 0, NULL, 0) < 0) goto cleanup; if (virDomainLxcEnterSecurityLabel(secmodel, seclabel, NULL, 0) < 0) goto cleanup; if (nfdlist > 0 && virDomainLxcEnterNamespace(dom, nfdlist, fdlist, NULL, NULL, 0) < 0) goto cleanup; if (virSetUIDGID(uid, gid, groups, ngroups) < 0) goto cleanup; if (chdir(homedir) < 0) { virReportSystemError(errno, _("Unable to chdir(%s)"), homedir); goto cleanup; } /* A fork is required to create new process in correct pid namespace. */ if ((cpid = virFork()) < 0) goto cleanup; if (cpid == 0) { int tmpfd; for (i = 3; i < openmax; i++) { tmpfd = i; VIR_MASS_CLOSE(tmpfd); } if (execv(shargv[0], (char *const*) shargv) < 0) { virReportSystemError(errno, _("Unable to exec shell %s"), shargv[0]); virDispatchError(NULL); return errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; } } /* At this point, the parent is now waiting for the child to exit, * but as that may take a long time, we release resources now. */ cleanup: if (nfdlist > 0) for (i = 0; i < nfdlist; i++) VIR_FORCE_CLOSE(fdlist[i]); VIR_FREE(fdlist); virConfFree(conf); if (dom) virDomainFree(dom); if (conn) virConnectClose(conn); virStringFreeList(shargv); VIR_FREE(name); VIR_FREE(homedir); VIR_FREE(seclabel); VIR_FREE(secmodel); VIR_FREE(groups); if (virProcessWait(cpid, &status, true) == 0) virProcessExitWithStatus(status); if (virGetLastError()) virDispatchError(NULL); return ret; }